aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_scsih.c
diff options
context:
space:
mode:
authornagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com>2011-10-19 06:06:26 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-30 04:35:57 -0400
commit921cd8024b908f8f49f772c8d3a02381b4db2ed2 (patch)
treea26f56a4a359cfe11551549f591469f5578abe6a /drivers/scsi/mpt2sas/mpt2sas_scsih.c
parentf9d979ce10c98dfd6d8d2a26217c3c4885ef97f6 (diff)
[SCSI] mpt2sas: New feature - Fast Load Support
New feature Fast Load Support. (1)Asynchronous SCSI scanning: This will allow the drivers to scan for devices in parallel while other device drivers are loading at the same time. This will improve the amount of time it takes for the OS to load. (2) Reporting Devices while port enable is active: This feature will allow devices to be reported to OS immediately while port enable is active. The previous implementation waits for port enable to complete, and then report devices. This feature is only enabled on IT firmware configurations when there are no boot device configured in BIOS Configuration Utility, else the driver will wait till port enable completes reporting devices. For IR firmware, this feature is turned off. This feature is to address large SAS topologies (>100 drives) when the boot OS is using onboard SATA device, in other words, the boot devices is not connected to our controller. (3) Scanning for devices after diagnostic reset completes: A new routine _scsih_scan_start is added. This will scan the expander pages, IR pages, and sas device pages, then reporting new devices to SCSI Mid layer. It seems the driver is not supporting adding devices while diagnostic reset is active. Apparently this is due to the sanity checks on ioc->shost_recovery flag throughout the context of kernel work thread FIFO, and the mpt2sas_fw_work. Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c423
1 files changed, 348 insertions, 75 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 1da1aa1a11e2..7a3865d9c959 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -71,6 +71,9 @@ static void _firmware_event_work(struct work_struct *work);
71 71
72static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); 72static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
73 73
74static void _scsih_scan_start(struct Scsi_Host *shost);
75static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
76
74/* global parameters */ 77/* global parameters */
75LIST_HEAD(mpt2sas_ioc_list); 78LIST_HEAD(mpt2sas_ioc_list);
76 79
@@ -79,6 +82,7 @@ static u8 scsi_io_cb_idx = -1;
79static u8 tm_cb_idx = -1; 82static u8 tm_cb_idx = -1;
80static u8 ctl_cb_idx = -1; 83static u8 ctl_cb_idx = -1;
81static u8 base_cb_idx = -1; 84static u8 base_cb_idx = -1;
85static u8 port_enable_cb_idx = -1;
82static u8 transport_cb_idx = -1; 86static u8 transport_cb_idx = -1;
83static u8 scsih_cb_idx = -1; 87static u8 scsih_cb_idx = -1;
84static u8 config_cb_idx = -1; 88static u8 config_cb_idx = -1;
@@ -103,6 +107,18 @@ static int max_lun = MPT2SAS_MAX_LUN;
103module_param(max_lun, int, 0); 107module_param(max_lun, int, 0);
104MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); 108MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
105 109
110/* diag_buffer_enable is bitwise
111 * bit 0 set = TRACE
112 * bit 1 set = SNAPSHOT
113 * bit 2 set = EXTENDED
114 *
115 * Either bit can be set, or both
116 */
117static int diag_buffer_enable = -1;
118module_param(diag_buffer_enable, int, 0);
119MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
120 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
121
106/** 122/**
107 * struct sense_info - common structure for obtaining sense keys 123 * struct sense_info - common structure for obtaining sense keys
108 * @skey: sense key 124 * @skey: sense key
@@ -117,8 +133,8 @@ struct sense_info {
117 133
118 134
119#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC) 135#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
120#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) 136#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
121 137#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
122/** 138/**
123 * struct fw_event_work - firmware event struct 139 * struct fw_event_work - firmware event struct
124 * @list: link list framework 140 * @list: link list framework
@@ -424,7 +440,11 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
424 u16 slot; 440 u16 slot;
425 441
426 /* only process this function when driver loads */ 442 /* only process this function when driver loads */
427 if (!ioc->wait_for_port_enable_to_complete) 443 if (!ioc->is_driver_loading)
444 return;
445
446 /* no Bios, return immediately */
447 if (!ioc->bios_pg3.BiosVersion)
428 return; 448 return;
429 449
430 if (!is_raid) { 450 if (!is_raid) {
@@ -2714,22 +2734,38 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
2714 2734
2715 2735
2716/** 2736/**
2717 * _scsih_queue_rescan - queue a topology rescan from user context 2737 * _scsih_error_recovery_delete_devices - remove devices not responding
2718 * @ioc: per adapter object 2738 * @ioc: per adapter object
2719 * 2739 *
2720 * Return nothing. 2740 * Return nothing.
2721 */ 2741 */
2722static void 2742static void
2723_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc) 2743_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
2724{ 2744{
2725 struct fw_event_work *fw_event; 2745 struct fw_event_work *fw_event;
2726 2746
2727 if (ioc->wait_for_port_enable_to_complete) 2747 if (ioc->is_driver_loading)
2728 return; 2748 return;
2749 fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
2750 fw_event->ioc = ioc;
2751 _scsih_fw_event_add(ioc, fw_event);
2752}
2753
2754/**
2755 * mpt2sas_port_enable_complete - port enable completed (fake event)
2756 * @ioc: per adapter object
2757 *
2758 * Return nothing.
2759 */
2760void
2761mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
2762{
2763 struct fw_event_work *fw_event;
2764
2729 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); 2765 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2730 if (!fw_event) 2766 if (!fw_event)
2731 return; 2767 return;
2732 fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET; 2768 fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
2733 fw_event->ioc = ioc; 2769 fw_event->ioc = ioc;
2734 _scsih_fw_event_add(ioc, fw_event); 2770 _scsih_fw_event_add(ioc, fw_event);
2735} 2771}
@@ -5099,7 +5135,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
5099 /* get device name */ 5135 /* get device name */
5100 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); 5136 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5101 5137
5102 if (ioc->wait_for_port_enable_to_complete) 5138 if (ioc->wait_for_discovery_to_complete)
5103 _scsih_sas_device_init_add(ioc, sas_device); 5139 _scsih_sas_device_init_add(ioc, sas_device);
5104 else 5140 else
5105 _scsih_sas_device_add(ioc, sas_device); 5141 _scsih_sas_device_add(ioc, sas_device);
@@ -5622,7 +5658,7 @@ broadcast_aen_retry:
5622 termination_count = 0; 5658 termination_count = 0;
5623 query_count = 0; 5659 query_count = 0;
5624 for (smid = 1; smid <= ioc->scsiio_depth; smid++) { 5660 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
5625 if (ioc->ioc_reset_in_progress_status) 5661 if (ioc->shost_recovery)
5626 goto out; 5662 goto out;
5627 scmd = _scsih_scsi_lookup_get(ioc, smid); 5663 scmd = _scsih_scsi_lookup_get(ioc, smid);
5628 if (!scmd) 5664 if (!scmd)
@@ -5644,7 +5680,7 @@ broadcast_aen_retry:
5644 lun = sas_device_priv_data->lun; 5680 lun = sas_device_priv_data->lun;
5645 query_count++; 5681 query_count++;
5646 5682
5647 if (ioc->ioc_reset_in_progress_status) 5683 if (ioc->shost_recovery)
5648 goto out; 5684 goto out;
5649 5685
5650 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 5686 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
@@ -5686,7 +5722,7 @@ broadcast_aen_retry:
5686 goto broadcast_aen_retry; 5722 goto broadcast_aen_retry;
5687 } 5723 }
5688 5724
5689 if (ioc->ioc_reset_in_progress_status) 5725 if (ioc->shost_recovery)
5690 goto out_no_lock; 5726 goto out_no_lock;
5691 5727
5692 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, 5728 r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
@@ -5725,7 +5761,7 @@ broadcast_aen_retry:
5725 ioc->name, __func__, query_count, termination_count)); 5761 ioc->name, __func__, query_count, termination_count));
5726 5762
5727 ioc->broadcast_aen_busy = 0; 5763 ioc->broadcast_aen_busy = 0;
5728 if (!ioc->ioc_reset_in_progress_status) 5764 if (!ioc->shost_recovery)
5729 _scsih_ublock_io_all_device(ioc); 5765 _scsih_ublock_io_all_device(ioc);
5730 mutex_unlock(&ioc->tm_cmds.mutex); 5766 mutex_unlock(&ioc->tm_cmds.mutex);
5731} 5767}
@@ -5845,7 +5881,7 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
5845 raid_device->handle = handle; 5881 raid_device->handle = handle;
5846 raid_device->wwid = wwid; 5882 raid_device->wwid = wwid;
5847 _scsih_raid_device_add(ioc, raid_device); 5883 _scsih_raid_device_add(ioc, raid_device);
5848 if (!ioc->wait_for_port_enable_to_complete) { 5884 if (!ioc->wait_for_discovery_to_complete) {
5849 rc = scsi_add_device(ioc->shost, RAID_CHANNEL, 5885 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
5850 raid_device->id, 0); 5886 raid_device->id, 0);
5851 if (rc) 5887 if (rc)
@@ -6127,6 +6163,10 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
6127 _scsih_sas_ir_config_change_event_debug(ioc, event_data); 6163 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6128 6164
6129#endif 6165#endif
6166
6167 if (ioc->shost_recovery)
6168 return;
6169
6130 foreign_config = (le32_to_cpu(event_data->Flags) & 6170 foreign_config = (le32_to_cpu(event_data->Flags) &
6131 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; 6171 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6132 6172
@@ -6185,6 +6225,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
6185 int rc; 6225 int rc;
6186 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; 6226 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
6187 6227
6228 if (ioc->shost_recovery)
6229 return;
6230
6188 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) 6231 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6189 return; 6232 return;
6190 6233
@@ -6267,6 +6310,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
6267 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; 6310 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
6268 u64 sas_address; 6311 u64 sas_address;
6269 6312
6313 if (ioc->shost_recovery)
6314 return;
6315
6270 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) 6316 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6271 return; 6317 return;
6272 6318
@@ -6510,10 +6556,10 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6510 u32 device_info; 6556 u32 device_info;
6511 u16 slot; 6557 u16 slot;
6512 6558
6513 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); 6559 printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
6514 6560
6515 if (list_empty(&ioc->sas_device_list)) 6561 if (list_empty(&ioc->sas_device_list))
6516 return; 6562 goto out;
6517 6563
6518 handle = 0xFFFF; 6564 handle = 0xFFFF;
6519 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, 6565 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -6532,6 +6578,9 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6532 _scsih_mark_responding_sas_device(ioc, sas_address, slot, 6578 _scsih_mark_responding_sas_device(ioc, sas_address, slot,
6533 handle); 6579 handle);
6534 } 6580 }
6581out:
6582 printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
6583 ioc->name);
6535} 6584}
6536 6585
6537/** 6586/**
@@ -6607,10 +6656,14 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
6607 u16 handle; 6656 u16 handle;
6608 u8 phys_disk_num; 6657 u8 phys_disk_num;
6609 6658
6610 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); 6659 if (!ioc->ir_firmware)
6660 return;
6661
6662 printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
6663 ioc->name);
6611 6664
6612 if (list_empty(&ioc->raid_device_list)) 6665 if (list_empty(&ioc->raid_device_list))
6613 return; 6666 goto out;
6614 6667
6615 handle = 0xFFFF; 6668 handle = 0xFFFF;
6616 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, 6669 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -6649,6 +6702,9 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
6649 set_bit(handle, ioc->pd_handles); 6702 set_bit(handle, ioc->pd_handles);
6650 } 6703 }
6651 } 6704 }
6705out:
6706 printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
6707 "complete\n", ioc->name);
6652} 6708}
6653 6709
6654/** 6710/**
@@ -6708,10 +6764,10 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
6708 u64 sas_address; 6764 u64 sas_address;
6709 u16 handle; 6765 u16 handle;
6710 6766
6711 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); 6767 printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
6712 6768
6713 if (list_empty(&ioc->sas_expander_list)) 6769 if (list_empty(&ioc->sas_expander_list))
6714 return; 6770 goto out;
6715 6771
6716 handle = 0xFFFF; 6772 handle = 0xFFFF;
6717 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, 6773 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
@@ -6730,6 +6786,8 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
6730 _scsih_mark_responding_expander(ioc, sas_address, handle); 6786 _scsih_mark_responding_expander(ioc, sas_address, handle);
6731 } 6787 }
6732 6788
6789 out:
6790 printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
6733} 6791}
6734 6792
6735/** 6793/**
@@ -6745,6 +6803,8 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6745 struct _sas_node *sas_expander; 6803 struct _sas_node *sas_expander;
6746 struct _raid_device *raid_device, *raid_device_next; 6804 struct _raid_device *raid_device, *raid_device_next;
6747 6805
6806 printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
6807 ioc->name);
6748 6808
6749 list_for_each_entry_safe(sas_device, sas_device_next, 6809 list_for_each_entry_safe(sas_device, sas_device_next,
6750 &ioc->sas_device_list, list) { 6810 &ioc->sas_device_list, list) {
@@ -6764,6 +6824,9 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6764 _scsih_remove_device(ioc, sas_device); 6824 _scsih_remove_device(ioc, sas_device);
6765 } 6825 }
6766 6826
6827 if (!ioc->ir_firmware)
6828 goto retry_expander_search;
6829
6767 list_for_each_entry_safe(raid_device, raid_device_next, 6830 list_for_each_entry_safe(raid_device, raid_device_next,
6768 &ioc->raid_device_list, list) { 6831 &ioc->raid_device_list, list) {
6769 if (raid_device->responding) { 6832 if (raid_device->responding) {
@@ -6790,52 +6853,170 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6790 mpt2sas_expander_remove(ioc, sas_expander->sas_address); 6853 mpt2sas_expander_remove(ioc, sas_expander->sas_address);
6791 goto retry_expander_search; 6854 goto retry_expander_search;
6792 } 6855 }
6856 printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
6857 ioc->name);
6858 /* unblock devices */
6859 _scsih_ublock_io_all_device(ioc);
6860}
6861
6862static void
6863_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
6864 struct _sas_node *sas_expander, u16 handle)
6865{
6866 Mpi2ExpanderPage1_t expander_pg1;
6867 Mpi2ConfigReply_t mpi_reply;
6868 int i;
6869
6870 for (i = 0 ; i < sas_expander->num_phys ; i++) {
6871 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
6872 &expander_pg1, i, handle))) {
6873 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
6874 ioc->name, __FILE__, __LINE__, __func__);
6875 return;
6876 }
6877
6878 mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
6879 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
6880 expander_pg1.NegotiatedLinkRate >> 4);
6881 }
6793} 6882}
6794 6883
6795/** 6884/**
6796 * _scsih_hide_unhide_sas_devices - add/remove device to/from OS 6885 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
6797 * @ioc: per adapter object 6886 * @ioc: per adapter object
6798 * 6887 *
6799 * Return nothing. 6888 * Return nothing.
6800 */ 6889 */
6801static void 6890static void
6802_scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc) 6891_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
6803{ 6892{
6804 struct _sas_device *sas_device, *sas_device_next; 6893 Mpi2ExpanderPage0_t expander_pg0;
6894 Mpi2SasDevicePage0_t sas_device_pg0;
6895 Mpi2RaidVolPage1_t volume_pg1;
6896 Mpi2RaidVolPage0_t volume_pg0;
6897 Mpi2RaidPhysDiskPage0_t pd_pg0;
6898 Mpi2EventIrConfigElement_t element;
6899 Mpi2ConfigReply_t mpi_reply;
6900 u8 phys_disk_num;
6901 u16 ioc_status;
6902 u16 handle, parent_handle;
6903 u64 sas_address;
6904 struct _sas_device *sas_device;
6905 struct _sas_node *expander_device;
6906 static struct _raid_device *raid_device;
6805 6907
6806 if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag != 6908 printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
6807 MFG_PAGE10_HIDE_IF_VOL_PRESENT)
6808 return;
6809 6909
6810 if (ioc->hide_drives) { 6910 _scsih_sas_host_refresh(ioc);
6811 if (_scsih_get_num_volumes(ioc)) 6911
6812 return; 6912 /* expanders */
6813 ioc->hide_drives = 0; 6913 handle = 0xFFFF;
6814 list_for_each_entry_safe(sas_device, sas_device_next, 6914 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6815 &ioc->sas_device_list, list) { 6915 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6816 if (!mpt2sas_transport_port_add(ioc, sas_device->handle, 6916 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6817 sas_device->sas_address_parent)) { 6917 MPI2_IOCSTATUS_MASK;
6818 _scsih_sas_device_remove(ioc, sas_device); 6918 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6819 } else if (!sas_device->starget) { 6919 break;
6820 mpt2sas_transport_port_remove(ioc, 6920 handle = le16_to_cpu(expander_pg0.DevHandle);
6821 sas_device->sas_address, 6921 expander_device = mpt2sas_scsih_expander_find_by_sas_address(
6822 sas_device->sas_address_parent); 6922 ioc, le64_to_cpu(expander_pg0.SASAddress));
6823 _scsih_sas_device_remove(ioc, sas_device); 6923 if (expander_device)
6824 } 6924 _scsih_refresh_expander_links(ioc, expander_device,
6925 handle);
6926 else
6927 _scsih_expander_add(ioc, handle);
6928 }
6929
6930 if (!ioc->ir_firmware)
6931 goto skip_to_sas;
6932
6933 /* phys disk */
6934 phys_disk_num = 0xFF;
6935 while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6936 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6937 phys_disk_num))) {
6938 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6939 MPI2_IOCSTATUS_MASK;
6940 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6941 break;
6942 phys_disk_num = pd_pg0.PhysDiskNum;
6943 handle = le16_to_cpu(pd_pg0.DevHandle);
6944 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6945 if (sas_device)
6946 continue;
6947 if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6948 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6949 handle) != 0)
6950 continue;
6951 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6952 if (!_scsih_get_sas_address(ioc, parent_handle,
6953 &sas_address)) {
6954 mpt2sas_transport_update_links(ioc, sas_address,
6955 handle, sas_device_pg0.PhyNum,
6956 MPI2_SAS_NEG_LINK_RATE_1_5);
6957 set_bit(handle, ioc->pd_handles);
6958 _scsih_add_device(ioc, handle, 0, 1);
6825 } 6959 }
6826 } else { 6960 }
6827 if (!_scsih_get_num_volumes(ioc)) 6961
6828 return; 6962 /* volumes */
6829 ioc->hide_drives = 1; 6963 handle = 0xFFFF;
6830 list_for_each_entry_safe(sas_device, sas_device_next, 6964 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6831 &ioc->sas_device_list, list) { 6965 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6832 mpt2sas_transport_port_remove(ioc, 6966 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6833 sas_device->sas_address, 6967 MPI2_IOCSTATUS_MASK;
6834 sas_device->sas_address_parent); 6968 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6969 break;
6970 handle = le16_to_cpu(volume_pg1.DevHandle);
6971 raid_device = _scsih_raid_device_find_by_wwid(ioc,
6972 le64_to_cpu(volume_pg1.WWID));
6973 if (raid_device)
6974 continue;
6975 if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6976 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6977 sizeof(Mpi2RaidVolPage0_t)))
6978 continue;
6979 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6980 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6981 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
6982 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
6983 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
6984 element.VolDevHandle = volume_pg1.DevHandle;
6985 _scsih_sas_volume_add(ioc, &element);
6986 }
6987 }
6988
6989 skip_to_sas:
6990
6991 /* sas devices */
6992 handle = 0xFFFF;
6993 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6994 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6995 handle))) {
6996 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6997 MPI2_IOCSTATUS_MASK;
6998 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6999 break;
7000 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7001 if (!(_scsih_is_end_device(
7002 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7003 continue;
7004 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
7005 le64_to_cpu(sas_device_pg0.SASAddress));
7006 if (sas_device)
7007 continue;
7008 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7009 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7010 mpt2sas_transport_update_links(ioc, sas_address, handle,
7011 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7012 _scsih_add_device(ioc, handle, 0, 0);
6835 } 7013 }
6836 } 7014 }
7015
7016 printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
6837} 7017}
6838 7018
7019
6839/** 7020/**
6840 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) 7021 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
6841 * @ioc: per adapter object 7022 * @ioc: per adapter object
@@ -6871,7 +7052,6 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
6871 } 7052 }
6872 _scsih_fw_event_cleanup_queue(ioc); 7053 _scsih_fw_event_cleanup_queue(ioc);
6873 _scsih_flush_running_cmds(ioc); 7054 _scsih_flush_running_cmds(ioc);
6874 _scsih_queue_rescan(ioc);
6875 break; 7055 break;
6876 case MPT2_IOC_DONE_RESET: 7056 case MPT2_IOC_DONE_RESET:
6877 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " 7057 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
@@ -6881,6 +7061,7 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
6881 _scsih_search_responding_sas_devices(ioc); 7061 _scsih_search_responding_sas_devices(ioc);
6882 _scsih_search_responding_raid_devices(ioc); 7062 _scsih_search_responding_raid_devices(ioc);
6883 _scsih_search_responding_expanders(ioc); 7063 _scsih_search_responding_expanders(ioc);
7064 _scsih_error_recovery_delete_devices(ioc);
6884 break; 7065 break;
6885 } 7066 }
6886} 7067}
@@ -6898,7 +7079,6 @@ _firmware_event_work(struct work_struct *work)
6898{ 7079{
6899 struct fw_event_work *fw_event = container_of(work, 7080 struct fw_event_work *fw_event = container_of(work,
6900 struct fw_event_work, delayed_work.work); 7081 struct fw_event_work, delayed_work.work);
6901 unsigned long flags;
6902 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; 7082 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
6903 7083
6904 /* the queue is being flushed so ignore this event */ 7084 /* the queue is being flushed so ignore this event */
@@ -6908,23 +7088,31 @@ _firmware_event_work(struct work_struct *work)
6908 return; 7088 return;
6909 } 7089 }
6910 7090
6911 if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) { 7091 switch (fw_event->event) {
6912 _scsih_fw_event_free(ioc, fw_event); 7092 case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
6913 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 7093 while (scsi_host_in_recovery(ioc->shost))
6914 if (ioc->shost_recovery) { 7094 ssleep(1);
6915 init_completion(&ioc->shost_recovery_done);
6916 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
6917 flags);
6918 wait_for_completion(&ioc->shost_recovery_done);
6919 } else
6920 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
6921 flags);
6922 _scsih_remove_unresponding_sas_devices(ioc); 7095 _scsih_remove_unresponding_sas_devices(ioc);
6923 _scsih_hide_unhide_sas_devices(ioc); 7096 _scsih_scan_for_devices_after_reset(ioc);
6924 return; 7097 break;
6925 } 7098 case MPT2SAS_PORT_ENABLE_COMPLETE:
7099 if (!ioc->is_driver_loading && ioc->shost_recovery) {
7100 _scsih_prep_device_scan(ioc);
7101 _scsih_search_responding_sas_devices(ioc);
7102 _scsih_search_responding_raid_devices(ioc);
7103 _scsih_search_responding_expanders(ioc);
7104 }
6926 7105
6927 switch (fw_event->event) { 7106 if (ioc->start_scan)
7107 ioc->start_scan = 0;
7108 else
7109 complete(&ioc->port_enable_done);
7110
7111
7112
7113 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
7114 "from worker thread\n", ioc->name));
7115 break;
6928 case MPT2SAS_TURN_ON_FAULT_LED: 7116 case MPT2SAS_TURN_ON_FAULT_LED:
6929 _scsih_turn_on_fault_led(ioc, fw_event->device_handle); 7117 _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
6930 break; 7118 break;
@@ -7121,6 +7309,8 @@ static struct scsi_host_template scsih_driver_template = {
7121 .slave_configure = _scsih_slave_configure, 7309 .slave_configure = _scsih_slave_configure,
7122 .target_destroy = _scsih_target_destroy, 7310 .target_destroy = _scsih_target_destroy,
7123 .slave_destroy = _scsih_slave_destroy, 7311 .slave_destroy = _scsih_slave_destroy,
7312 .scan_finished = _scsih_scan_finished,
7313 .scan_start = _scsih_scan_start,
7124 .change_queue_depth = _scsih_change_queue_depth, 7314 .change_queue_depth = _scsih_change_queue_depth,
7125 .change_queue_type = _scsih_change_queue_type, 7315 .change_queue_type = _scsih_change_queue_type,
7126 .eh_abort_handler = _scsih_abort, 7316 .eh_abort_handler = _scsih_abort,
@@ -7381,7 +7571,12 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
7381 unsigned long flags; 7571 unsigned long flags;
7382 int rc; 7572 int rc;
7383 7573
7574 /* no Bios, return immediately */
7575 if (!ioc->bios_pg3.BiosVersion)
7576 return;
7577
7384 device = NULL; 7578 device = NULL;
7579 is_raid = 0;
7385 if (ioc->req_boot_device.device) { 7580 if (ioc->req_boot_device.device) {
7386 device = ioc->req_boot_device.device; 7581 device = ioc->req_boot_device.device;
7387 is_raid = ioc->req_boot_device.is_raid; 7582 is_raid = ioc->req_boot_device.is_raid;
@@ -7490,9 +7685,7 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
7490static void 7685static void
7491_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) 7686_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
7492{ 7687{
7493 u16 volume_mapping_flags = 7688 u16 volume_mapping_flags;
7494 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
7495 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
7496 7689
7497 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) 7690 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
7498 return; /* return when IOC doesn't support initiator mode */ 7691 return; /* return when IOC doesn't support initiator mode */
@@ -7500,18 +7693,93 @@ _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
7500 _scsih_probe_boot_devices(ioc); 7693 _scsih_probe_boot_devices(ioc);
7501 7694
7502 if (ioc->ir_firmware) { 7695 if (ioc->ir_firmware) {
7503 if ((volume_mapping_flags & 7696 volume_mapping_flags =
7504 MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) { 7697 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
7505 _scsih_probe_sas(ioc); 7698 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
7699 if (volume_mapping_flags ==
7700 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
7506 _scsih_probe_raid(ioc); 7701 _scsih_probe_raid(ioc);
7702 _scsih_probe_sas(ioc);
7507 } else { 7703 } else {
7508 _scsih_probe_raid(ioc);
7509 _scsih_probe_sas(ioc); 7704 _scsih_probe_sas(ioc);
7705 _scsih_probe_raid(ioc);
7510 } 7706 }
7511 } else 7707 } else
7512 _scsih_probe_sas(ioc); 7708 _scsih_probe_sas(ioc);
7513} 7709}
7514 7710
7711
7712/**
7713 * _scsih_scan_start - scsi lld callback for .scan_start
7714 * @shost: SCSI host pointer
7715 *
7716 * The shost has the ability to discover targets on its own instead
7717 * of scanning the entire bus. In our implemention, we will kick off
7718 * firmware discovery.
7719 */
7720static void
7721_scsih_scan_start(struct Scsi_Host *shost)
7722{
7723 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7724 int rc;
7725
7726 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
7727 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
7728
7729 ioc->start_scan = 1;
7730 rc = mpt2sas_port_enable(ioc);
7731
7732 if (rc != 0)
7733 printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
7734}
7735
7736/**
7737 * _scsih_scan_finished - scsi lld callback for .scan_finished
7738 * @shost: SCSI host pointer
7739 * @time: elapsed time of the scan in jiffies
7740 *
7741 * This function will be called periodically until it returns 1 with the
7742 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
7743 * we wait for firmware discovery to complete, then return 1.
7744 */
7745static int
7746_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
7747{
7748 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
7749
7750 if (time >= (300 * HZ)) {
7751 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7752 printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
7753 "(timeout=300s)\n", ioc->name);
7754 ioc->is_driver_loading = 0;
7755 return 1;
7756 }
7757
7758 if (ioc->start_scan)
7759 return 0;
7760
7761 if (ioc->start_scan_failed) {
7762 printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
7763 "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
7764 ioc->is_driver_loading = 0;
7765 ioc->wait_for_discovery_to_complete = 0;
7766 ioc->remove_host = 1;
7767 return 1;
7768 }
7769
7770 printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
7771 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
7772
7773 if (ioc->wait_for_discovery_to_complete) {
7774 ioc->wait_for_discovery_to_complete = 0;
7775 _scsih_probe_devices(ioc);
7776 }
7777 mpt2sas_base_start_watchdog(ioc);
7778 ioc->is_driver_loading = 0;
7779 return 1;
7780}
7781
7782
7515/** 7783/**
7516 * _scsih_probe - attach and add scsi host 7784 * _scsih_probe - attach and add scsi host
7517 * @pdev: PCI device struct 7785 * @pdev: PCI device struct
@@ -7548,6 +7816,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
7548 ioc->tm_cb_idx = tm_cb_idx; 7816 ioc->tm_cb_idx = tm_cb_idx;
7549 ioc->ctl_cb_idx = ctl_cb_idx; 7817 ioc->ctl_cb_idx = ctl_cb_idx;
7550 ioc->base_cb_idx = base_cb_idx; 7818 ioc->base_cb_idx = base_cb_idx;
7819 ioc->port_enable_cb_idx = port_enable_cb_idx;
7551 ioc->transport_cb_idx = transport_cb_idx; 7820 ioc->transport_cb_idx = transport_cb_idx;
7552 ioc->scsih_cb_idx = scsih_cb_idx; 7821 ioc->scsih_cb_idx = scsih_cb_idx;
7553 ioc->config_cb_idx = config_cb_idx; 7822 ioc->config_cb_idx = config_cb_idx;
@@ -7620,14 +7889,14 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
7620 goto out_thread_fail; 7889 goto out_thread_fail;
7621 } 7890 }
7622 7891
7623 ioc->wait_for_port_enable_to_complete = 1; 7892 ioc->is_driver_loading = 1;
7624 if ((mpt2sas_base_attach(ioc))) { 7893 if ((mpt2sas_base_attach(ioc))) {
7625 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", 7894 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
7626 ioc->name, __FILE__, __LINE__, __func__); 7895 ioc->name, __FILE__, __LINE__, __func__);
7627 goto out_attach_fail; 7896 goto out_attach_fail;
7628 } 7897 }
7629 7898
7630 ioc->wait_for_port_enable_to_complete = 0; 7899 scsi_scan_host(shost);
7631 if (ioc->is_warpdrive) { 7900 if (ioc->is_warpdrive) {
7632 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) 7901 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
7633 ioc->hide_drives = 0; 7902 ioc->hide_drives = 0;
@@ -7650,6 +7919,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
7650 out_thread_fail: 7919 out_thread_fail:
7651 list_del(&ioc->list); 7920 list_del(&ioc->list);
7652 scsi_remove_host(shost); 7921 scsi_remove_host(shost);
7922 scsi_host_put(shost);
7653 out_add_shost_fail: 7923 out_add_shost_fail:
7654 return -ENODEV; 7924 return -ENODEV;
7655} 7925}
@@ -7896,6 +8166,8 @@ _scsih_init(void)
7896 8166
7897 /* base internal commands callback handler */ 8167 /* base internal commands callback handler */
7898 base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done); 8168 base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
8169 port_enable_cb_idx = mpt2sas_base_register_callback_handler(
8170 mpt2sas_port_enable_done);
7899 8171
7900 /* transport internal commands callback handler */ 8172 /* transport internal commands callback handler */
7901 transport_cb_idx = mpt2sas_base_register_callback_handler( 8173 transport_cb_idx = mpt2sas_base_register_callback_handler(
@@ -7950,6 +8222,7 @@ _scsih_exit(void)
7950 mpt2sas_base_release_callback_handler(scsi_io_cb_idx); 8222 mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
7951 mpt2sas_base_release_callback_handler(tm_cb_idx); 8223 mpt2sas_base_release_callback_handler(tm_cb_idx);
7952 mpt2sas_base_release_callback_handler(base_cb_idx); 8224 mpt2sas_base_release_callback_handler(base_cb_idx);
8225 mpt2sas_base_release_callback_handler(port_enable_cb_idx);
7953 mpt2sas_base_release_callback_handler(transport_cb_idx); 8226 mpt2sas_base_release_callback_handler(transport_cb_idx);
7954 mpt2sas_base_release_callback_handler(scsih_cb_idx); 8227 mpt2sas_base_release_callback_handler(scsih_cb_idx);
7955 mpt2sas_base_release_callback_handler(config_cb_idx); 8228 mpt2sas_base_release_callback_handler(config_cb_idx);