@@ -430,6 +430,7 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc)
430
430
tgt_priv -> io_throttle_enabled = 0 ;
431
431
tgt_priv -> io_divert = 0 ;
432
432
tgt_priv -> throttle_group = NULL ;
433
+ tgt_priv -> wslen = 0 ;
433
434
if (tgtdev -> host_exposed )
434
435
atomic_set (& tgt_priv -> block_io , 1 );
435
436
}
@@ -1108,6 +1109,18 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
1108
1109
tgtdev -> io_throttle_enabled =
1109
1110
(flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED ) ? 1 : 0 ;
1110
1111
1112
+ switch (flags & MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK ) {
1113
+ case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB :
1114
+ tgtdev -> wslen = MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS ;
1115
+ break ;
1116
+ case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB :
1117
+ tgtdev -> wslen = MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS ;
1118
+ break ;
1119
+ case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT :
1120
+ default :
1121
+ tgtdev -> wslen = 0 ;
1122
+ break ;
1123
+ }
1111
1124
1112
1125
if (tgtdev -> starget && tgtdev -> starget -> hostdata ) {
1113
1126
scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data * )
@@ -1119,6 +1132,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
1119
1132
tgtdev -> io_throttle_enabled ;
1120
1133
if (is_added == true)
1121
1134
atomic_set (& scsi_tgt_priv_data -> block_io , 0 );
1135
+ scsi_tgt_priv_data -> wslen = tgtdev -> wslen ;
1122
1136
}
1123
1137
1124
1138
switch (dev_pg0 -> access_status ) {
@@ -3939,6 +3953,48 @@ void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout)
3939
3953
mpi3mr_get_fw_pending_ios (mrioc ));
3940
3954
}
3941
3955
3956
+ /**
3957
+ * mpi3mr_setup_divert_ws - Setup Divert IO flag for write same
3958
+ * @mrioc: Adapter instance reference
3959
+ * @scmd: SCSI command reference
3960
+ * @scsiio_req: MPI3 SCSI IO request
3961
+ * @scsiio_flags: Pointer to MPI3 SCSI IO Flags
3962
+ * @wslen: write same max length
3963
+ *
3964
+ * Gets values of unmap, ndob and number of blocks from write
3965
+ * same scsi io and based on these values it sets divert IO flag
3966
+ * and reason for diverting IO to firmware.
3967
+ *
3968
+ * Return: Nothing
3969
+ */
3970
+ static inline void mpi3mr_setup_divert_ws (struct mpi3mr_ioc * mrioc ,
3971
+ struct scsi_cmnd * scmd , struct mpi3_scsi_io_request * scsiio_req ,
3972
+ u32 * scsiio_flags , u16 wslen )
3973
+ {
3974
+ u8 unmap = 0 , ndob = 0 ;
3975
+ u8 opcode = scmd -> cmnd [0 ];
3976
+ u32 num_blocks = 0 ;
3977
+ u16 sa = (scmd -> cmnd [8 ] << 8 ) | (scmd -> cmnd [9 ]);
3978
+
3979
+ if (opcode == WRITE_SAME_16 ) {
3980
+ unmap = scmd -> cmnd [1 ] & 0x08 ;
3981
+ ndob = scmd -> cmnd [1 ] & 0x01 ;
3982
+ num_blocks = get_unaligned_be32 (scmd -> cmnd + 10 );
3983
+ } else if ((opcode == VARIABLE_LENGTH_CMD ) && (sa == WRITE_SAME_32 )) {
3984
+ unmap = scmd -> cmnd [10 ] & 0x08 ;
3985
+ ndob = scmd -> cmnd [10 ] & 0x01 ;
3986
+ num_blocks = get_unaligned_be32 (scmd -> cmnd + 28 );
3987
+ } else
3988
+ return ;
3989
+
3990
+ if ((unmap ) && (ndob ) && (num_blocks > wslen )) {
3991
+ scsiio_req -> msg_flags |=
3992
+ MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE ;
3993
+ * scsiio_flags |=
3994
+ MPI3_SCSIIO_FLAGS_DIVERT_REASON_WRITE_SAME_TOO_LARGE ;
3995
+ }
3996
+ }
3997
+
3942
3998
/**
3943
3999
* mpi3mr_eh_host_reset - Host reset error handling callback
3944
4000
* @scmd: SCSI command reference
@@ -4436,7 +4492,6 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
4436
4492
unsigned long flags ;
4437
4493
int retval = 0 ;
4438
4494
struct sas_rphy * rphy = NULL ;
4439
- bool update_stgt_priv_data = false;
4440
4495
4441
4496
scsi_tgt_priv_data = kzalloc (sizeof (* scsi_tgt_priv_data ), GFP_KERNEL );
4442
4497
if (!scsi_tgt_priv_data )
@@ -4445,39 +4500,50 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
4445
4500
starget -> hostdata = scsi_tgt_priv_data ;
4446
4501
4447
4502
spin_lock_irqsave (& mrioc -> tgtdev_lock , flags );
4448
-
4449
4503
if (starget -> channel == mrioc -> scsi_device_channel ) {
4450
4504
tgt_dev = __mpi3mr_get_tgtdev_by_perst_id (mrioc , starget -> id );
4451
- if (tgt_dev && !tgt_dev -> is_hidden )
4452
- update_stgt_priv_data = true;
4453
- else
4505
+ if (tgt_dev && !tgt_dev -> is_hidden ) {
4506
+ scsi_tgt_priv_data -> starget = starget ;
4507
+ scsi_tgt_priv_data -> dev_handle = tgt_dev -> dev_handle ;
4508
+ scsi_tgt_priv_data -> perst_id = tgt_dev -> perst_id ;
4509
+ scsi_tgt_priv_data -> dev_type = tgt_dev -> dev_type ;
4510
+ scsi_tgt_priv_data -> tgt_dev = tgt_dev ;
4511
+ tgt_dev -> starget = starget ;
4512
+ atomic_set (& scsi_tgt_priv_data -> block_io , 0 );
4513
+ retval = 0 ;
4514
+ if ((tgt_dev -> dev_type == MPI3_DEVICE_DEVFORM_PCIE ) &&
4515
+ ((tgt_dev -> dev_spec .pcie_inf .dev_info &
4516
+ MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK ) ==
4517
+ MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE ) &&
4518
+ ((tgt_dev -> dev_spec .pcie_inf .dev_info &
4519
+ MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_MASK ) !=
4520
+ MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_0 ))
4521
+ scsi_tgt_priv_data -> dev_nvme_dif = 1 ;
4522
+ scsi_tgt_priv_data -> io_throttle_enabled = tgt_dev -> io_throttle_enabled ;
4523
+ scsi_tgt_priv_data -> wslen = tgt_dev -> wslen ;
4524
+ if (tgt_dev -> dev_type == MPI3_DEVICE_DEVFORM_VD )
4525
+ scsi_tgt_priv_data -> throttle_group = tgt_dev -> dev_spec .vd_inf .tg ;
4526
+ } else
4454
4527
retval = - ENXIO ;
4455
4528
} else if (mrioc -> sas_transport_enabled && !starget -> channel ) {
4456
4529
rphy = dev_to_rphy (starget -> dev .parent );
4457
4530
tgt_dev = __mpi3mr_get_tgtdev_by_addr_and_rphy (mrioc ,
4458
4531
rphy -> identify .sas_address , rphy );
4459
4532
if (tgt_dev && !tgt_dev -> is_hidden && !tgt_dev -> non_stl &&
4460
- (tgt_dev -> dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA ))
4461
- update_stgt_priv_data = true;
4462
- else
4533
+ (tgt_dev -> dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA )) {
4534
+ scsi_tgt_priv_data -> starget = starget ;
4535
+ scsi_tgt_priv_data -> dev_handle = tgt_dev -> dev_handle ;
4536
+ scsi_tgt_priv_data -> perst_id = tgt_dev -> perst_id ;
4537
+ scsi_tgt_priv_data -> dev_type = tgt_dev -> dev_type ;
4538
+ scsi_tgt_priv_data -> tgt_dev = tgt_dev ;
4539
+ scsi_tgt_priv_data -> io_throttle_enabled = tgt_dev -> io_throttle_enabled ;
4540
+ scsi_tgt_priv_data -> wslen = tgt_dev -> wslen ;
4541
+ tgt_dev -> starget = starget ;
4542
+ atomic_set (& scsi_tgt_priv_data -> block_io , 0 );
4543
+ retval = 0 ;
4544
+ } else
4463
4545
retval = - ENXIO ;
4464
4546
}
4465
-
4466
- if (update_stgt_priv_data ) {
4467
- scsi_tgt_priv_data -> starget = starget ;
4468
- scsi_tgt_priv_data -> dev_handle = tgt_dev -> dev_handle ;
4469
- scsi_tgt_priv_data -> perst_id = tgt_dev -> perst_id ;
4470
- scsi_tgt_priv_data -> dev_type = tgt_dev -> dev_type ;
4471
- scsi_tgt_priv_data -> tgt_dev = tgt_dev ;
4472
- tgt_dev -> starget = starget ;
4473
- atomic_set (& scsi_tgt_priv_data -> block_io , 0 );
4474
- retval = 0 ;
4475
- scsi_tgt_priv_data -> io_throttle_enabled =
4476
- tgt_dev -> io_throttle_enabled ;
4477
- if (tgt_dev -> dev_type == MPI3_DEVICE_DEVFORM_VD )
4478
- scsi_tgt_priv_data -> throttle_group =
4479
- tgt_dev -> dev_spec .vd_inf .tg ;
4480
- }
4481
4547
spin_unlock_irqrestore (& mrioc -> tgtdev_lock , flags );
4482
4548
4483
4549
return retval ;
@@ -4738,6 +4804,10 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
4738
4804
4739
4805
mpi3mr_setup_eedp (mrioc , scmd , scsiio_req );
4740
4806
4807
+ if (stgt_priv_data -> wslen )
4808
+ mpi3mr_setup_divert_ws (mrioc , scmd , scsiio_req , & scsiio_flags ,
4809
+ stgt_priv_data -> wslen );
4810
+
4741
4811
memcpy (scsiio_req -> cdb .cdb32 , scmd -> cmnd , scmd -> cmd_len );
4742
4812
scsiio_req -> data_length = cpu_to_le32 (scsi_bufflen (scmd ));
4743
4813
scsiio_req -> dev_handle = cpu_to_le16 (dev_handle );
0 commit comments