From patchwork Mon Mar 17 05:33:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Nicholas A. Bellinger" X-Patchwork-Id: 3841361 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C2D59BF540 for ; Mon, 17 Mar 2014 05:56:18 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B9C77201C0 for ; Mon, 17 Mar 2014 05:56:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A526A201B4 for ; Mon, 17 Mar 2014 05:56:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756283AbaCQFzs (ORCPT ); Mon, 17 Mar 2014 01:55:48 -0400 Received: from mail-ob0-f175.google.com ([209.85.214.175]:59074 "EHLO mail-ob0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756227AbaCQFzp (ORCPT ); Mon, 17 Mar 2014 01:55:45 -0400 Received: by mail-ob0-f175.google.com with SMTP id uy5so5071208obc.34 for ; Sun, 16 Mar 2014 22:55:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=u56fT8bKUEmQr2uV4a6rJFb4kFGG+5ExWM3hRbGOlvg=; b=HydAmEl15KgTeVd9qoJLnhZPQAbdDoHfl6fRyXLMuiKo/akCAKqCAedShPcKb9qLty 4qvUMylyGPot0DpyR20eZONJMA6NIwhAdyGTmRHdp+VhtnT37TCpxpX9aCRPwIW9ff+p l6oIA4XtSkRW1TU3bqi+1sczulLiYnOmyFDz2eIsMIdpshY5sP5+TzxqOBN731chputV YtdwxuUnIOylaNBJL5gY2uQxtG8d68oJxf/CQbNVj3xqd5Z6DS0eetIAen0QRoG8R32+ v72xppPUM4uxDQ6d8N9bTiC6AAGzh7XOwnmg55YA/tja4aR/JLxvhfIQLUa1HdCN6uCI b+vA== X-Gm-Message-State: ALoCoQkSfHmxr273ORbg7whkdrZe3o7RDFHKGVZjlGjc9LAGctF7fUL1gFAeq9AaKdNR2uC+Boro X-Received: by 10.60.46.98 with SMTP id u2mr19307436oem.44.1395035744565; Sun, 16 Mar 2014 22:55:44 -0700 (PDT) Received: from localhost.localdomain (mail.linux-iscsi.org. [67.23.28.174]) by mx.google.com with ESMTPSA id f9sm4915749obm.2.2014.03.16.22.55.43 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 16 Mar 2014 22:55:43 -0700 (PDT) From: "Nicholas A. Bellinger" To: target-devel Cc: linux-scsi , linux-kernel , kvm-devel , "Michael S. Tsirkin" , Paolo Bonzini , "Martin K. Petersen" , Christoph Hellwig , Hannes Reinecke , Sagi Grimberg , "H. Peter Anvin" , Nicholas Bellinger , Sagi Grimberg Subject: [RFCv2 7/7] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD Date: Mon, 17 Mar 2014 05:33:01 +0000 Message-Id: <1395034381-656-8-git-send-email-nab@daterainc.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1395034381-656-1-git-send-email-nab@daterainc.com> References: <1395034381-656-1-git-send-email-nab@daterainc.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Nicholas Bellinger This patch updates virtscsi_probe() to setup necessary Scsi_Host level protection resources. (currently hardcoded to 1) It changes virtscsi_add_cmd() to attach outgoing / incoming protection SGLs preceeding the data payload, and is using the new virtio_scsi_cmd_req_pi->d[oi],pi_niv field to signal to signal to vhost/scsi how many prot_sgs to expect. v2 changes: - Make protection buffer come before data buffer (Paolo) - Enable virtio_scsi_cmd_req_pi usage (Paolo) Cc: Paolo Bonzini Cc: Michael S. Tsirkin Cc: Martin K. Petersen Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Sagi Grimberg Cc: H. Peter Anvin Signed-off-by: Nicholas Bellinger --- drivers/scsi/virtio_scsi.c | 79 ++++++++++++++++++++++++++++++++++---------- 1 files changed, 61 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 16bfd50..4cccfed 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -37,6 +37,7 @@ struct virtio_scsi_cmd { struct completion *comp; union { struct virtio_scsi_cmd_req cmd; + struct virtio_scsi_cmd_req_pi cmd_pi; struct virtio_scsi_ctrl_tmf_req tmf; struct virtio_scsi_ctrl_an_req an; } req; @@ -440,7 +441,7 @@ static int virtscsi_add_cmd(struct virtqueue *vq, size_t req_size, size_t resp_size, gfp_t gfp) { struct scsi_cmnd *sc = cmd->sc; - struct scatterlist *sgs[4], req, resp; + struct scatterlist *sgs[6], req, resp; struct sg_table *out, *in; unsigned out_num = 0, in_num = 0; @@ -458,16 +459,24 @@ static int virtscsi_add_cmd(struct virtqueue *vq, sgs[out_num++] = &req; /* Data-out buffer. */ - if (out) + if (out) { + /* Place WRITE protection SGLs before Data OUT payload */ + if (scsi_prot_sg_count(sc)) + sgs[out_num++] = scsi_prot_sglist(sc); sgs[out_num++] = out->sgl; + } /* Response header. */ sg_init_one(&resp, &cmd->resp, resp_size); sgs[out_num + in_num++] = &resp; /* Data-in buffer */ - if (in) + if (in) { + /* Place READ protection SGLs before Data IN payload */ + if (scsi_prot_sg_count(sc)) + sgs[out_num + in_num++] = scsi_prot_sglist(sc); sgs[out_num + in_num++] = in->sgl; + } return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp); } @@ -492,12 +501,36 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, return err; } +static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd, + struct scsi_cmnd *sc) +{ + cmd->lun[0] = 1; + cmd->lun[1] = sc->device->id; + cmd->lun[2] = (sc->device->lun >> 8) | 0x40; + cmd->lun[3] = sc->device->lun & 0xff; + cmd->tag = (unsigned long)sc; + cmd->task_attr = VIRTIO_SCSI_S_SIMPLE; + cmd->prio = 0; + cmd->crn = 0; +} + +static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi, + struct scsi_cmnd *sc) +{ + virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc); + + if (sc->sc_data_direction == DMA_TO_DEVICE) + cmd_pi->do_pi_niov = scsi_prot_sg_count(sc); + else if (sc->sc_data_direction == DMA_FROM_DEVICE) + cmd_pi->di_pi_niov = scsi_prot_sg_count(sc); +} + static int virtscsi_queuecommand(struct virtio_scsi *vscsi, struct virtio_scsi_vq *req_vq, struct scsi_cmnd *sc) { struct virtio_scsi_cmd *cmd; - int ret; + int ret, req_size; struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); @@ -515,22 +548,20 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, memset(cmd, 0, sizeof(*cmd)); cmd->sc = sc; - cmd->req.cmd = (struct virtio_scsi_cmd_req){ - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - .tag = (unsigned long)sc, - .task_attr = VIRTIO_SCSI_S_SIMPLE, - .prio = 0, - .crn = 0, - }; BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); - memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); - if (virtscsi_kick_cmd(req_vq, cmd, - sizeof cmd->req.cmd, sizeof cmd->resp.cmd, + if (scsi_prot_sg_count(sc)) { + virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc); + memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len); + req_size = sizeof(cmd->req.cmd_pi); + } else { + virtio_scsi_init_hdr(&cmd->req.cmd, sc); + memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); + req_size = sizeof(cmd->req.cmd); + } + + if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd), GFP_ATOMIC) == 0) ret = 0; else @@ -871,7 +902,7 @@ static int virtscsi_probe(struct virtio_device *vdev) { struct Scsi_Host *shost; struct virtio_scsi *vscsi; - int err; + int err, host_prot; u32 sg_elems, num_targets; u32 cmd_per_lun; u32 num_queues; @@ -921,6 +952,17 @@ static int virtscsi_probe(struct virtio_device *vdev) shost->max_id = num_targets; shost->max_channel = 0; shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; + + /* FIXME: Figure out why this is broken.. */ + if (1 || virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { + host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | + SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | + SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; + + scsi_host_set_prot(shost, host_prot); + scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); + } + err = scsi_add_host(shost, &vdev->dev); if (err) goto scsi_add_host_failed; @@ -990,6 +1032,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_SCSI_F_HOTPLUG, VIRTIO_SCSI_F_CHANGE, + VIRTIO_SCSI_F_T10_PI, }; static struct virtio_driver virtio_scsi_driver = {