aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2011-06-14 01:26:43 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 17:15:51 -0400
commitf93213de5c28d4aeda51b3c03daf7e27f6dd2b7a (patch)
tree424e6e1e95065387f38b8160febf8866c72c549a /drivers/scsi
parenta3e1e55e4b5ca4d49618c592b4d10814e21e12a7 (diff)
[SCSI] mpt2sas: fix broadcast AEN and task management issue
Properly handling of target reset in multi-initiator environment Clean up in broadcast change handling: (1) Need to look at the status of each task management request, and retry the TM when there are failures. (2) Need quiescence IO so the driver doesn't take on more IO request while it's in the middle of sending TM request to firmware (3) Add support to keep track of how many pending broadcast AEN events are received while the broadcast handling is active, then loop back at the end of this routine if there were any events received. Clean up in mpt2sas_scsih_issue_tm routine: (1) Make sure proper status is returned when host reset fails (2) Clean up sanity checks near end of routine, insuring all outstanding IOs were completed. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h15
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c241
3 files changed, 202 insertions, 56 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 451dc1ce2287..8418abbd3134 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -589,6 +589,16 @@ struct mpt2sas_port_facts {
589}; 589};
590 590
591/** 591/**
592 * enum mutex_type - task management mutex type
593 * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
594 * @TM_MUTEX_ON: mutex is required
595 */
596enum mutex_type {
597 TM_MUTEX_OFF = 0,
598 TM_MUTEX_ON = 1,
599};
600
601/**
592 * struct MPT2SAS_ADAPTER - per adapter struct 602 * struct MPT2SAS_ADAPTER - per adapter struct
593 * @list: ioc_list 603 * @list: ioc_list
594 * @shost: shost object 604 * @shost: shost object
@@ -750,6 +760,7 @@ struct MPT2SAS_ADAPTER {
750 /* misc flags */ 760 /* misc flags */
751 int aen_event_read_flag; 761 int aen_event_read_flag;
752 u8 broadcast_aen_busy; 762 u8 broadcast_aen_busy;
763 u16 broadcast_aen_pending;
753 u8 shost_recovery; 764 u8 shost_recovery;
754 765
755 struct mutex reset_in_progress_mutex; 766 struct mutex reset_in_progress_mutex;
@@ -979,8 +990,8 @@ void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
979u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, 990u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
980 u32 reply); 991 u32 reply);
981int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, 992int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
982 uint channel, uint id, uint lun, u8 type, u16 smid_task, 993 uint channel, uint id, uint lun, u8 type, u16 smid_task,
983 ulong timeout, struct scsi_cmnd *scmd); 994 ulong timeout, unsigned long serial_number, enum mutex_type m_type);
984void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); 995void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
985void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); 996void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
986void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address); 997void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index d1c3bba7e936..38ed0260959d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -994,7 +994,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
994 mpt2sas_scsih_issue_tm(ioc, 994 mpt2sas_scsih_issue_tm(ioc,
995 le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, 995 le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
996 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10, 996 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
997 NULL); 997 0, TM_MUTEX_ON);
998 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 998 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
999 } else 999 } else
1000 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, 1000 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index f86f2b1418e7..c20f590c77b3 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -2240,6 +2240,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2240 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) 2240 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2241 * @smid_task: smid assigned to the task 2241 * @smid_task: smid assigned to the task
2242 * @timeout: timeout in seconds 2242 * @timeout: timeout in seconds
2243 * @serial_number: the serial_number from scmd
2244 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
2243 * Context: user 2245 * Context: user
2244 * 2246 *
2245 * A generic API for sending task management requests to firmware. 2247 * A generic API for sending task management requests to firmware.
@@ -2251,17 +2253,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2251int 2253int
2252mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, 2254mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2253 uint id, uint lun, u8 type, u16 smid_task, ulong timeout, 2255 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
2254 struct scsi_cmnd *scmd) 2256 unsigned long serial_number, enum mutex_type m_type)
2255{ 2257{
2256 Mpi2SCSITaskManagementRequest_t *mpi_request; 2258 Mpi2SCSITaskManagementRequest_t *mpi_request;
2257 Mpi2SCSITaskManagementReply_t *mpi_reply; 2259 Mpi2SCSITaskManagementReply_t *mpi_reply;
2258 u16 smid = 0; 2260 u16 smid = 0;
2259 u32 ioc_state; 2261 u32 ioc_state;
2260 unsigned long timeleft; 2262 unsigned long timeleft;
2261 struct scsi_cmnd *scmd_lookup; 2263 struct scsiio_tracker *scsi_lookup = NULL;
2262 int rc; 2264 int rc;
2263 2265
2264 mutex_lock(&ioc->tm_cmds.mutex); 2266 if (m_type == TM_MUTEX_ON)
2267 mutex_lock(&ioc->tm_cmds.mutex);
2265 if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) { 2268 if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
2266 printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n", 2269 printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
2267 __func__, ioc->name); 2270 __func__, ioc->name);
@@ -2281,18 +2284,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2281 if (ioc_state & MPI2_DOORBELL_USED) { 2284 if (ioc_state & MPI2_DOORBELL_USED) {
2282 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell " 2285 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
2283 "active!\n", ioc->name)); 2286 "active!\n", ioc->name));
2284 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, 2287 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2285 FORCE_BIG_HAMMER); 2288 FORCE_BIG_HAMMER);
2286 rc = SUCCESS; 2289 rc = (!rc) ? SUCCESS : FAILED;
2287 goto err_out; 2290 goto err_out;
2288 } 2291 }
2289 2292
2290 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { 2293 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2291 mpt2sas_base_fault_info(ioc, ioc_state & 2294 mpt2sas_base_fault_info(ioc, ioc_state &
2292 MPI2_DOORBELL_DATA_MASK); 2295 MPI2_DOORBELL_DATA_MASK);
2293 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, 2296 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2294 FORCE_BIG_HAMMER); 2297 FORCE_BIG_HAMMER);
2295 rc = SUCCESS; 2298 rc = (!rc) ? SUCCESS : FAILED;
2296 goto err_out; 2299 goto err_out;
2297 } 2300 }
2298 2301
@@ -2304,6 +2307,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2304 goto err_out; 2307 goto err_out;
2305 } 2308 }
2306 2309
2310 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2311 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2312
2307 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," 2313 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
2308 " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, 2314 " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
2309 smid_task)); 2315 smid_task));
@@ -2311,6 +2317,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2311 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); 2317 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2312 ioc->tm_cmds.smid = smid; 2318 ioc->tm_cmds.smid = smid;
2313 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); 2319 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2320 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
2314 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 2321 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2315 mpi_request->DevHandle = cpu_to_le16(handle); 2322 mpi_request->DevHandle = cpu_to_le16(handle);
2316 mpi_request->TaskType = type; 2323 mpi_request->TaskType = type;
@@ -2326,9 +2333,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2326 _debug_dump_mf(mpi_request, 2333 _debug_dump_mf(mpi_request,
2327 sizeof(Mpi2SCSITaskManagementRequest_t)/4); 2334 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2328 if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) { 2335 if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
2329 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, 2336 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2330 FORCE_BIG_HAMMER); 2337 FORCE_BIG_HAMMER);
2331 rc = SUCCESS; 2338 rc = (!rc) ? SUCCESS : FAILED;
2332 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 2339 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
2333 mpt2sas_scsih_clear_tm_flag(ioc, handle); 2340 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2334 goto err_out; 2341 goto err_out;
@@ -2350,20 +2357,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2350 } 2357 }
2351 } 2358 }
2352 2359
2353 /* sanity check:
2354 * Check to see the commands were terminated.
2355 * This is only needed for eh callbacks, hence the scmd check.
2356 */
2357 rc = FAILED;
2358 if (scmd == NULL)
2359 goto bypass_sanity_checks;
2360 switch (type) { 2360 switch (type) {
2361 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK: 2361 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2362 scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task); 2362 rc = SUCCESS;
2363 if (scmd_lookup) 2363 if (scsi_lookup->scmd == NULL)
2364 rc = FAILED; 2364 break;
2365 else 2365 rc = FAILED;
2366 rc = SUCCESS;
2367 break; 2366 break;
2368 2367
2369 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET: 2368 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2373,24 +2372,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
2373 rc = SUCCESS; 2372 rc = SUCCESS;
2374 break; 2373 break;
2375 2374
2375 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
2376 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: 2376 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2377 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel)) 2377 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2378 rc = FAILED; 2378 rc = FAILED;
2379 else 2379 else
2380 rc = SUCCESS; 2380 rc = SUCCESS;
2381 break; 2381 break;
2382 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2383 rc = SUCCESS;
2384 break;
2385 default:
2386 rc = FAILED;
2387 break;
2382 } 2388 }
2383 2389
2384 bypass_sanity_checks:
2385
2386 mpt2sas_scsih_clear_tm_flag(ioc, handle); 2390 mpt2sas_scsih_clear_tm_flag(ioc, handle);
2387 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 2391 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
2388 mutex_unlock(&ioc->tm_cmds.mutex); 2392 if (m_type == TM_MUTEX_ON)
2393 mutex_unlock(&ioc->tm_cmds.mutex);
2389 2394
2390 return rc; 2395 return rc;
2391 2396
2392 err_out: 2397 err_out:
2393 mutex_unlock(&ioc->tm_cmds.mutex); 2398 if (m_type == TM_MUTEX_ON)
2399 mutex_unlock(&ioc->tm_cmds.mutex);
2394 return rc; 2400 return rc;
2395} 2401}
2396 2402
@@ -2500,7 +2506,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
2500 handle = sas_device_priv_data->sas_target->handle; 2506 handle = sas_device_priv_data->sas_target->handle;
2501 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, 2507 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2502 scmd->device->id, scmd->device->lun, 2508 scmd->device->id, scmd->device->lun,
2503 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd); 2509 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
2510 scmd->serial_number, TM_MUTEX_ON);
2504 2511
2505 out: 2512 out:
2506 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", 2513 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2561,7 +2568,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
2561 2568
2562 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, 2569 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2563 scmd->device->id, scmd->device->lun, 2570 scmd->device->id, scmd->device->lun,
2564 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd); 2571 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
2572 TM_MUTEX_ON);
2565 2573
2566 out: 2574 out:
2567 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", 2575 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2621,7 +2629,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
2621 2629
2622 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel, 2630 r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2623 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 2631 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
2624 30, scmd); 2632 30, 0, TM_MUTEX_ON);
2625 2633
2626 out: 2634 out:
2627 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", 2635 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2754,6 +2762,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
2754} 2762}
2755 2763
2756/** 2764/**
2765 * _scsih_ublock_io_all_device - unblock every device
2766 * @ioc: per adapter object
2767 *
2768 * change the device state from block to running
2769 */
2770static void
2771_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2772{
2773 struct MPT2SAS_DEVICE *sas_device_priv_data;
2774 struct scsi_device *sdev;
2775
2776 shost_for_each_device(sdev, ioc->shost) {
2777 sas_device_priv_data = sdev->hostdata;
2778 if (!sas_device_priv_data)
2779 continue;
2780 if (!sas_device_priv_data->block)
2781 continue;
2782 sas_device_priv_data->block = 0;
2783 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
2784 "handle(0x%04x)\n",
2785 sas_device_priv_data->sas_target->handle));
2786 scsi_internal_device_unblock(sdev);
2787 }
2788}
2789/**
2757 * _scsih_ublock_io_device - set the device state to SDEV_RUNNING 2790 * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
2758 * @ioc: per adapter object 2791 * @ioc: per adapter object
2759 * @handle: device handle 2792 * @handle: device handle
@@ -2783,6 +2816,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2783} 2816}
2784 2817
2785/** 2818/**
2819 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2820 * @ioc: per adapter object
2821 * @handle: device handle
2822 *
2823 * During device pull we need to appropiately set the sdev state.
2824 */
2825static void
2826_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2827{
2828 struct MPT2SAS_DEVICE *sas_device_priv_data;
2829 struct scsi_device *sdev;
2830
2831 shost_for_each_device(sdev, ioc->shost) {
2832 sas_device_priv_data = sdev->hostdata;
2833 if (!sas_device_priv_data)
2834 continue;
2835 if (sas_device_priv_data->block)
2836 continue;
2837 sas_device_priv_data->block = 1;
2838 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
2839 "handle(0x%04x)\n",
2840 sas_device_priv_data->sas_target->handle));
2841 scsi_internal_device_block(sdev);
2842 }
2843}
2844
2845
2846/**
2786 * _scsih_block_io_device - set the device state to SDEV_BLOCK 2847 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2787 * @ioc: per adapter object 2848 * @ioc: per adapter object
2788 * @handle: device handle 2849 * @handle: device handle
@@ -5384,9 +5445,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
5384 break; 5445 break;
5385 } 5446 }
5386 printk(MPT2SAS_INFO_FMT "device status change: (%s)\n" 5447 printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
5387 "\thandle(0x%04x), sas address(0x%016llx)", ioc->name, 5448 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5388 reason_str, le16_to_cpu(event_data->DevHandle), 5449 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5389 (unsigned long long)le64_to_cpu(event_data->SASAddress)); 5450 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5451 le16_to_cpu(event_data->TaskTag));
5390 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) 5452 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5391 printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, 5453 printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5392 event_data->ASC, event_data->ASCQ); 5454 event_data->ASC, event_data->ASCQ);
@@ -5526,25 +5588,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5526 u32 termination_count; 5588 u32 termination_count;
5527 u32 query_count; 5589 u32 query_count;
5528 Mpi2SCSITaskManagementReply_t *mpi_reply; 5590 Mpi2SCSITaskManagementReply_t *mpi_reply;
5529#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
5530 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; 5591 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
5531#endif
5532 u16 ioc_status; 5592 u16 ioc_status;
5533 unsigned long flags; 5593 unsigned long flags;
5534 int r; 5594 int r;
5595 u8 max_retries = 0;
5596 u8 task_abort_retries;
5535 5597
5536 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: " 5598 mutex_lock(&ioc->tm_cmds.mutex);
5537 "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, 5599 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
5538 event_data->PortWidth)); 5600 "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
5539 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, 5601 event_data->PortWidth));
5540 __func__)); 5602
5603 _scsih_block_io_all_device(ioc);
5541 5604
5542 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 5605 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5543 ioc->broadcast_aen_busy = 0; 5606 mpi_reply = ioc->tm_cmds.reply;
5607broadcast_aen_retry:
5608
5609 /* sanity checks for retrying this loop */
5610 if (max_retries++ == 5) {
5611 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
5612 ioc->name, __func__));
5613 goto out;
5614 } else if (max_retries > 1)
5615 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
5616 ioc->name, __func__, max_retries - 1));
5617
5544 termination_count = 0; 5618 termination_count = 0;
5545 query_count = 0; 5619 query_count = 0;
5546 mpi_reply = ioc->tm_cmds.reply;
5547 for (smid = 1; smid <= ioc->scsiio_depth; smid++) { 5620 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
5621 if (ioc->ioc_reset_in_progress_status)
5622 goto out;
5548 scmd = _scsih_scsi_lookup_get(ioc, smid); 5623 scmd = _scsih_scsi_lookup_get(ioc, smid);
5549 if (!scmd) 5624 if (!scmd)
5550 continue; 5625 continue;
@@ -5565,34 +5640,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
5565 lun = sas_device_priv_data->lun; 5640 lun = sas_device_priv_data->lun;
5566 query_count++; 5641 query_count++;
5567 5642
5643 if (ioc->ioc_reset_in_progress_status)
5644 goto out;
5645
5568 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 5646 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5569 mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, 5647 r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
5570 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL); 5648 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
5571 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 5649 TM_MUTEX_OFF);
5650 if (r == FAILED) {
5651 sdev_printk(KERN_WARNING, sdev,
5652 "mpt2sas_scsih_issue_tm: FAILED when sending "
5653 "QUERY_TASK: scmd(%p)\n", scmd);
5654 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5655 goto broadcast_aen_retry;
5656 }
5572 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) 5657 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5573 & MPI2_IOCSTATUS_MASK; 5658 & MPI2_IOCSTATUS_MASK;
5574 if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && 5659 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5575 (mpi_reply->ResponseCode == 5660 sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
5661 "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
5662 scmd);
5663 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5664 goto broadcast_aen_retry;
5665 }
5666
5667 /* see if IO is still owned by IOC and target */
5668 if (mpi_reply->ResponseCode ==
5576 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || 5669 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5577 mpi_reply->ResponseCode == 5670 mpi_reply->ResponseCode ==
5578 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) { 5671 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
5579 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 5672 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5580 continue; 5673 continue;
5581 } 5674 }
5675 task_abort_retries = 0;
5676 tm_retry:
5677 if (task_abort_retries++ == 60) {
5678 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
5679 "%s: ABORT_TASK: giving up\n", ioc->name,
5680 __func__));
5681 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5682 goto broadcast_aen_retry;
5683 }
5684
5685 if (ioc->ioc_reset_in_progress_status)
5686 goto out_no_lock;
5687
5582 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, 5688 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5583 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, 5689 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
5584 scmd); 5690 scmd->serial_number, TM_MUTEX_OFF);
5585 if (r == FAILED) 5691 if (r == FAILED) {
5586 sdev_printk(KERN_WARNING, sdev, "task abort: FAILED " 5692 sdev_printk(KERN_WARNING, sdev,
5693 "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
5587 "scmd(%p)\n", scmd); 5694 "scmd(%p)\n", scmd);
5695 goto tm_retry;
5696 }
5697
5698 if (task_abort_retries > 1)
5699 sdev_printk(KERN_WARNING, sdev,
5700 "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5701 " scmd(%p)\n",
5702 task_abort_retries - 1, scmd);
5703
5588 termination_count += le32_to_cpu(mpi_reply->TerminationCount); 5704 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
5589 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 5705 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5590 } 5706 }
5707
5708 if (ioc->broadcast_aen_pending) {
5709 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
5710 " pending AEN\n", ioc->name, __func__));
5711 ioc->broadcast_aen_pending = 0;
5712 goto broadcast_aen_retry;
5713 }
5714
5715 out:
5591 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 5716 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5717 out_no_lock:
5592 5718
5593 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT 5719 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
5594 "%s - exit, query_count = %d termination_count = %d\n", 5720 "%s - exit, query_count = %d termination_count = %d\n",
5595 ioc->name, __func__, query_count, termination_count)); 5721 ioc->name, __func__, query_count, termination_count));
5722
5723 ioc->broadcast_aen_busy = 0;
5724 if (!ioc->ioc_reset_in_progress_status)
5725 _scsih_ublock_io_all_device(ioc);
5726 mutex_unlock(&ioc->tm_cmds.mutex);
5596} 5727}
5597 5728
5598/** 5729/**
@@ -6866,10 +6997,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
6866 mpi_reply->EventData; 6997 mpi_reply->EventData;
6867 6998
6868 if (baen_data->Primitive != 6999 if (baen_data->Primitive !=
6869 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || 7000 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
6870 ioc->broadcast_aen_busy)
6871 return 1; 7001 return 1;
6872 ioc->broadcast_aen_busy = 1; 7002
7003 if (ioc->broadcast_aen_busy) {
7004 ioc->broadcast_aen_pending++;
7005 return 1;
7006 } else
7007 ioc->broadcast_aen_busy = 1;
6873 break; 7008 break;
6874 } 7009 }
6875 7010