From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IxMrw-0000oN-CF for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:24 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IxMru-0000nb-VV for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:23 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IxMru-0000nT-Iv for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:22 -0500 Received: from ecfrec.frec.bull.fr ([129.183.4.8]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IxMrt-0001Pe-Qp for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:22 -0500 Received: from localhost (localhost [127.0.0.1]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id B11AA19D9F0 for ; Wed, 28 Nov 2007 14:21:45 +0100 (CET) Received: from ecfrec.frec.bull.fr ([127.0.0.1]) by localhost (ecfrec.frec.bull.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 13295-09 for ; Wed, 28 Nov 2007 14:21:42 +0100 (CET) Received: from ecn002.frec.bull.fr (ecn002.frec.bull.fr [129.183.4.6]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 953B319D9F9 for ; Wed, 28 Nov 2007 14:21:37 +0100 (CET) In-Reply-To: <11962562201796@bull.net> Date: Wed, 28 Nov 2007 14:23:41 +0100 Message-Id: <11962562212582@bull.net> Mime-Version: 1.0 From: Laurent Vivier Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Subject: [Qemu-devel] [PATCH 3/3] SG support (Asynchronous Send Command) Reply-To: Laurent Vivier , qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org This patch modifies scsi_send_command() to use asynchronous I/O with SCSI Generic. This allows to use command with data transfers that are not immediate. Old behavior can generate softlockup in the guest kernel. hw/lsi53c895a.c has been modified to manage this new behavior. --- hw/lsi53c895a.c | 25 ++++++++++++++++++------- hw/scsi-generic.c | 3 +-- 2 files changed, 19 insertions(+), 9 deletions(-) Index: qemu/hw/lsi53c895a.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu.orig/hw/lsi53c895a.c 2007-11-28 13:12:22.000000000 +0100 +++ qemu/hw/lsi53c895a.c 2007-11-28 13:13:42.000000000 +0100 @@ -187,6 +187,7 @@ typedef struct { /* The tag is a combination of the device ID and the SCSI tag. */ uint32_t current_tag; uint32_t current_dma_len; + int command_complete; uint8_t *dma_buf; lsi_queue *queue; int queue_len; @@ -597,6 +598,7 @@ static void lsi_command_complete(void *o if (reason =3D=3D SCSI_REASON_DONE) { DPRINTF("Command complete sense=3D%d\n", (int)arg); s->sense =3D arg; + s->command_complete =3D 2; if (s->waiting && s->dbc !=3D 0) { /* Raise phase mismatch for short transfers. */ lsi_bad_phase(s, out, PHASE_ST); @@ -613,6 +615,7 @@ static void lsi_command_complete(void *o } DPRINTF("Data ready tag=3D0x%x len=3D%d\n", tag, arg); s->current_dma_len =3D arg; + s->command_complete =3D 1; if (!s->waiting) return; if (s->waiting =3D=3D 1 || s->dbc =3D=3D 0) { @@ -632,6 +635,7 @@ static void lsi_do_command(LSIState *s) s->dbc =3D 16; cpu_physical_memory_read(s->dnad, buf, s->dbc); s->sfbr =3D buf[0]; + s->command_complete =3D 0; n =3D s->current_dev->send_command(s->current_dev, s->current_tag, buf, s->current_lun); if (n > 0) { @@ -641,13 +645,20 @@ static void lsi_do_command(LSIState *s) lsi_set_phase(s, PHASE_DO); s->current_dev->write_data(s->current_dev, s->current_tag); } - if (n && s->current_dma_len =3D=3D 0) { - /* Command did not complete immediately so disconnect. */ - lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */ - lsi_add_msg_byte(s, 4); /* DISCONNECT */ - lsi_set_phase(s, PHASE_MI); - s->msg_action =3D 1; - lsi_queue_command(s); + + if (!s->command_complete) { + if (n) { + /* Command did not complete immediately so disconnect. */ + lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */ + lsi_add_msg_byte(s, 4); /* DISCONNECT */ + /* wait data */ + lsi_set_phase(s, PHASE_MI); + s->msg_action =3D 1; + lsi_queue_command(s); + } else { + /* wait command complete */ + lsi_set_phase(s, PHASE_DI); + } } } =20 Index: qemu/hw/scsi-generic.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu.orig/hw/scsi-generic.c 2007-11-28 13:13:13.000000000 +0100 +++ qemu/hw/scsi-generic.c 2007-11-28 13:13:42.000000000 +0100 @@ -496,12 +496,11 @@ static int32_t scsi_send_command(SCSIDev free(r->buf); r->buflen =3D 0; r->buf =3D NULL; - ret =3D execute_command(s->bdrv, r, SG_DXFER_NONE, NULL); + ret =3D execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_co= mplete); if (ret =3D=3D -1) { scsi_command_complete(r, -EINVAL); return 0; } - scsi_command_complete(r, scsi_get_sense(r)); return 0; } =20