From patchwork Mon Jul 29 04:49:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 262668 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 14D5C2C0106 for ; Mon, 29 Jul 2013 14:50:10 +1000 (EST) Received: from localhost ([::1]:60307 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3fPM-0005LT-3E for incoming@patchwork.ozlabs.org; Mon, 29 Jul 2013 00:50:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59109) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3fP0-0005HM-N3 for qemu-devel@nongnu.org; Mon, 29 Jul 2013 00:49:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V3fOu-0004NW-GD for qemu-devel@nongnu.org; Mon, 29 Jul 2013 00:49:46 -0400 Received: from mail-pb0-f50.google.com ([209.85.160.50]:35849) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3fOu-0004Ml-7N for qemu-devel@nongnu.org; Mon, 29 Jul 2013 00:49:40 -0400 Received: by mail-pb0-f50.google.com with SMTP id uo5so845220pbc.23 for ; Sun, 28 Jul 2013 21:49:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=0V+m0n2m1rL1WbdR2xbZwfFSE1KUY5p5DHUK64jHGDI=; b=hRbgprUROKYWzjcLPEVu7hkeVDjRUE546Gp3grRsIm30lGUcX7WT6o7aOMbyJ7Epdv CSPvisBqTyfeqk0z/NYGza3opyGbh6VmFh50IGM88dnKO/JgzA6eG5xy/ZxNZnnk+USY ++0p7yBPXK5kRhr0zRRMKtltowYY5/geflgt7tJOtLJXH+dXIcZvVHPiKq2qYICseChq voZqzEiVBpGRkp4JicdFuVGK9GM+qIkuOlESH4c0qbq5MXWD45P0sUZ5bKll18Em988n sDKkLYSNOlPN8J1p9Bm1sHsDJr36T9qJcNqewsNOffy3EzR8gqNLaDxV+NZ4jiUBxXh0 MSkA== X-Received: by 10.68.231.200 with SMTP id ti8mr65288038pbc.46.1375073379188; Sun, 28 Jul 2013 21:49:39 -0700 (PDT) Received: from ka1.ozlabs.ibm.com (ibmaus65.lnk.telstra.net. [165.228.126.9]) by mx.google.com with ESMTPSA id sz6sm18337862pab.5.2013.07.28.21.49.35 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 28 Jul 2013 21:49:37 -0700 (PDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Mon, 29 Jul 2013 14:49:29 +1000 Message-Id: <1375073369-17546-1-git-send-email-aik@ozlabs.ru> X-Mailer: git-send-email 1.8.3.2 X-Gm-Message-State: ALoCoQlS0UsJRELobTu5+PU8kaTApTBB+9LvgxTd3DW0n83uXoDlCkTVixGMGyz0Zu5ctDa9mNzz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.160.50 Cc: Alexey Kardashevskiy , qemu-ppc@nongnu.org, Alexander Graf , Paolo Bonzini Subject: [Qemu-devel] [PATCH v5] spapr-vscsi: add task management 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 At the moment the guest kernel issues two types of task management requests to the hypervisor - task about and lun reset. This adds handling for these tasks. As spapr-vscsi starts calling scsi_req_cancel(), free_request callback was implemented. As virtio-vscsi, spapr-vscsi does not handle CLEAR_ACA either as CDB control byte does not seem to be used at all so NACA bit is not set to the guest so the guest has no good reason to call CLEAR_ACA task. Signed-off-by: Alexey Kardashevskiy --- Changes: 2013/07/29 (v5): * sending response on task management was fixed not to use vscsi_send_rsp() as it is unable to send response data 2013/07/26: * fixed error handling 2013/07/23: * remove unnecessary free_request callback 2013/07/22: * fixed LUN_RESET (it used to clear requests while it should reset a device) * added handling of ABORT_TASK_SET/CLEAR_TASK_SET Signed-off-by: Alexey Kardashevskiy --- hw/scsi/spapr_vscsi.c | 117 ++++++++++++++++++++++++++++++++++++++------------ hw/scsi/srp.h | 7 +++ 2 files changed, 96 insertions(+), 28 deletions(-) diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index 541ffcc..8e49d0d 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -118,6 +118,20 @@ static struct vscsi_req *vscsi_get_req(VSCSIState *s) return NULL; } +static struct vscsi_req *vscsi_find_req(VSCSIState *s, uint64_t srp_tag) +{ + vscsi_req *req; + int i; + + for (i = 0; i < VSCSI_REQ_LIMIT; i++) { + req = &s->reqs[i]; + if (req->iu.srp.cmd.tag == srp_tag) { + return req; + } + } + return NULL; +} + static void vscsi_put_req(vscsi_req *req) { if (req->sreq != NULL) { @@ -654,40 +668,87 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req) static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req) { union viosrp_iu *iu = &req->iu; - int fn; + vscsi_req *tmpreq; + int i, lun = 0, resp = SRP_TSK_MGMT_COMPLETE; + SCSIDevice *d; + uint64_t tag = iu->srp.rsp.tag; + uint8_t sol_not = iu->srp.cmd.sol_not; fprintf(stderr, "vscsi_process_tsk_mgmt %02x\n", iu->srp.tsk_mgmt.tsk_mgmt_func); - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { -#if 0 /* We really don't deal with these for now */ - case SRP_TSK_ABORT_TASK: - fn = ABORT_TASK; - break; - case SRP_TSK_ABORT_TASK_SET: - fn = ABORT_TASK_SET; - break; - case SRP_TSK_CLEAR_TASK_SET: - fn = CLEAR_TASK_SET; - break; - case SRP_TSK_LUN_RESET: - fn = LOGICAL_UNIT_RESET; - break; - case SRP_TSK_CLEAR_ACA: - fn = CLEAR_ACA; - break; -#endif - default: - fn = 0; - } - if (fn) { - /* XXX Send/Handle target task management */ - ; + d = vscsi_device_find(&s->bus, be64_to_cpu(req->iu.srp.tsk_mgmt.lun), &lun); + if (!d) { + resp = SRP_TSK_MGMT_FIELDS_INVALID; } else { - vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x20, 0); - vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0); + switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { + case SRP_TSK_ABORT_TASK: + if (d->lun != lun) { + resp = SRP_TSK_MGMT_FIELDS_INVALID; + break; + } + + tmpreq = vscsi_find_req(s, req->iu.srp.tsk_mgmt.task_tag); + if (tmpreq && tmpreq->sreq) { + assert(tmpreq->sreq->hba_private); + scsi_req_cancel(tmpreq->sreq); + } + break; + + case SRP_TSK_LUN_RESET: + if (d->lun != lun) { + resp = SRP_TSK_MGMT_FIELDS_INVALID; + break; + } + + qdev_reset_all(&d->qdev); + break; + + case SRP_TSK_ABORT_TASK_SET: + case SRP_TSK_CLEAR_TASK_SET: + if (d->lun != lun) { + resp = SRP_TSK_MGMT_FIELDS_INVALID; + break; + } + + for (i = 0; i < VSCSI_REQ_LIMIT; i++) { + tmpreq = &s->reqs[i]; + if (tmpreq->iu.srp.cmd.lun != req->iu.srp.tsk_mgmt.lun) { + continue; + } + if (!tmpreq->active || !tmpreq->sreq) { + continue; + } + assert(tmpreq->sreq->hba_private); + scsi_req_cancel(tmpreq->sreq); + } + break; + + case SRP_TSK_CLEAR_ACA: + resp = SRP_TSK_MGMT_NOT_SUPPORTED; + break; + + default: + resp = SRP_TSK_MGMT_FIELDS_INVALID; + break; + } } - return !fn; + + /* Compose the response here as */ + memset(iu, 0, sizeof(struct srp_rsp) + 4); + iu->srp.rsp.opcode = SRP_RSP; + iu->srp.rsp.req_lim_delta = cpu_to_be32(1); + iu->srp.rsp.tag = tag; + iu->srp.rsp.flags |= SRP_RSP_FLAG_RSPVALID; + iu->srp.rsp.resp_data_len = cpu_to_be32(4); + /* Copy UCSOLNT bit as SRP_RSP_FLAG_RSPVALID is set */ + iu->srp.rsp.sol_not = (sol_not & 0x04) >> 1; + iu->srp.rsp.status = GOOD; + iu->srp.rsp.data[3] = resp; + + vscsi_send_iu(s, req, sizeof(iu->srp.rsp) + 4, VIOSRP_SRP_FORMAT); + + return 1; } static int vscsi_handle_srp_req(VSCSIState *s, vscsi_req *req) diff --git a/hw/scsi/srp.h b/hw/scsi/srp.h index 5e0cad5..d27f31d 100644 --- a/hw/scsi/srp.h +++ b/hw/scsi/srp.h @@ -90,6 +90,13 @@ enum { SRP_REV16A_IB_IO_CLASS = 0x0100 }; +enum { + SRP_TSK_MGMT_COMPLETE = 0x00, + SRP_TSK_MGMT_FIELDS_INVALID = 0x02, + SRP_TSK_MGMT_NOT_SUPPORTED = 0x04, + SRP_TSK_MGMT_FAILED = 0x05 +}; + struct srp_direct_buf { uint64_t va; uint32_t key;