From patchwork Fri Oct 18 12:33:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Whitehorn X-Patchwork-Id: 284584 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4BB022C00B1 for ; Sat, 19 Oct 2013 00:34:57 +1100 (EST) Received: from localhost ([::1]:57754 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXACd-00075L-EO for incoming@patchwork.ozlabs.org; Fri, 18 Oct 2013 09:34:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35053) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXACO-00075G-5c for qemu-devel@nongnu.org; Fri, 18 Oct 2013 09:34:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VXACM-0002ze-Sj for qemu-devel@nongnu.org; Fri, 18 Oct 2013 09:34:40 -0400 Received: from comporellon.tachypleus.net ([2001:4978:137:1:230:48ff:fed5:7b70]:61844) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXACM-0002wz-HO for qemu-devel@nongnu.org; Fri, 18 Oct 2013 09:34:38 -0400 Received: from comporellon.tachypleus.net (smmsp@localhost [127.0.0.1]) by comporellon.tachypleus.net (8.14.7/8.14.7) with ESMTP id r9ICibpf088023; Fri, 18 Oct 2013 07:46:27 -0500 (CDT) (envelope-from nwhitehorn@comporellon.tachypleus.net) Received: (from nwhitehorn@localhost) by comporellon.tachypleus.net (8.14.7/8.14.7/Submit) id r9ICXvmH088005; Fri, 18 Oct 2013 07:33:57 -0500 (CDT) (envelope-from nwhitehorn) From: Nathan Whitehorn To: qemu-devel@nongnu.org Date: Fri, 18 Oct 2013 07:33:42 -0500 Message-Id: <1382099622-87967-1-git-send-email-nwhitehorn@freebsd.org> X-Mailer: git-send-email 1.8.4 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:4978:137:1:230:48ff:fed5:7b70 Cc: pbonzini@redhat.com, Nathan Whitehorn Subject: [Qemu-devel] [PATCH] spapr_vscsi: Fix REPORT_LUNS handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Acked-by: Paolo Bonzini --- 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",