| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: Chaitra P B <chaitra.basappa@broadcom.com> |
| Date: Wed, 27 Dec 2017 23:09:11 -0800 |
| Subject: scsi: mpt3sas: Proper handling of set/clear of "ATA command pending" flag. |
| |
| From: Chaitra P B <chaitra.basappa@broadcom.com> |
| |
| |
| [ Upstream commit f49d4aed1315a7b766d855f1367142e682b0cc87 ] |
| |
| 1. In IO path, setting of "ATA command pending" flag early before device |
| removal, invalid device handle etc., checks causes any new commands |
| to be always returned with SAM_STAT_BUSY and when the driver removes |
| the drive the SML issues SYNC Cache command and that command is |
| always returned with SAM_STAT_BUSY and thus making SYNC Cache command |
| to requeued. |
| |
| 2. If the driver gets an ATA PT command for a SATA drive then the driver |
| set "ATA command pending" flag in device specific data structure not |
| to allow any further commands until the ATA PT command is completed. |
| However, after setting the flag if the driver decides to return the |
| command back to upper layers without actually issuing to the firmware |
| (i.e., returns from qcmd failure return paths) then the corresponding |
| flag is not cleared and this prevents the driver from sending any new |
| commands to the drive. |
| |
| This patch fixes above two issues by setting of "ATA command pending" |
| flag after checking for whether device deleted, invalid device handle, |
| device busy with task management. And by setting "ATA command pending" |
| flag to false in all of the qcmd failure return paths after setting the |
| flag. |
| |
| Signed-off-by: Chaitra P B <chaitra.basappa@broadcom.com> |
| Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/scsi/mpt3sas/mpt3sas_scsih.c | 28 +++++++++++++++------------- |
| 1 file changed, 15 insertions(+), 13 deletions(-) |
| |
| --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c |
| +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c |
| @@ -4065,19 +4065,6 @@ scsih_qcmd(struct Scsi_Host *shost, stru |
| return 0; |
| } |
| |
| - /* |
| - * Bug work around for firmware SATL handling. The loop |
| - * is based on atomic operations and ensures consistency |
| - * since we're lockless at this point |
| - */ |
| - do { |
| - if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { |
| - scmd->result = SAM_STAT_BUSY; |
| - scmd->scsi_done(scmd); |
| - return 0; |
| - } |
| - } while (_scsih_set_satl_pending(scmd, true)); |
| - |
| sas_target_priv_data = sas_device_priv_data->sas_target; |
| |
| /* invalid device handle */ |
| @@ -4103,6 +4090,19 @@ scsih_qcmd(struct Scsi_Host *shost, stru |
| sas_device_priv_data->block) |
| return SCSI_MLQUEUE_DEVICE_BUSY; |
| |
| + /* |
| + * Bug work around for firmware SATL handling. The loop |
| + * is based on atomic operations and ensures consistency |
| + * since we're lockless at this point |
| + */ |
| + do { |
| + if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { |
| + scmd->result = SAM_STAT_BUSY; |
| + scmd->scsi_done(scmd); |
| + return 0; |
| + } |
| + } while (_scsih_set_satl_pending(scmd, true)); |
| + |
| if (scmd->sc_data_direction == DMA_FROM_DEVICE) |
| mpi_control = MPI2_SCSIIO_CONTROL_READ; |
| else if (scmd->sc_data_direction == DMA_TO_DEVICE) |
| @@ -4124,6 +4124,7 @@ scsih_qcmd(struct Scsi_Host *shost, stru |
| if (!smid) { |
| pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", |
| ioc->name, __func__); |
| + _scsih_set_satl_pending(scmd, false); |
| goto out; |
| } |
| mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); |
| @@ -4154,6 +4155,7 @@ scsih_qcmd(struct Scsi_Host *shost, stru |
| if (mpi_request->DataLength) { |
| if (ioc->build_sg_scmd(ioc, scmd, smid)) { |
| mpt3sas_base_free_smid(ioc, smid); |
| + _scsih_set_satl_pending(scmd, false); |
| goto out; |
| } |
| } else |