aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/virtio_scsi.c87
2 files changed, 70 insertions, 18 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 02832d64d918..baca5897039f 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1773,6 +1773,7 @@ config SCSI_BFA_FC
1773config SCSI_VIRTIO 1773config SCSI_VIRTIO
1774 tristate "virtio-scsi support" 1774 tristate "virtio-scsi support"
1775 depends on VIRTIO 1775 depends on VIRTIO
1776 select BLK_DEV_INTEGRITY
1776 help 1777 help
1777 This is the virtual HBA driver for virtio. If the kernel will 1778 This is the virtual HBA driver for virtio. If the kernel will
1778 be used in a virtual machine, say Y or M. 1779 be used in a virtual machine, say Y or M.
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 16bfd50cd3fe..1c326b63ca55 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -23,6 +23,7 @@
23#include <linux/virtio_config.h> 23#include <linux/virtio_config.h>
24#include <linux/virtio_scsi.h> 24#include <linux/virtio_scsi.h>
25#include <linux/cpu.h> 25#include <linux/cpu.h>
26#include <linux/blkdev.h>
26#include <scsi/scsi_host.h> 27#include <scsi/scsi_host.h>
27#include <scsi/scsi_device.h> 28#include <scsi/scsi_device.h>
28#include <scsi/scsi_cmnd.h> 29#include <scsi/scsi_cmnd.h>
@@ -37,6 +38,7 @@ struct virtio_scsi_cmd {
37 struct completion *comp; 38 struct completion *comp;
38 union { 39 union {
39 struct virtio_scsi_cmd_req cmd; 40 struct virtio_scsi_cmd_req cmd;
41 struct virtio_scsi_cmd_req_pi cmd_pi;
40 struct virtio_scsi_ctrl_tmf_req tmf; 42 struct virtio_scsi_ctrl_tmf_req tmf;
41 struct virtio_scsi_ctrl_an_req an; 43 struct virtio_scsi_ctrl_an_req an;
42 } req; 44 } req;
@@ -440,7 +442,7 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
440 size_t req_size, size_t resp_size, gfp_t gfp) 442 size_t req_size, size_t resp_size, gfp_t gfp)
441{ 443{
442 struct scsi_cmnd *sc = cmd->sc; 444 struct scsi_cmnd *sc = cmd->sc;
443 struct scatterlist *sgs[4], req, resp; 445 struct scatterlist *sgs[6], req, resp;
444 struct sg_table *out, *in; 446 struct sg_table *out, *in;
445 unsigned out_num = 0, in_num = 0; 447 unsigned out_num = 0, in_num = 0;
446 448
@@ -458,16 +460,24 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
458 sgs[out_num++] = &req; 460 sgs[out_num++] = &req;
459 461
460 /* Data-out buffer. */ 462 /* Data-out buffer. */
461 if (out) 463 if (out) {
464 /* Place WRITE protection SGLs before Data OUT payload */
465 if (scsi_prot_sg_count(sc))
466 sgs[out_num++] = scsi_prot_sglist(sc);
462 sgs[out_num++] = out->sgl; 467 sgs[out_num++] = out->sgl;
468 }
463 469
464 /* Response header. */ 470 /* Response header. */
465 sg_init_one(&resp, &cmd->resp, resp_size); 471 sg_init_one(&resp, &cmd->resp, resp_size);
466 sgs[out_num + in_num++] = &resp; 472 sgs[out_num + in_num++] = &resp;
467 473
468 /* Data-in buffer */ 474 /* Data-in buffer */
469 if (in) 475 if (in) {
476 /* Place READ protection SGLs before Data IN payload */
477 if (scsi_prot_sg_count(sc))
478 sgs[out_num + in_num++] = scsi_prot_sglist(sc);
470 sgs[out_num + in_num++] = in->sgl; 479 sgs[out_num + in_num++] = in->sgl;
480 }
471 481
472 return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp); 482 return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp);
473} 483}
@@ -492,12 +502,44 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
492 return err; 502 return err;
493} 503}
494 504
505static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd,
506 struct scsi_cmnd *sc)
507{
508 cmd->lun[0] = 1;
509 cmd->lun[1] = sc->device->id;
510 cmd->lun[2] = (sc->device->lun >> 8) | 0x40;
511 cmd->lun[3] = sc->device->lun & 0xff;
512 cmd->tag = (unsigned long)sc;
513 cmd->task_attr = VIRTIO_SCSI_S_SIMPLE;
514 cmd->prio = 0;
515 cmd->crn = 0;
516}
517
518static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi,
519 struct scsi_cmnd *sc)
520{
521 struct request *rq = sc->request;
522 struct blk_integrity *bi;
523
524 virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc);
525
526 if (!rq || !scsi_prot_sg_count(sc))
527 return;
528
529 bi = blk_get_integrity(rq->rq_disk);
530
531 if (sc->sc_data_direction == DMA_TO_DEVICE)
532 cmd_pi->pi_bytesout = blk_rq_sectors(rq) * bi->tuple_size;
533 else if (sc->sc_data_direction == DMA_FROM_DEVICE)
534 cmd_pi->pi_bytesin = blk_rq_sectors(rq) * bi->tuple_size;
535}
536
495static int virtscsi_queuecommand(struct virtio_scsi *vscsi, 537static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
496 struct virtio_scsi_vq *req_vq, 538 struct virtio_scsi_vq *req_vq,
497 struct scsi_cmnd *sc) 539 struct scsi_cmnd *sc)
498{ 540{
499 struct virtio_scsi_cmd *cmd; 541 struct virtio_scsi_cmd *cmd;
500 int ret; 542 int ret, req_size;
501 543
502 struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); 544 struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
503 BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); 545 BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
@@ -515,22 +557,20 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
515 557
516 memset(cmd, 0, sizeof(*cmd)); 558 memset(cmd, 0, sizeof(*cmd));
517 cmd->sc = sc; 559 cmd->sc = sc;
518 cmd->req.cmd = (struct virtio_scsi_cmd_req){
519 .lun[0] = 1,
520 .lun[1] = sc->device->id,
521 .lun[2] = (sc->device->lun >> 8) | 0x40,
522 .lun[3] = sc->device->lun & 0xff,
523 .tag = (unsigned long)sc,
524 .task_attr = VIRTIO_SCSI_S_SIMPLE,
525 .prio = 0,
526 .crn = 0,
527 };
528 560
529 BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); 561 BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
530 memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
531 562
532 if (virtscsi_kick_cmd(req_vq, cmd, 563 if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) {
533 sizeof cmd->req.cmd, sizeof cmd->resp.cmd, 564 virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc);
565 memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len);
566 req_size = sizeof(cmd->req.cmd_pi);
567 } else {
568 virtio_scsi_init_hdr(&cmd->req.cmd, sc);
569 memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
570 req_size = sizeof(cmd->req.cmd);
571 }
572
573 if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd),
534 GFP_ATOMIC) == 0) 574 GFP_ATOMIC) == 0)
535 ret = 0; 575 ret = 0;
536 else 576 else
@@ -871,7 +911,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
871{ 911{
872 struct Scsi_Host *shost; 912 struct Scsi_Host *shost;
873 struct virtio_scsi *vscsi; 913 struct virtio_scsi *vscsi;
874 int err; 914 int err, host_prot;
875 u32 sg_elems, num_targets; 915 u32 sg_elems, num_targets;
876 u32 cmd_per_lun; 916 u32 cmd_per_lun;
877 u32 num_queues; 917 u32 num_queues;
@@ -921,6 +961,16 @@ static int virtscsi_probe(struct virtio_device *vdev)
921 shost->max_id = num_targets; 961 shost->max_id = num_targets;
922 shost->max_channel = 0; 962 shost->max_channel = 0;
923 shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; 963 shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE;
964
965 if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) {
966 host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
967 SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION |
968 SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION;
969
970 scsi_host_set_prot(shost, host_prot);
971 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
972 }
973
924 err = scsi_add_host(shost, &vdev->dev); 974 err = scsi_add_host(shost, &vdev->dev);
925 if (err) 975 if (err)
926 goto scsi_add_host_failed; 976 goto scsi_add_host_failed;
@@ -990,6 +1040,7 @@ static struct virtio_device_id id_table[] = {
990static unsigned int features[] = { 1040static unsigned int features[] = {
991 VIRTIO_SCSI_F_HOTPLUG, 1041 VIRTIO_SCSI_F_HOTPLUG,
992 VIRTIO_SCSI_F_CHANGE, 1042 VIRTIO_SCSI_F_CHANGE,
1043 VIRTIO_SCSI_F_T10_PI,
993}; 1044};
994 1045
995static struct virtio_driver virtio_scsi_driver = { 1046static struct virtio_driver virtio_scsi_driver = {