aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-05-29 07:21:32 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-09 18:42:34 -0400
commiteedf92b99806aeff18dc21c9dfb28999ce374413 (patch)
tree5273959ce99a8893b6eba8a186f9b3c4522a73e9
parentf9c34022eae9c76465dc2ec8805b9905e171ef40 (diff)
[SCSI] mpt fusion: Rescan SAS topology added
1.) SAS topology Rescan is added. If Firmware is doing Reset and we get Device add interrupt from Firmware, we will not receive it as part of Reset is going ON. After Reset we will do special Rescan of SAS topology. 2.) Driver version changed from 3.04.08 to 3.04.09. Added proper lock/unlock in mptsas_not_responding_devices() as per James' comment. Signed-off-by: Kashyap Desai <kadesai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/message/fusion/mptbase.h6
-rw-r--r--drivers/message/fusion/mptsas.c169
2 files changed, 172 insertions, 3 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 8d1aadb6b4ac..11fc8f3960a6 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
76#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR 76#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
77#endif 77#endif
78 78
79#define MPT_LINUX_VERSION_COMMON "3.04.08" 79#define MPT_LINUX_VERSION_COMMON "3.04.09"
80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.08" 80#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.09"
81#define WHAT_MAGIC_STRING "@" "(" "#" ")" 81#define WHAT_MAGIC_STRING "@" "(" "#" ")"
82 82
83#define show_mptmod_ver(s,ver) \ 83#define show_mptmod_ver(s,ver) \
@@ -711,6 +711,7 @@ typedef struct _MPT_ADAPTER
711 u16 hba_port_num_phy; 711 u16 hba_port_num_phy;
712 struct list_head sas_device_info_list; 712 struct list_head sas_device_info_list;
713 struct mutex sas_device_info_mutex; 713 struct mutex sas_device_info_mutex;
714 u8 old_sas_discovery_protocal;
714 u8 sas_discovery_quiesce_io; 715 u8 sas_discovery_quiesce_io;
715 int sas_index; /* index refrencing */ 716 int sas_index; /* index refrencing */
716 MPT_MGMT sas_mgmt; 717 MPT_MGMT sas_mgmt;
@@ -741,6 +742,7 @@ typedef struct _MPT_ADAPTER
741 spinlock_t fault_reset_work_lock; 742 spinlock_t fault_reset_work_lock;
742 743
743 u8 sg_addr_size; 744 u8 sg_addr_size;
745 u8 in_rescan;
744 u8 SGE_size; 746 u8 SGE_size;
745 747
746} MPT_ADAPTER; 748} MPT_ADAPTER;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 7f2f76f0db3f..6aa91268afe9 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -119,6 +119,8 @@ static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
119static void mptsas_expander_delete(MPT_ADAPTER *ioc, 119static void mptsas_expander_delete(MPT_ADAPTER *ioc,
120 struct mptsas_portinfo *port_info, u8 force); 120 struct mptsas_portinfo *port_info, u8 force);
121static void mptsas_send_expander_event(struct fw_event_work *fw_event); 121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
122 124
123static void mptsas_print_phy_data(MPT_ADAPTER *ioc, 125static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
124 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) 126 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -844,6 +846,24 @@ mptsas_queue_device_delete(MPT_ADAPTER *ioc,
844 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1)); 846 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
845} 847}
846 848
849static void
850mptsas_queue_rescan(MPT_ADAPTER *ioc)
851{
852 struct fw_event_work *fw_event;
853 int sz;
854
855 sz = offsetof(struct fw_event_work, event_data);
856 fw_event = kzalloc(sz, GFP_ATOMIC);
857 if (!fw_event) {
858 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
859 ioc->name, __func__, __LINE__);
860 return;
861 }
862 fw_event->event = -1;
863 fw_event->ioc = ioc;
864 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
865}
866
847 867
848/** 868/**
849 * mptsas_target_reset 869 * mptsas_target_reset
@@ -1100,6 +1120,7 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1100 complete(&ioc->sas_mgmt.done); 1120 complete(&ioc->sas_mgmt.done);
1101 } 1121 }
1102 mptsas_cleanup_fw_event_q(ioc); 1122 mptsas_cleanup_fw_event_q(ioc);
1123 mptsas_queue_rescan(ioc);
1103 mptsas_fw_event_on(ioc); 1124 mptsas_fw_event_on(ioc);
1104 break; 1125 break;
1105 default: 1126 default:
@@ -1406,6 +1427,23 @@ mptsas_firmware_event_work(struct work_struct *work)
1406 container_of(work, struct fw_event_work, work.work); 1427 container_of(work, struct fw_event_work, work.work);
1407 MPT_ADAPTER *ioc = fw_event->ioc; 1428 MPT_ADAPTER *ioc = fw_event->ioc;
1408 1429
1430 /* special rescan topology handling */
1431 if (fw_event->event == -1) {
1432 if (ioc->in_rescan) {
1433 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1434 "%s: rescan ignored as it is in progress\n",
1435 ioc->name, __func__));
1436 return;
1437 }
1438 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1439 "reset\n", ioc->name, __func__));
1440 ioc->in_rescan = 1;
1441 mptsas_not_responding_devices(ioc);
1442 mptsas_scan_sas_topology(ioc);
1443 ioc->in_rescan = 0;
1444 mptsas_free_fw_event(ioc, fw_event);
1445 return;
1446 }
1409 1447
1410 /* events handling turned off during host reset */ 1448 /* events handling turned off during host reset */
1411 if (ioc->fw_events_off) { 1449 if (ioc->fw_events_off) {
@@ -3153,8 +3191,15 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
3153 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 || 3191 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3154 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) { 3192 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3155 3193
3156 if (!port_info) 3194 if (!port_info) {
3195 if (ioc->old_sas_discovery_protocal) {
3196 port_info = mptsas_expander_add(ioc,
3197 le16_to_cpu(link_data->DevHandle));
3198 if (port_info)
3199 goto out;
3200 }
3157 goto out; 3201 goto out;
3202 }
3158 3203
3159 if (port_info == ioc->hba_port_info) 3204 if (port_info == ioc->hba_port_info)
3160 mptsas_probe_hba_phys(ioc); 3205 mptsas_probe_hba_phys(ioc);
@@ -3176,6 +3221,121 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
3176 mptsas_free_fw_event(ioc, fw_event); 3221 mptsas_free_fw_event(ioc, fw_event);
3177} 3222}
3178 3223
3224static void
3225mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3226{
3227 struct mptsas_portinfo buffer, *port_info;
3228 struct mptsas_device_info *sas_info;
3229 struct mptsas_devinfo sas_device;
3230 u32 handle;
3231 VirtTarget *vtarget = NULL;
3232 struct mptsas_phyinfo *phy_info;
3233 u8 found_expander;
3234 int retval, retry_count;
3235 unsigned long flags;
3236
3237 mpt_findImVolumes(ioc);
3238
3239 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3240 if (ioc->ioc_reset_in_progress) {
3241 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3242 "%s: exiting due to a parallel reset \n", ioc->name,
3243 __func__));
3244 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3245 return;
3246 }
3247 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3248
3249 /* devices, logical volumes */
3250 mutex_lock(&ioc->sas_device_info_mutex);
3251 redo_device_scan:
3252 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
3253 sas_device.handle = 0;
3254 retry_count = 0;
3255retry_page:
3256 retval = mptsas_sas_device_pg0(ioc, &sas_device,
3257 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3258 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3259 (sas_info->fw.channel << 8) +
3260 sas_info->fw.id);
3261
3262 if (sas_device.handle)
3263 continue;
3264 if (retval == -EBUSY) {
3265 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3266 if (ioc->ioc_reset_in_progress) {
3267 dfailprintk(ioc,
3268 printk(MYIOC_s_DEBUG_FMT
3269 "%s: exiting due to reset\n",
3270 ioc->name, __func__));
3271 spin_unlock_irqrestore
3272 (&ioc->taskmgmt_lock, flags);
3273 mutex_unlock(&ioc->sas_device_info_mutex);
3274 return;
3275 }
3276 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3277 flags);
3278 }
3279
3280 if (retval && (retval != -ENODEV)) {
3281 if (retry_count < 10) {
3282 retry_count++;
3283 goto retry_page;
3284 } else {
3285 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3286 "%s: Config page retry exceeded retry "
3287 "count deleting device 0x%llx\n",
3288 ioc->name, __func__,
3289 sas_info->sas_address));
3290 }
3291 }
3292
3293 /* delete device */
3294 vtarget = mptsas_find_vtarget(ioc,
3295 sas_info->fw.channel, sas_info->fw.id);
3296 if (vtarget)
3297 vtarget->deleted = 1;
3298 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3299 sas_info->sas_address);
3300 if (phy_info) {
3301 mptsas_del_end_device(ioc, phy_info);
3302 goto redo_device_scan;
3303 }
3304 }
3305 mutex_unlock(&ioc->sas_device_info_mutex);
3306
3307 /* expanders */
3308 mutex_lock(&ioc->sas_topology_mutex);
3309 redo_expander_scan:
3310 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3311
3312 if (port_info->phy_info &&
3313 (!(port_info->phy_info[0].identify.device_info &
3314 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3315 continue;
3316 found_expander = 0;
3317 handle = 0xFFFF;
3318 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3319 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3320 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3321 !found_expander) {
3322
3323 handle = buffer.phy_info[0].handle;
3324 if (buffer.phy_info[0].identify.sas_address ==
3325 port_info->phy_info[0].identify.sas_address) {
3326 found_expander = 1;
3327 }
3328 kfree(buffer.phy_info);
3329 }
3330
3331 if (!found_expander) {
3332 mptsas_expander_delete(ioc, port_info, 0);
3333 goto redo_expander_scan;
3334 }
3335 }
3336 mutex_lock(&ioc->sas_topology_mutex);
3337}
3338
3179/** 3339/**
3180 * mptsas_probe_expanders - adding expanders 3340 * mptsas_probe_expanders - adding expanders
3181 * @ioc: Pointer to MPT_ADAPTER structure 3341 * @ioc: Pointer to MPT_ADAPTER structure
@@ -3895,6 +4055,8 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3895 MpiEventDataSasExpanderStatusChange_t *expander_data = 4055 MpiEventDataSasExpanderStatusChange_t *expander_data =
3896 (MpiEventDataSasExpanderStatusChange_t *)reply->Data; 4056 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
3897 4057
4058 if (ioc->old_sas_discovery_protocal)
4059 return 0;
3898 4060
3899 if (expander_data->ReasonCode == 4061 if (expander_data->ReasonCode ==
3900 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING && 4062 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
@@ -3910,6 +4072,8 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3910 4072
3911 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus); 4073 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
3912 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0; 4074 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
4075 if (ioc->old_sas_discovery_protocal && !discovery_status)
4076 mptsas_queue_rescan(ioc);
3913 return 0; 4077 return 0;
3914 } 4078 }
3915 case MPI_EVENT_INTEGRATED_RAID: 4079 case MPI_EVENT_INTEGRATED_RAID:
@@ -4117,6 +4281,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
4117 goto out_mptsas_probe; 4281 goto out_mptsas_probe;
4118 } 4282 }
4119 4283
4284 /* older firmware doesn't support expander events */
4285 if ((ioc->facts.HeaderVersion >> 8) < 0xE)
4286 ioc->old_sas_discovery_protocal = 1;
4120 mptsas_scan_sas_topology(ioc); 4287 mptsas_scan_sas_topology(ioc);
4121 mptsas_fw_event_on(ioc); 4288 mptsas_fw_event_on(ioc);
4122 return 0; 4289 return 0;