aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2017-01-01 12:39:24 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2017-01-17 14:36:57 -0500
commitffb58456589443ca572221fabbdef3db8483a779 (patch)
tree229f7131a9361279f612ba993381956320eeb1ae
parent8667f515952feefebb3c0f8d9a9266c91b101a46 (diff)
scsi: mpt3sas: fix hang on ata passthrough commands
mpt3sas has a firmware failure where it can only handle one pass through ATA command at a time. If another comes in, contrary to the SAT standard, it will hang until the first one completes (causing long commands like secure erase to timeout). The original fix was to block the device when an ATA command came in, but this caused a regression with commit 669f044170d8933c3d66d231b69ea97cb8447338 Author: Bart Van Assche <bart.vanassche@sandisk.com> Date: Tue Nov 22 16:17:13 2016 -0800 scsi: srp_transport: Move queuecommand() wait code to SCSI core So fix the original fix of the secure erase timeout by properly returning SAM_STAT_BUSY like the SAT recommends. The original patch also had a concurrency problem since scsih_qcmd is lockless at that point (this is fixed by using atomic bitops to set and test the flag). [mkp: addressed feedback wrt. test_bit and fixed whitespace] Fixes: 18f6084a989ba1b (mpt3sas: Fix secure erase premature termination) Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Acked-by: Sreekanth Reddy <Sreekanth.Reddy@broadcom.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reported-by: Ingo Molnar <mingo@kernel.org> Tested-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h12
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c40
2 files changed, 38 insertions, 14 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 394fe1338d09..dcb33f4fa687 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -393,6 +393,7 @@ struct MPT3SAS_TARGET {
393 * @eedp_enable: eedp support enable bit 393 * @eedp_enable: eedp support enable bit
394 * @eedp_type: 0(type_1), 1(type_2), 2(type_3) 394 * @eedp_type: 0(type_1), 1(type_2), 2(type_3)
395 * @eedp_block_length: block size 395 * @eedp_block_length: block size
396 * @ata_command_pending: SATL passthrough outstanding for device
396 */ 397 */
397struct MPT3SAS_DEVICE { 398struct MPT3SAS_DEVICE {
398 struct MPT3SAS_TARGET *sas_target; 399 struct MPT3SAS_TARGET *sas_target;
@@ -404,6 +405,17 @@ struct MPT3SAS_DEVICE {
404 u8 ignore_delay_remove; 405 u8 ignore_delay_remove;
405 /* Iopriority Command Handling */ 406 /* Iopriority Command Handling */
406 u8 ncq_prio_enable; 407 u8 ncq_prio_enable;
408 /*
409 * Bug workaround for SATL handling: the mpt2/3sas firmware
410 * doesn't return BUSY or TASK_SET_FULL for subsequent
411 * commands while a SATL pass through is in operation as the
412 * spec requires, it simply does nothing with them until the
413 * pass through completes, causing them possibly to timeout if
414 * the passthrough is a long executing command (like format or
415 * secure erase). This variable allows us to do the right
416 * thing while a SATL command is pending.
417 */
418 unsigned long ata_command_pending;
407 419
408}; 420};
409 421
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index b5c966e319d3..75f3fce1c867 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3899,9 +3899,18 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3899 } 3899 }
3900} 3900}
3901 3901
3902static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd) 3902static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
3903{ 3903{
3904 return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16); 3904 struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
3905
3906 if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
3907 return 0;
3908
3909 if (pending)
3910 return test_and_set_bit(0, &priv->ata_command_pending);
3911
3912 clear_bit(0, &priv->ata_command_pending);
3913 return 0;
3905} 3914}
3906 3915
3907/** 3916/**
@@ -3925,9 +3934,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3925 if (!scmd) 3934 if (!scmd)
3926 continue; 3935 continue;
3927 count++; 3936 count++;
3928 if (ata_12_16_cmd(scmd)) 3937 _scsih_set_satl_pending(scmd, false);
3929 scsi_internal_device_unblock(scmd->device,
3930 SDEV_RUNNING);
3931 mpt3sas_base_free_smid(ioc, smid); 3938 mpt3sas_base_free_smid(ioc, smid);
3932 scsi_dma_unmap(scmd); 3939 scsi_dma_unmap(scmd);
3933 if (ioc->pci_error_recovery) 3940 if (ioc->pci_error_recovery)
@@ -4063,13 +4070,6 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
4063 if (ioc->logging_level & MPT_DEBUG_SCSI) 4070 if (ioc->logging_level & MPT_DEBUG_SCSI)
4064 scsi_print_command(scmd); 4071 scsi_print_command(scmd);
4065 4072
4066 /*
4067 * Lock the device for any subsequent command until command is
4068 * done.
4069 */
4070 if (ata_12_16_cmd(scmd))
4071 scsi_internal_device_block(scmd->device);
4072
4073 sas_device_priv_data = scmd->device->hostdata; 4073 sas_device_priv_data = scmd->device->hostdata;
4074 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { 4074 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
4075 scmd->result = DID_NO_CONNECT << 16; 4075 scmd->result = DID_NO_CONNECT << 16;
@@ -4083,6 +4083,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
4083 return 0; 4083 return 0;
4084 } 4084 }
4085 4085
4086 /*
4087 * Bug work around for firmware SATL handling. The loop
4088 * is based on atomic operations and ensures consistency
4089 * since we're lockless at this point
4090 */
4091 do {
4092 if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
4093 scmd->result = SAM_STAT_BUSY;
4094 scmd->scsi_done(scmd);
4095 return 0;
4096 }
4097 } while (_scsih_set_satl_pending(scmd, true));
4098
4086 sas_target_priv_data = sas_device_priv_data->sas_target; 4099 sas_target_priv_data = sas_device_priv_data->sas_target;
4087 4100
4088 /* invalid device handle */ 4101 /* invalid device handle */
@@ -4650,8 +4663,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4650 if (scmd == NULL) 4663 if (scmd == NULL)
4651 return 1; 4664 return 1;
4652 4665
4653 if (ata_12_16_cmd(scmd)) 4666 _scsih_set_satl_pending(scmd, false);
4654 scsi_internal_device_unblock(scmd->device, SDEV_RUNNING);
4655 4667
4656 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); 4668 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4657 4669