diff options
-rw-r--r-- | drivers/message/fusion/mptbase.h | 6 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 169 |
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 | |||
119 | static void mptsas_expander_delete(MPT_ADAPTER *ioc, | 119 | static void mptsas_expander_delete(MPT_ADAPTER *ioc, |
120 | struct mptsas_portinfo *port_info, u8 force); | 120 | struct mptsas_portinfo *port_info, u8 force); |
121 | static void mptsas_send_expander_event(struct fw_event_work *fw_event); | 121 | static void mptsas_send_expander_event(struct fw_event_work *fw_event); |
122 | static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); | ||
123 | static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); | ||
122 | 124 | ||
123 | static void mptsas_print_phy_data(MPT_ADAPTER *ioc, | 125 | static 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 | ||
849 | static void | ||
850 | mptsas_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 | ||
3224 | static void | ||
3225 | mptsas_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; | ||
3255 | retry_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; |