2323#include <linux/virtio_config.h>
2424#include <linux/virtio_scsi.h>
2525#include <linux/cpu.h>
26+ #include <linux/blkdev.h>
2627#include <scsi/scsi_host.h>
2728#include <scsi/scsi_device.h>
2829#include <scsi/scsi_cmnd.h>
@@ -37,6 +38,7 @@ struct virtio_scsi_cmd {
3738 struct completion * comp ;
3839 union {
3940 struct virtio_scsi_cmd_req cmd ;
41+ struct virtio_scsi_cmd_req_pi cmd_pi ;
4042 struct virtio_scsi_ctrl_tmf_req tmf ;
4143 struct virtio_scsi_ctrl_an_req an ;
4244 } req ;
@@ -440,7 +442,7 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
440442 size_t req_size , size_t resp_size , gfp_t gfp )
441443{
442444 struct scsi_cmnd * sc = cmd -> sc ;
443- struct scatterlist * sgs [4 ], req , resp ;
445+ struct scatterlist * sgs [6 ], req , resp ;
444446 struct sg_table * out , * in ;
445447 unsigned out_num = 0 , in_num = 0 ;
446448
@@ -458,16 +460,24 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
458460 sgs [out_num ++ ] = & req ;
459461
460462 /* 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 );
462467 sgs [out_num ++ ] = out -> sgl ;
468+ }
463469
464470 /* Response header. */
465471 sg_init_one (& resp , & cmd -> resp , resp_size );
466472 sgs [out_num + in_num ++ ] = & resp ;
467473
468474 /* 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 );
470479 sgs [out_num + in_num ++ ] = in -> sgl ;
480+ }
471481
472482 return virtqueue_add_sgs (vq , sgs , out_num , in_num , cmd , gfp );
473483}
@@ -492,12 +502,44 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
492502 return err ;
493503}
494504
505+ static 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+
518+ static 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+
495537static int virtscsi_queuecommand (struct virtio_scsi * vscsi ,
496538 struct virtio_scsi_vq * req_vq ,
497539 struct scsi_cmnd * sc )
498540{
499541 struct virtio_scsi_cmd * cmd ;
500- int ret ;
542+ int ret , req_size ;
501543
502544 struct Scsi_Host * shost = virtio_scsi_host (vscsi -> vdev );
503545 BUG_ON (scsi_sg_count (sc ) > shost -> sg_tablesize );
@@ -515,22 +557,20 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
515557
516558 memset (cmd , 0 , sizeof (* cmd ));
517559 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- };
528560
529561 BUG_ON (sc -> cmd_len > VIRTIO_SCSI_CDB_SIZE );
530- memcpy (cmd -> req .cmd .cdb , sc -> cmnd , sc -> cmd_len );
531562
532- if (virtscsi_kick_cmd (req_vq , cmd ,
533- sizeof cmd -> req .cmd , sizeof cmd -> resp .cmd ,
563+ if (virtio_has_feature (vscsi -> vdev , VIRTIO_SCSI_F_T10_PI )) {
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 ),
534574 GFP_ATOMIC ) == 0 )
535575 ret = 0 ;
536576 else
@@ -871,7 +911,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
871911{
872912 struct Scsi_Host * shost ;
873913 struct virtio_scsi * vscsi ;
874- int err ;
914+ int err , host_prot ;
875915 u32 sg_elems , num_targets ;
876916 u32 cmd_per_lun ;
877917 u32 num_queues ;
@@ -921,6 +961,16 @@ static int virtscsi_probe(struct virtio_device *vdev)
921961 shost -> max_id = num_targets ;
922962 shost -> max_channel = 0 ;
923963 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+
924974 err = scsi_add_host (shost , & vdev -> dev );
925975 if (err )
926976 goto scsi_add_host_failed ;
@@ -990,6 +1040,7 @@ static struct virtio_device_id id_table[] = {
9901040static unsigned int features [] = {
9911041 VIRTIO_SCSI_F_HOTPLUG ,
9921042 VIRTIO_SCSI_F_CHANGE ,
1043+ VIRTIO_SCSI_F_T10_PI ,
9931044};
9941045
9951046static struct virtio_driver virtio_scsi_driver = {
0 commit comments