aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/virtio_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r--drivers/scsi/virtio_scsi.c86
1 files changed, 69 insertions, 17 deletions
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 99fdb9403944..89ee5929eb6d 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;
@@ -399,7 +401,7 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
399 size_t req_size, size_t resp_size) 401 size_t req_size, size_t resp_size)
400{ 402{
401 struct scsi_cmnd *sc = cmd->sc; 403 struct scsi_cmnd *sc = cmd->sc;
402 struct scatterlist *sgs[4], req, resp; 404 struct scatterlist *sgs[6], req, resp;
403 struct sg_table *out, *in; 405 struct sg_table *out, *in;
404 unsigned out_num = 0, in_num = 0; 406 unsigned out_num = 0, in_num = 0;
405 407
@@ -417,16 +419,24 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
417 sgs[out_num++] = &req; 419 sgs[out_num++] = &req;
418 420
419 /* Data-out buffer. */ 421 /* Data-out buffer. */
420 if (out) 422 if (out) {
423 /* Place WRITE protection SGLs before Data OUT payload */
424 if (scsi_prot_sg_count(sc))
425 sgs[out_num++] = scsi_prot_sglist(sc);
421 sgs[out_num++] = out->sgl; 426 sgs[out_num++] = out->sgl;
427 }
422 428
423 /* Response header. */ 429 /* Response header. */
424 sg_init_one(&resp, &cmd->resp, resp_size); 430 sg_init_one(&resp, &cmd->resp, resp_size);
425 sgs[out_num + in_num++] = &resp; 431 sgs[out_num + in_num++] = &resp;
426 432
427 /* Data-in buffer */ 433 /* Data-in buffer */
428 if (in) 434 if (in) {
435 /* Place READ protection SGLs before Data IN payload */
436 if (scsi_prot_sg_count(sc))
437 sgs[out_num + in_num++] = scsi_prot_sglist(sc);
429 sgs[out_num + in_num++] = in->sgl; 438 sgs[out_num + in_num++] = in->sgl;
439 }
430 440
431 return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); 441 return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC);
432} 442}
@@ -451,12 +461,45 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
451 return err; 461 return err;
452} 462}
453 463
464static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd,
465 struct scsi_cmnd *sc)
466{
467 cmd->lun[0] = 1;
468 cmd->lun[1] = sc->device->id;
469 cmd->lun[2] = (sc->device->lun >> 8) | 0x40;
470 cmd->lun[3] = sc->device->lun & 0xff;
471 cmd->tag = (unsigned long)sc;
472 cmd->task_attr = VIRTIO_SCSI_S_SIMPLE;
473 cmd->prio = 0;
474 cmd->crn = 0;
475}
476
477static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi,
478 struct scsi_cmnd *sc)
479{
480 struct request *rq = sc->request;
481 struct blk_integrity *bi;
482
483 virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc);
484
485 if (!rq || !scsi_prot_sg_count(sc))
486 return;
487
488 bi = blk_get_integrity(rq->rq_disk);
489
490 if (sc->sc_data_direction == DMA_TO_DEVICE)
491 cmd_pi->pi_bytesout = blk_rq_sectors(rq) * bi->tuple_size;
492 else if (sc->sc_data_direction == DMA_FROM_DEVICE)
493 cmd_pi->pi_bytesin = blk_rq_sectors(rq) * bi->tuple_size;
494}
495
454static int virtscsi_queuecommand(struct virtio_scsi *vscsi, 496static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
455 struct virtio_scsi_vq *req_vq, 497 struct virtio_scsi_vq *req_vq,
456 struct scsi_cmnd *sc) 498 struct scsi_cmnd *sc)
457{ 499{
458 struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); 500 struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
459 struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); 501 struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
502 int req_size;
460 503
461 BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); 504 BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
462 505
@@ -468,22 +511,20 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
468 511
469 memset(cmd, 0, sizeof(*cmd)); 512 memset(cmd, 0, sizeof(*cmd));
470 cmd->sc = sc; 513 cmd->sc = sc;
471 cmd->req.cmd = (struct virtio_scsi_cmd_req){
472 .lun[0] = 1,
473 .lun[1] = sc->device->id,
474 .lun[2] = (sc->device->lun >> 8) | 0x40,
475 .lun[3] = sc->device->lun & 0xff,
476 .tag = (unsigned long)sc,
477 .task_attr = VIRTIO_SCSI_S_SIMPLE,
478 .prio = 0,
479 .crn = 0,
480 };
481 514
482 BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); 515 BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
483 memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
484 516
485 if (virtscsi_kick_cmd(req_vq, cmd, 517 if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) {
486 sizeof cmd->req.cmd, sizeof cmd->resp.cmd) != 0) 518 virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc);
519 memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len);
520 req_size = sizeof(cmd->req.cmd_pi);
521 } else {
522 virtio_scsi_init_hdr(&cmd->req.cmd, sc);
523 memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
524 req_size = sizeof(cmd->req.cmd);
525 }
526
527 if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0)
487 return SCSI_MLQUEUE_HOST_BUSY; 528 return SCSI_MLQUEUE_HOST_BUSY;
488 return 0; 529 return 0;
489} 530}
@@ -820,7 +861,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
820{ 861{
821 struct Scsi_Host *shost; 862 struct Scsi_Host *shost;
822 struct virtio_scsi *vscsi; 863 struct virtio_scsi *vscsi;
823 int err; 864 int err, host_prot;
824 u32 sg_elems, num_targets; 865 u32 sg_elems, num_targets;
825 u32 cmd_per_lun; 866 u32 cmd_per_lun;
826 u32 num_queues; 867 u32 num_queues;
@@ -870,6 +911,16 @@ static int virtscsi_probe(struct virtio_device *vdev)
870 shost->max_id = num_targets; 911 shost->max_id = num_targets;
871 shost->max_channel = 0; 912 shost->max_channel = 0;
872 shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; 913 shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE;
914
915 if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) {
916 host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
917 SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION |
918 SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION;
919
920 scsi_host_set_prot(shost, host_prot);
921 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
922 }
923
873 err = scsi_add_host(shost, &vdev->dev); 924 err = scsi_add_host(shost, &vdev->dev);
874 if (err) 925 if (err)
875 goto scsi_add_host_failed; 926 goto scsi_add_host_failed;
@@ -939,6 +990,7 @@ static struct virtio_device_id id_table[] = {
939static unsigned int features[] = { 990static unsigned int features[] = {
940 VIRTIO_SCSI_F_HOTPLUG, 991 VIRTIO_SCSI_F_HOTPLUG,
941 VIRTIO_SCSI_F_CHANGE, 992 VIRTIO_SCSI_F_CHANGE,
993 VIRTIO_SCSI_F_T10_PI,
942}; 994};
943 995
944static struct virtio_driver virtio_scsi_driver = { 996static struct virtio_driver virtio_scsi_driver = {