aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2011-01-05 07:24:32 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-01-24 10:24:28 -0500
commitec07a053597bdab51cbd23619f9f9f392712508a (patch)
treef6d2308eb2481481c430f961e98fa68b5b0c1240 /drivers/scsi
parent11e1b961ab067ee3acaf723531da4d3f23e1d6f7 (diff)
[SCSI] mpt2sas: Fix the race between broadcast asyn event and scsi command completion
False timeout after hard resets, there were two issues which leads to timeout. (1) Panic because of invalid memory access in the broadcast asyn event processing routine due to a race between accessing the scsi command pointer from broadcast asyn event processing thread and completing the same scsi command from the interrupt context. (2) Broadcast asyn event notifcations are not handled due to events ignored while the broadcast asyn event is activity being processed from the event process kernel thread. In addition, changed the ABRT_TASK_SET to ABORT_TASK in the broadcast async event processing routine. This is less disruptive to other request that generate Broadcast Asyn Primitives besides target reset. e.g clear reservations, microcode download,and mode select. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Cc: stable@kernel.org Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index a16f2a05736f..db287d79bdcf 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -819,7 +819,7 @@ _scsih_is_end_device(u32 device_info)
819} 819}
820 820
821/** 821/**
822 * mptscsih_get_scsi_lookup - returns scmd entry 822 * _scsih_scsi_lookup_get - returns scmd entry
823 * @ioc: per adapter object 823 * @ioc: per adapter object
824 * @smid: system request message index 824 * @smid: system request message index
825 * 825 *
@@ -832,6 +832,28 @@ _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
832} 832}
833 833
834/** 834/**
835 * _scsih_scsi_lookup_get_clear - returns scmd entry
836 * @ioc: per adapter object
837 * @smid: system request message index
838 *
839 * Returns the smid stored scmd pointer.
840 * Then will derefrence the stored scmd pointer.
841 */
842static inline struct scsi_cmnd *
843_scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
844{
845 unsigned long flags;
846 struct scsi_cmnd *scmd;
847
848 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
849 scmd = ioc->scsi_lookup[smid - 1].scmd;
850 ioc->scsi_lookup[smid - 1].scmd = NULL;
851 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
852
853 return scmd;
854}
855
856/**
835 * _scsih_scsi_lookup_find_by_scmd - scmd lookup 857 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
836 * @ioc: per adapter object 858 * @ioc: per adapter object
837 * @smid: system request message index 859 * @smid: system request message index
@@ -3207,7 +3229,7 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
3207 u16 count = 0; 3229 u16 count = 0;
3208 3230
3209 for (smid = 1; smid <= ioc->scsiio_depth; smid++) { 3231 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3210 scmd = _scsih_scsi_lookup_get(ioc, smid); 3232 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3211 if (!scmd) 3233 if (!scmd)
3212 continue; 3234 continue;
3213 count++; 3235 count++;
@@ -3801,7 +3823,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
3801 u32 response_code = 0; 3823 u32 response_code = 0;
3802 3824
3803 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); 3825 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
3804 scmd = _scsih_scsi_lookup_get(ioc, smid); 3826 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3805 if (scmd == NULL) 3827 if (scmd == NULL)
3806 return 1; 3828 return 1;
3807 3829
@@ -5102,6 +5124,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5102 struct fw_event_work *fw_event) 5124 struct fw_event_work *fw_event)
5103{ 5125{
5104 struct scsi_cmnd *scmd; 5126 struct scsi_cmnd *scmd;
5127 struct scsi_device *sdev;
5105 u16 smid, handle; 5128 u16 smid, handle;
5106 u32 lun; 5129 u32 lun;
5107 struct MPT2SAS_DEVICE *sas_device_priv_data; 5130 struct MPT2SAS_DEVICE *sas_device_priv_data;
@@ -5112,12 +5135,17 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5112 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; 5135 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
5113#endif 5136#endif
5114 u16 ioc_status; 5137 u16 ioc_status;
5138 unsigned long flags;
5139 int r;
5140
5115 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: " 5141 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: "
5116 "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, 5142 "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
5117 event_data->PortWidth)); 5143 event_data->PortWidth));
5118 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, 5144 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
5119 __func__)); 5145 __func__));
5120 5146
5147 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5148 ioc->broadcast_aen_busy = 0;
5121 termination_count = 0; 5149 termination_count = 0;
5122 query_count = 0; 5150 query_count = 0;
5123 mpi_reply = ioc->tm_cmds.reply; 5151 mpi_reply = ioc->tm_cmds.reply;
@@ -5125,7 +5153,8 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5125 scmd = _scsih_scsi_lookup_get(ioc, smid); 5153 scmd = _scsih_scsi_lookup_get(ioc, smid);
5126 if (!scmd) 5154 if (!scmd)
5127 continue; 5155 continue;
5128 sas_device_priv_data = scmd->device->hostdata; 5156 sdev = scmd->device;
5157 sas_device_priv_data = sdev->hostdata;
5129 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) 5158 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5130 continue; 5159 continue;
5131 /* skip hidden raid components */ 5160 /* skip hidden raid components */
@@ -5141,6 +5170,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5141 lun = sas_device_priv_data->lun; 5170 lun = sas_device_priv_data->lun;
5142 query_count++; 5171 query_count++;
5143 5172
5173 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5144 mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, 5174 mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
5145 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL); 5175 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
5146 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 5176 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
@@ -5150,14 +5180,20 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5150 (mpi_reply->ResponseCode == 5180 (mpi_reply->ResponseCode ==
5151 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || 5181 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5152 mpi_reply->ResponseCode == 5182 mpi_reply->ResponseCode ==
5153 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) 5183 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
5184 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5154 continue; 5185 continue;
5155 5186 }
5156 mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, 5187 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5157 MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, 0, 30, NULL); 5188 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
5189 scmd);
5190 if (r == FAILED)
5191 sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
5192 "scmd(%p)\n", scmd);
5158 termination_count += le32_to_cpu(mpi_reply->TerminationCount); 5193 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
5194 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5159 } 5195 }
5160 ioc->broadcast_aen_busy = 0; 5196 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5161 5197
5162 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT 5198 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
5163 "%s - exit, query_count = %d termination_count = %d\n", 5199 "%s - exit, query_count = %d termination_count = %d\n",