From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56714) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VnXec-0004HV-C2 for qemu-devel@nongnu.org; Mon, 02 Dec 2013 12:51:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VnXeW-0000WC-Ai for qemu-devel@nongnu.org; Mon, 02 Dec 2013 12:51:30 -0500 Received: from trout.icecube.wisc.edu ([128.104.255.119]:36820 helo=mail.icecube.wisc.edu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VnXeW-0000UQ-3R for qemu-devel@nongnu.org; Mon, 02 Dec 2013 12:51:24 -0500 Message-ID: <529CC896.5020304@freebsd.org> Date: Mon, 02 Dec 2013 11:51:18 -0600 From: Nathan Whitehorn MIME-Version: 1.0 References: <1382099622-87967-1-git-send-email-nwhitehorn@freebsd.org> In-Reply-To: <1382099622-87967-1-git-send-email-nwhitehorn@freebsd.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH] spapr_vscsi: Fix REPORT_LUNS handling List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com Any news on this? FreeBSD is unbootable from CDROM devices in QEMU/pseries without this patch. -Nathan On 10/18/13 07:33, Nathan Whitehorn wrote: > Intercept REPORT_LUNS commands addressed either to SRP LUN 0 or the well-known > LUN for REPORT_LUNS commands. This is required to implement the SAM and SPC > specifications. > > Since SRP implements only a single SCSI target port per connection, the SRP > target is required to report all available LUNs in response to a REPORT_LUNS > command addressed either to LUN 0 or the well-known LUN. Instead, QEMU was > forwarding such requests to the first QEMU SCSI target, with the result that > initiators that relied on this feature would only see LUNs on the first QEMU > SCSI target. > > Behavior for REPORT_LUNS commands addressed to any other LUN is not specified > by the standard and so is left unchanged. This preserves behavior under Linux > and SLOF, which enumerate possible LUNs by hand and so address no commands > either to LUN 0 or the well-known REPORT_LUNS LUN. > > Signed-off-by: Nathan Whitehorn > --- > hw/scsi/spapr_vscsi.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 57 insertions(+) > > diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c > index 2a26042..87e0fb3 100644 > --- a/hw/scsi/spapr_vscsi.c > +++ b/hw/scsi/spapr_vscsi.c > @@ -63,6 +63,8 @@ > #define SCSI_SENSE_BUF_SIZE 96 > #define SRP_RSP_SENSE_DATA_LEN 18 > > +#define SRP_REPORT_LUNS_WLUN 0xc10100000000000 > + > typedef union vscsi_crq { > struct viosrp_crq s; > uint8_t raw[16]; > @@ -720,12 +722,67 @@ static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req) > } > } > > +static void vscsi_report_luns(VSCSIState *s, vscsi_req *req) > +{ > + BusChild *kid; > + int i, len, n, rc; > + uint8_t *resp_data; > + bool found_lun0; > + > + n = 0; > + found_lun0 = false; > + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { > + SCSIDevice *dev = SCSI_DEVICE(kid->child); > + > + n += 8; > + if (dev->channel == 0 && dev->id == 0 && dev->lun == 0) > + found_lun0 = true; > + } > + if (!found_lun0) { > + n += 8; > + } > + len = n+8; > + > + resp_data = malloc(len); > + memset(resp_data, 0, len); > + stl_be_p(resp_data, n); > + i = found_lun0 ? 8 : 16; > + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { > + DeviceState *qdev = kid->child; > + SCSIDevice *dev = SCSI_DEVICE(qdev); > + > + if (dev->id == 0 && dev->channel == 0) > + resp_data[i] = 0; > + else > + resp_data[i] = (2 << 6); > + resp_data[i] |= dev->id; > + resp_data[i+1] = (dev->channel << 5); > + resp_data[i+1] |= dev->lun; > + i += 8; > + } > + > + vscsi_preprocess_desc(req); > + rc = vscsi_srp_transfer_data(s, req, 0, resp_data, len); > + free(resp_data); > + if (rc < 0) { > + vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0); > + vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0); > + } else { > + vscsi_send_rsp(s, req, 0, len - rc, 0); > + } > +} > + > static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req) > { > union srp_iu *srp = &req->iu.srp; > SCSIDevice *sdev; > int n, lun; > > + if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN) && srp->cmd.cdb[0] == REPORT_LUNS) { > + vscsi_report_luns(s, req); > + return 0; > + } > + > sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun); > if (!sdev) { > DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",