aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt3sas
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2017-01-01 12:39:24 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-26 02:24:44 -0500
commit16236802bfecb1082144a48b7d6fa60997824662 (patch)
tree58b0862671f165f26107765f0560cbc11b9569d5 /drivers/scsi/mpt3sas
parenta07a122ad2a2e03209155fe907bf8b1e6ae4c915 (diff)
scsi: mpt3sas: fix hang on ata passthrough commands
commit ffb58456589443ca572221fabbdef3db8483a779 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/scsi/mpt3sas')
-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 3e71bc1b4a80..7008061c4b5b 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;
@@ -402,6 +403,17 @@ struct MPT3SAS_DEVICE {
402 u8 block; 403 u8 block;
403 u8 tlr_snoop_check; 404 u8 tlr_snoop_check;
404 u8 ignore_delay_remove; 405 u8 ignore_delay_remove;
406 /*
407 * Bug workaround for SATL handling: the mpt2/3sas firmware
408 * doesn't return BUSY or TASK_SET_FULL for subsequent
409 * commands while a SATL pass through is in operation as the
410 * spec requires, it simply does nothing with them until the
411 * pass through completes, causing them possibly to timeout if
412 * the passthrough is a long executing command (like format or
413 * secure erase). This variable allows us to do the right
414 * thing while a SATL command is pending.
415 */
416 unsigned long ata_command_pending;
405}; 417};
406 418
407#define MPT3_CMD_NOT_USED 0x8000 /* free */ 419#define MPT3_CMD_NOT_USED 0x8000 /* free */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 1c4744e78173..f84a6087cebd 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3885,9 +3885,18 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3885 } 3885 }
3886} 3886}
3887 3887
3888static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd) 3888static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
3889{ 3889{
3890 return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16); 3890 struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
3891
3892 if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
3893 return 0;
3894
3895 if (pending)
3896 return test_and_set_bit(0, &priv->ata_command_pending);
3897
3898 clear_bit(0, &priv->ata_command_pending);
3899 return 0;
3891} 3900}
3892 3901
3893/** 3902/**
@@ -3911,9 +3920,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3911 if (!scmd) 3920 if (!scmd)
3912 continue; 3921 continue;
3913 count++; 3922 count++;
3914 if (ata_12_16_cmd(scmd)) 3923 _scsih_set_satl_pending(scmd, false);
3915 scsi_internal_device_unblock(scmd->device,
3916 SDEV_RUNNING);
3917 mpt3sas_base_free_smid(ioc, smid); 3924 mpt3sas_base_free_smid(ioc, smid);
3918 scsi_dma_unmap(scmd); 3925 scsi_dma_unmap(scmd);
3919 if (ioc->pci_error_recovery) 3926 if (ioc->pci_error_recovery)
@@ -4044,13 +4051,6 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
4044 if (ioc->logging_level & MPT_DEBUG_SCSI) 4051 if (ioc->logging_level & MPT_DEBUG_SCSI)
4045 scsi_print_command(scmd); 4052 scsi_print_command(scmd);
4046 4053
4047 /*
4048 * Lock the device for any subsequent command until command is
4049 * done.
4050 */
4051 if (ata_12_16_cmd(scmd))
4052 scsi_internal_device_block(scmd->device);
4053
4054 sas_device_priv_data = scmd->device->hostdata; 4054 sas_device_priv_data = scmd->device->hostdata;
4055 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { 4055 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
4056 scmd->result = DID_NO_CONNECT << 16; 4056 scmd->result = DID_NO_CONNECT << 16;
@@ -4064,6 +4064,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
4064 return 0; 4064 return 0;
4065 } 4065 }
4066 4066
4067 /*
4068 * Bug work around for firmware SATL handling. The loop
4069 * is based on atomic operations and ensures consistency
4070 * since we're lockless at this point
4071 */
4072 do {
4073 if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
4074 scmd->result = SAM_STAT_BUSY;
4075 scmd->scsi_done(scmd);
4076 return 0;
4077 }
4078 } while (_scsih_set_satl_pending(scmd, true));
4079
4067 sas_target_priv_data = sas_device_priv_data->sas_target; 4080 sas_target_priv_data = sas_device_priv_data->sas_target;
4068 4081
4069 /* invalid device handle */ 4082 /* invalid device handle */
@@ -4626,8 +4639,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4626 if (scmd == NULL) 4639 if (scmd == NULL)
4627 return 1; 4640 return 1;
4628 4641
4629 if (ata_12_16_cmd(scmd)) 4642 _scsih_set_satl_pending(scmd, false);
4630 scsi_internal_device_unblock(scmd->device, SDEV_RUNNING);
4631 4643
4632 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); 4644 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4633 4645