diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 252 |
1 files changed, 110 insertions, 142 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 2e9a4445596f..774b34525bba 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -103,7 +103,6 @@ struct sense_info { | |||
103 | }; | 103 | }; |
104 | 104 | ||
105 | 105 | ||
106 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) | ||
107 | /** | 106 | /** |
108 | * struct fw_event_work - firmware event struct | 107 | * struct fw_event_work - firmware event struct |
109 | * @list: link list framework | 108 | * @list: link list framework |
@@ -1502,7 +1501,13 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
1502 | break; | 1501 | break; |
1503 | case MPI2_RAID_VOL_TYPE_RAID1E: | 1502 | case MPI2_RAID_VOL_TYPE_RAID1E: |
1504 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | 1503 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; |
1505 | r_level = "RAID1E"; | 1504 | if (ioc->manu_pg10.OEMIdentifier && |
1505 | (ioc->manu_pg10.GenericFlags0 & | ||
1506 | MFG10_GF0_R10_DISPLAY) && | ||
1507 | !(raid_device->num_pds % 2)) | ||
1508 | r_level = "RAID10"; | ||
1509 | else | ||
1510 | r_level = "RAID1E"; | ||
1506 | break; | 1511 | break; |
1507 | case MPI2_RAID_VOL_TYPE_RAID1: | 1512 | case MPI2_RAID_VOL_TYPE_RAID1: |
1508 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; | 1513 | qdepth = MPT2SAS_RAID_QUEUE_DEPTH; |
@@ -1786,17 +1791,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1786 | u32 ioc_state; | 1791 | u32 ioc_state; |
1787 | unsigned long timeleft; | 1792 | unsigned long timeleft; |
1788 | u8 VF_ID = 0; | 1793 | u8 VF_ID = 0; |
1789 | unsigned long flags; | ||
1790 | 1794 | ||
1791 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 1795 | if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) { |
1792 | if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED || | 1796 | printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n", |
1793 | ioc->shost_recovery) { | 1797 | __func__, ioc->name); |
1794 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 1798 | return; |
1799 | } | ||
1800 | |||
1801 | if (ioc->shost_recovery) { | ||
1795 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | 1802 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", |
1796 | __func__, ioc->name); | 1803 | __func__, ioc->name); |
1797 | return; | 1804 | return; |
1798 | } | 1805 | } |
1799 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
1800 | 1806 | ||
1801 | ioc_state = mpt2sas_base_get_iocstate(ioc, 0); | 1807 | ioc_state = mpt2sas_base_get_iocstate(ioc, 0); |
1802 | if (ioc_state & MPI2_DOORBELL_USED) { | 1808 | if (ioc_state & MPI2_DOORBELL_USED) { |
@@ -1830,6 +1836,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1830 | mpi_request->TaskMID = cpu_to_le16(smid_task); | 1836 | mpi_request->TaskMID = cpu_to_le16(smid_task); |
1831 | int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); | 1837 | int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); |
1832 | mpt2sas_scsih_set_tm_flag(ioc, handle); | 1838 | mpt2sas_scsih_set_tm_flag(ioc, handle); |
1839 | init_completion(&ioc->tm_cmds.done); | ||
1833 | mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID); | 1840 | mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID); |
1834 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); | 1841 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); |
1835 | mpt2sas_scsih_clear_tm_flag(ioc, handle); | 1842 | mpt2sas_scsih_clear_tm_flag(ioc, handle); |
@@ -2222,7 +2229,7 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2222 | MPT2SAS_INFO_FMT "SDEV_RUNNING: " | 2229 | MPT2SAS_INFO_FMT "SDEV_RUNNING: " |
2223 | "handle(0x%04x)\n", ioc->name, handle)); | 2230 | "handle(0x%04x)\n", ioc->name, handle)); |
2224 | sas_device_priv_data->block = 0; | 2231 | sas_device_priv_data->block = 0; |
2225 | scsi_device_set_state(sdev, SDEV_RUNNING); | 2232 | scsi_internal_device_unblock(sdev); |
2226 | } | 2233 | } |
2227 | } | 2234 | } |
2228 | } | 2235 | } |
@@ -2251,7 +2258,7 @@ _scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2251 | MPT2SAS_INFO_FMT "SDEV_BLOCK: " | 2258 | MPT2SAS_INFO_FMT "SDEV_BLOCK: " |
2252 | "handle(0x%04x)\n", ioc->name, handle)); | 2259 | "handle(0x%04x)\n", ioc->name, handle)); |
2253 | sas_device_priv_data->block = 1; | 2260 | sas_device_priv_data->block = 1; |
2254 | scsi_device_set_state(sdev, SDEV_BLOCK); | 2261 | scsi_internal_device_block(sdev); |
2255 | } | 2262 | } |
2256 | } | 2263 | } |
2257 | } | 2264 | } |
@@ -2327,6 +2334,7 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2327 | u16 handle; | 2334 | u16 handle; |
2328 | u16 reason_code; | 2335 | u16 reason_code; |
2329 | u8 phy_number; | 2336 | u8 phy_number; |
2337 | u8 link_rate; | ||
2330 | 2338 | ||
2331 | for (i = 0; i < event_data->NumEntries; i++) { | 2339 | for (i = 0; i < event_data->NumEntries; i++) { |
2332 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 2340 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
@@ -2337,6 +2345,11 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2337 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 2345 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
2338 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) | 2346 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) |
2339 | _scsih_block_io_device(ioc, handle); | 2347 | _scsih_block_io_device(ioc, handle); |
2348 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) { | ||
2349 | link_rate = event_data->PHY[i].LinkRate >> 4; | ||
2350 | if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5) | ||
2351 | _scsih_ublock_io_device(ioc, handle); | ||
2352 | } | ||
2340 | } | 2353 | } |
2341 | } | 2354 | } |
2342 | 2355 | ||
@@ -2405,27 +2418,6 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, | |||
2405 | } | 2418 | } |
2406 | 2419 | ||
2407 | /** | 2420 | /** |
2408 | * _scsih_queue_rescan - queue a topology rescan from user context | ||
2409 | * @ioc: per adapter object | ||
2410 | * | ||
2411 | * Return nothing. | ||
2412 | */ | ||
2413 | static void | ||
2414 | _scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc) | ||
2415 | { | ||
2416 | struct fw_event_work *fw_event; | ||
2417 | |||
2418 | if (ioc->wait_for_port_enable_to_complete) | ||
2419 | return; | ||
2420 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | ||
2421 | if (!fw_event) | ||
2422 | return; | ||
2423 | fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET; | ||
2424 | fw_event->ioc = ioc; | ||
2425 | _scsih_fw_event_add(ioc, fw_event); | ||
2426 | } | ||
2427 | |||
2428 | /** | ||
2429 | * _scsih_flush_running_cmds - completing outstanding commands. | 2421 | * _scsih_flush_running_cmds - completing outstanding commands. |
2430 | * @ioc: per adapter object | 2422 | * @ioc: per adapter object |
2431 | * | 2423 | * |
@@ -2456,46 +2448,6 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) | |||
2456 | } | 2448 | } |
2457 | 2449 | ||
2458 | /** | 2450 | /** |
2459 | * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) | ||
2460 | * @ioc: per adapter object | ||
2461 | * @reset_phase: phase | ||
2462 | * | ||
2463 | * The handler for doing any required cleanup or initialization. | ||
2464 | * | ||
2465 | * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, | ||
2466 | * MPT2_IOC_DONE_RESET | ||
2467 | * | ||
2468 | * Return nothing. | ||
2469 | */ | ||
2470 | void | ||
2471 | mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | ||
2472 | { | ||
2473 | switch (reset_phase) { | ||
2474 | case MPT2_IOC_PRE_RESET: | ||
2475 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
2476 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
2477 | _scsih_fw_event_off(ioc); | ||
2478 | break; | ||
2479 | case MPT2_IOC_AFTER_RESET: | ||
2480 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
2481 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | ||
2482 | if (ioc->tm_cmds.status & MPT2_CMD_PENDING) { | ||
2483 | ioc->tm_cmds.status |= MPT2_CMD_RESET; | ||
2484 | mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid); | ||
2485 | complete(&ioc->tm_cmds.done); | ||
2486 | } | ||
2487 | _scsih_fw_event_on(ioc); | ||
2488 | _scsih_flush_running_cmds(ioc); | ||
2489 | break; | ||
2490 | case MPT2_IOC_DONE_RESET: | ||
2491 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
2492 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | ||
2493 | _scsih_queue_rescan(ioc); | ||
2494 | break; | ||
2495 | } | ||
2496 | } | ||
2497 | |||
2498 | /** | ||
2499 | * _scsih_setup_eedp - setup MPI request for EEDP transfer | 2451 | * _scsih_setup_eedp - setup MPI request for EEDP transfer |
2500 | * @scmd: pointer to scsi command object | 2452 | * @scmd: pointer to scsi command object |
2501 | * @mpi_request: pointer to the SCSI_IO reqest message frame | 2453 | * @mpi_request: pointer to the SCSI_IO reqest message frame |
@@ -2615,7 +2567,6 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2615 | Mpi2SCSIIORequest_t *mpi_request; | 2567 | Mpi2SCSIIORequest_t *mpi_request; |
2616 | u32 mpi_control; | 2568 | u32 mpi_control; |
2617 | u16 smid; | 2569 | u16 smid; |
2618 | unsigned long flags; | ||
2619 | 2570 | ||
2620 | scmd->scsi_done = done; | 2571 | scmd->scsi_done = done; |
2621 | sas_device_priv_data = scmd->device->hostdata; | 2572 | sas_device_priv_data = scmd->device->hostdata; |
@@ -2634,13 +2585,10 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2634 | } | 2585 | } |
2635 | 2586 | ||
2636 | /* see if we are busy with task managment stuff */ | 2587 | /* see if we are busy with task managment stuff */ |
2637 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 2588 | if (sas_target_priv_data->tm_busy) |
2638 | if (sas_target_priv_data->tm_busy || | 2589 | return SCSI_MLQUEUE_DEVICE_BUSY; |
2639 | ioc->shost_recovery || ioc->ioc_link_reset_in_progress) { | 2590 | else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) |
2640 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
2641 | return SCSI_MLQUEUE_HOST_BUSY; | 2591 | return SCSI_MLQUEUE_HOST_BUSY; |
2642 | } | ||
2643 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
2644 | 2592 | ||
2645 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) | 2593 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) |
2646 | mpi_control = MPI2_SCSIIO_CONTROL_READ; | 2594 | mpi_control = MPI2_SCSIIO_CONTROL_READ; |
@@ -3189,25 +3137,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
3189 | } | 3137 | } |
3190 | 3138 | ||
3191 | /** | 3139 | /** |
3192 | * _scsih_link_change - process phy link changes | ||
3193 | * @ioc: per adapter object | ||
3194 | * @handle: phy handle | ||
3195 | * @attached_handle: valid for devices attached to link | ||
3196 | * @phy_number: phy number | ||
3197 | * @link_rate: new link rate | ||
3198 | * Context: user. | ||
3199 | * | ||
3200 | * Return nothing. | ||
3201 | */ | ||
3202 | static void | ||
3203 | _scsih_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle, u16 attached_handle, | ||
3204 | u8 phy_number, u8 link_rate) | ||
3205 | { | ||
3206 | mpt2sas_transport_update_phy_link_change(ioc, handle, attached_handle, | ||
3207 | phy_number, link_rate); | ||
3208 | } | ||
3209 | |||
3210 | /** | ||
3211 | * _scsih_sas_host_refresh - refreshing sas host object contents | 3140 | * _scsih_sas_host_refresh - refreshing sas host object contents |
3212 | * @ioc: per adapter object | 3141 | * @ioc: per adapter object |
3213 | * @update: update link information | 3142 | * @update: update link information |
@@ -3251,7 +3180,8 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) | |||
3251 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. | 3180 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. |
3252 | ControllerDevHandle); | 3181 | ControllerDevHandle); |
3253 | if (update) | 3182 | if (update) |
3254 | _scsih_link_change(ioc, | 3183 | mpt2sas_transport_update_links( |
3184 | ioc, | ||
3255 | ioc->sas_hba.phy[i].handle, | 3185 | ioc->sas_hba.phy[i].handle, |
3256 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. | 3186 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. |
3257 | AttachedDevHandle), i, | 3187 | AttachedDevHandle), i, |
@@ -3436,6 +3366,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3436 | if (!handle) | 3366 | if (!handle) |
3437 | return -1; | 3367 | return -1; |
3438 | 3368 | ||
3369 | if (ioc->shost_recovery) | ||
3370 | return -1; | ||
3371 | |||
3439 | if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, | 3372 | if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, |
3440 | MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { | 3373 | MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { |
3441 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3374 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
@@ -3572,6 +3505,9 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3572 | struct _sas_node *sas_expander; | 3505 | struct _sas_node *sas_expander; |
3573 | unsigned long flags; | 3506 | unsigned long flags; |
3574 | 3507 | ||
3508 | if (ioc->shost_recovery) | ||
3509 | return; | ||
3510 | |||
3575 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3511 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
3576 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); | 3512 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); |
3577 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 3513 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
@@ -3743,6 +3679,8 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3743 | mutex_unlock(&ioc->tm_cmds.mutex); | 3679 | mutex_unlock(&ioc->tm_cmds.mutex); |
3744 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset " | 3680 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset " |
3745 | "done: handle(0x%04x)\n", ioc->name, device_handle)); | 3681 | "done: handle(0x%04x)\n", ioc->name, device_handle)); |
3682 | if (ioc->shost_recovery) | ||
3683 | goto out; | ||
3746 | } | 3684 | } |
3747 | 3685 | ||
3748 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ | 3686 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ |
@@ -3765,6 +3703,9 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3765 | le32_to_cpu(mpi_reply.IOCLogInfo))); | 3703 | le32_to_cpu(mpi_reply.IOCLogInfo))); |
3766 | 3704 | ||
3767 | out: | 3705 | out: |
3706 | |||
3707 | _scsih_ublock_io_device(ioc, handle); | ||
3708 | |||
3768 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, | 3709 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, |
3769 | sas_device->parent_handle); | 3710 | sas_device->parent_handle); |
3770 | 3711 | ||
@@ -3908,6 +3849,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3908 | "expander event\n", ioc->name)); | 3849 | "expander event\n", ioc->name)); |
3909 | return; | 3850 | return; |
3910 | } | 3851 | } |
3852 | if (ioc->shost_recovery) | ||
3853 | return; | ||
3911 | if (event_data->PHY[i].PhyStatus & | 3854 | if (event_data->PHY[i].PhyStatus & |
3912 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) | 3855 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) |
3913 | continue; | 3856 | continue; |
@@ -3923,9 +3866,10 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3923 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 3866 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
3924 | if (!parent_handle) { | 3867 | if (!parent_handle) { |
3925 | if (phy_number < ioc->sas_hba.num_phys) | 3868 | if (phy_number < ioc->sas_hba.num_phys) |
3926 | _scsih_link_change(ioc, | 3869 | mpt2sas_transport_update_links( |
3927 | ioc->sas_hba.phy[phy_number].handle, | 3870 | ioc, |
3928 | handle, phy_number, link_rate_); | 3871 | ioc->sas_hba.phy[phy_number].handle, |
3872 | handle, phy_number, link_rate_); | ||
3929 | } else { | 3873 | } else { |
3930 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3874 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
3931 | sas_expander = | 3875 | sas_expander = |
@@ -3935,17 +3879,14 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3935 | flags); | 3879 | flags); |
3936 | if (sas_expander) { | 3880 | if (sas_expander) { |
3937 | if (phy_number < sas_expander->num_phys) | 3881 | if (phy_number < sas_expander->num_phys) |
3938 | _scsih_link_change(ioc, | 3882 | mpt2sas_transport_update_links( |
3939 | sas_expander-> | 3883 | ioc, |
3940 | phy[phy_number].handle, | 3884 | sas_expander-> |
3941 | handle, phy_number, | 3885 | phy[phy_number].handle, |
3942 | link_rate_); | 3886 | handle, phy_number, |
3887 | link_rate_); | ||
3943 | } | 3888 | } |
3944 | } | 3889 | } |
3945 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) { | ||
3946 | if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5) | ||
3947 | _scsih_ublock_io_device(ioc, handle); | ||
3948 | } | ||
3949 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) { | 3890 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) { |
3950 | if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5) | 3891 | if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5) |
3951 | break; | 3892 | break; |
@@ -4455,7 +4396,7 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
4455 | return; | 4396 | return; |
4456 | } | 4397 | } |
4457 | 4398 | ||
4458 | _scsih_link_change(ioc, | 4399 | mpt2sas_transport_update_links(ioc, |
4459 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 4400 | le16_to_cpu(sas_device_pg0.ParentDevHandle), |
4460 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 4401 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); |
4461 | 4402 | ||
@@ -4744,7 +4685,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4744 | return; | 4685 | return; |
4745 | } | 4686 | } |
4746 | 4687 | ||
4747 | _scsih_link_change(ioc, | 4688 | mpt2sas_transport_update_links(ioc, |
4748 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 4689 | le16_to_cpu(sas_device_pg0.ParentDevHandle), |
4749 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 4690 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); |
4750 | 4691 | ||
@@ -5156,22 +5097,9 @@ static void | |||
5156 | _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | 5097 | _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) |
5157 | { | 5098 | { |
5158 | struct _sas_device *sas_device, *sas_device_next; | 5099 | struct _sas_device *sas_device, *sas_device_next; |
5159 | struct _sas_node *sas_expander, *sas_expander_next; | 5100 | struct _sas_node *sas_expander; |
5160 | struct _raid_device *raid_device, *raid_device_next; | 5101 | struct _raid_device *raid_device, *raid_device_next; |
5161 | unsigned long flags; | ||
5162 | 5102 | ||
5163 | _scsih_search_responding_sas_devices(ioc); | ||
5164 | _scsih_search_responding_raid_devices(ioc); | ||
5165 | _scsih_search_responding_expanders(ioc); | ||
5166 | |||
5167 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
5168 | ioc->shost_recovery = 0; | ||
5169 | if (ioc->shost->shost_state == SHOST_RECOVERY) { | ||
5170 | printk(MPT2SAS_INFO_FMT "putting controller into " | ||
5171 | "SHOST_RUNNING\n", ioc->name); | ||
5172 | scsi_host_set_state(ioc->shost, SHOST_RUNNING); | ||
5173 | } | ||
5174 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
5175 | 5103 | ||
5176 | list_for_each_entry_safe(sas_device, sas_device_next, | 5104 | list_for_each_entry_safe(sas_device, sas_device_next, |
5177 | &ioc->sas_device_list, list) { | 5105 | &ioc->sas_device_list, list) { |
@@ -5207,16 +5135,63 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5207 | _scsih_raid_device_remove(ioc, raid_device); | 5135 | _scsih_raid_device_remove(ioc, raid_device); |
5208 | } | 5136 | } |
5209 | 5137 | ||
5210 | list_for_each_entry_safe(sas_expander, sas_expander_next, | 5138 | retry_expander_search: |
5211 | &ioc->sas_expander_list, list) { | 5139 | sas_expander = NULL; |
5140 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
5212 | if (sas_expander->responding) { | 5141 | if (sas_expander->responding) { |
5213 | sas_expander->responding = 0; | 5142 | sas_expander->responding = 0; |
5214 | continue; | 5143 | continue; |
5215 | } | 5144 | } |
5216 | printk("\tremoving expander: handle(0x%04x), " | ||
5217 | " sas_addr(0x%016llx)\n", sas_expander->handle, | ||
5218 | (unsigned long long)sas_expander->sas_address); | ||
5219 | _scsih_expander_remove(ioc, sas_expander->handle); | 5145 | _scsih_expander_remove(ioc, sas_expander->handle); |
5146 | goto retry_expander_search; | ||
5147 | } | ||
5148 | } | ||
5149 | |||
5150 | /** | ||
5151 | * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) | ||
5152 | * @ioc: per adapter object | ||
5153 | * @reset_phase: phase | ||
5154 | * | ||
5155 | * The handler for doing any required cleanup or initialization. | ||
5156 | * | ||
5157 | * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, | ||
5158 | * MPT2_IOC_DONE_RESET | ||
5159 | * | ||
5160 | * Return nothing. | ||
5161 | */ | ||
5162 | void | ||
5163 | mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | ||
5164 | { | ||
5165 | switch (reset_phase) { | ||
5166 | case MPT2_IOC_PRE_RESET: | ||
5167 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
5168 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
5169 | _scsih_fw_event_off(ioc); | ||
5170 | break; | ||
5171 | case MPT2_IOC_AFTER_RESET: | ||
5172 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
5173 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | ||
5174 | if (ioc->tm_cmds.status & MPT2_CMD_PENDING) { | ||
5175 | ioc->tm_cmds.status |= MPT2_CMD_RESET; | ||
5176 | mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid); | ||
5177 | complete(&ioc->tm_cmds.done); | ||
5178 | } | ||
5179 | _scsih_fw_event_on(ioc); | ||
5180 | _scsih_flush_running_cmds(ioc); | ||
5181 | break; | ||
5182 | case MPT2_IOC_DONE_RESET: | ||
5183 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
5184 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | ||
5185 | _scsih_sas_host_refresh(ioc, 0); | ||
5186 | _scsih_search_responding_sas_devices(ioc); | ||
5187 | _scsih_search_responding_raid_devices(ioc); | ||
5188 | _scsih_search_responding_expanders(ioc); | ||
5189 | break; | ||
5190 | case MPT2_IOC_RUNNING: | ||
5191 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | ||
5192 | "MPT2_IOC_RUNNING\n", ioc->name, __func__)); | ||
5193 | _scsih_remove_unresponding_devices(ioc); | ||
5194 | break; | ||
5220 | } | 5195 | } |
5221 | } | 5196 | } |
5222 | 5197 | ||
@@ -5236,14 +5211,6 @@ _firmware_event_work(struct work_struct *work) | |||
5236 | unsigned long flags; | 5211 | unsigned long flags; |
5237 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; | 5212 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; |
5238 | 5213 | ||
5239 | /* This is invoked by calling _scsih_queue_rescan(). */ | ||
5240 | if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) { | ||
5241 | _scsih_fw_event_free(ioc, fw_event); | ||
5242 | _scsih_sas_host_refresh(ioc, 1); | ||
5243 | _scsih_remove_unresponding_devices(ioc); | ||
5244 | return; | ||
5245 | } | ||
5246 | |||
5247 | /* the queue is being flushed so ignore this event */ | 5214 | /* the queue is being flushed so ignore this event */ |
5248 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 5215 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
5249 | if (ioc->fw_events_off || ioc->remove_host) { | 5216 | if (ioc->fw_events_off || ioc->remove_host) { |
@@ -5253,13 +5220,10 @@ _firmware_event_work(struct work_struct *work) | |||
5253 | } | 5220 | } |
5254 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 5221 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
5255 | 5222 | ||
5256 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
5257 | if (ioc->shost_recovery) { | 5223 | if (ioc->shost_recovery) { |
5258 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
5259 | _scsih_fw_event_requeue(ioc, fw_event, 1000); | 5224 | _scsih_fw_event_requeue(ioc, fw_event, 1000); |
5260 | return; | 5225 | return; |
5261 | } | 5226 | } |
5262 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
5263 | 5227 | ||
5264 | switch (fw_event->event) { | 5228 | switch (fw_event->event) { |
5265 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | 5229 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: |
@@ -5461,6 +5425,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5461 | if (!sas_device) | 5425 | if (!sas_device) |
5462 | continue; | 5426 | continue; |
5463 | _scsih_remove_device(ioc, sas_device->handle); | 5427 | _scsih_remove_device(ioc, sas_device->handle); |
5428 | if (ioc->shost_recovery) | ||
5429 | return; | ||
5464 | goto retry_device_search; | 5430 | goto retry_device_search; |
5465 | } | 5431 | } |
5466 | } | 5432 | } |
@@ -5482,6 +5448,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5482 | if (!expander_sibling) | 5448 | if (!expander_sibling) |
5483 | continue; | 5449 | continue; |
5484 | _scsih_expander_remove(ioc, expander_sibling->handle); | 5450 | _scsih_expander_remove(ioc, expander_sibling->handle); |
5451 | if (ioc->shost_recovery) | ||
5452 | return; | ||
5485 | goto retry_expander_search; | 5453 | goto retry_expander_search; |
5486 | } | 5454 | } |
5487 | } | 5455 | } |