diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 98 |
1 files changed, 67 insertions, 31 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index f3da592f7bcc..35a13867495e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work) | |||
119 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 119 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
120 | } | 120 | } |
121 | 121 | ||
122 | /** | ||
123 | * mpt2sas_base_start_watchdog - start the fault_reset_work_q | ||
124 | * @ioc: pointer to scsi command object | ||
125 | * Context: sleep. | ||
126 | * | ||
127 | * Return nothing. | ||
128 | */ | ||
129 | void | ||
130 | mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
131 | { | ||
132 | unsigned long flags; | ||
133 | |||
134 | if (ioc->fault_reset_work_q) | ||
135 | return; | ||
136 | |||
137 | /* initialize fault polling */ | ||
138 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
139 | snprintf(ioc->fault_reset_work_q_name, | ||
140 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
141 | ioc->fault_reset_work_q = | ||
142 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
143 | if (!ioc->fault_reset_work_q) { | ||
144 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
145 | ioc->name, __func__, __LINE__); | ||
146 | return; | ||
147 | } | ||
148 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
149 | if (ioc->fault_reset_work_q) | ||
150 | queue_delayed_work(ioc->fault_reset_work_q, | ||
151 | &ioc->fault_reset_work, | ||
152 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
153 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q | ||
158 | * @ioc: pointer to scsi command object | ||
159 | * Context: sleep. | ||
160 | * | ||
161 | * Return nothing. | ||
162 | */ | ||
163 | void | ||
164 | mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
165 | { | ||
166 | unsigned long flags; | ||
167 | struct workqueue_struct *wq; | ||
168 | |||
169 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
170 | wq = ioc->fault_reset_work_q; | ||
171 | ioc->fault_reset_work_q = NULL; | ||
172 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
173 | if (wq) { | ||
174 | if (!cancel_delayed_work(&ioc->fault_reset_work)) | ||
175 | flush_workqueue(wq); | ||
176 | destroy_workqueue(wq); | ||
177 | } | ||
178 | } | ||
179 | |||
122 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 180 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
123 | /** | 181 | /** |
124 | * _base_sas_ioc_info - verbose translation of the ioc status | 182 | * _base_sas_ioc_info - verbose translation of the ioc status |
@@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) | |||
440 | if (sas_loginfo.dw.bus_type != 3 /*SAS*/) | 498 | if (sas_loginfo.dw.bus_type != 3 /*SAS*/) |
441 | return; | 499 | return; |
442 | 500 | ||
501 | /* each nexus loss loginfo */ | ||
502 | if (log_info == 0x31170000) | ||
503 | return; | ||
504 | |||
443 | /* eat the loginfos associated with task aborts */ | 505 | /* eat the loginfos associated with task aborts */ |
444 | if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == | 506 | if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == |
445 | 0x31140000 || log_info == 0x31130000)) | 507 | 0x31140000 || log_info == 0x31130000)) |
@@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1109 | } | 1171 | } |
1110 | } | 1172 | } |
1111 | 1173 | ||
1112 | pci_set_drvdata(pdev, ioc->shost); | ||
1113 | _base_mask_interrupts(ioc); | 1174 | _base_mask_interrupts(ioc); |
1114 | r = _base_enable_msix(ioc); | 1175 | r = _base_enable_msix(ioc); |
1115 | if (r) | 1176 | if (r) |
@@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1132 | ioc->pci_irq = -1; | 1193 | ioc->pci_irq = -1; |
1133 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 1194 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
1134 | pci_disable_device(pdev); | 1195 | pci_disable_device(pdev); |
1135 | pci_set_drvdata(pdev, NULL); | ||
1136 | return r; | 1196 | return r; |
1137 | } | 1197 | } |
1138 | 1198 | ||
@@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
3191 | ioc->chip_phys = 0; | 3251 | ioc->chip_phys = 0; |
3192 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 3252 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
3193 | pci_disable_device(pdev); | 3253 | pci_disable_device(pdev); |
3194 | pci_set_drvdata(pdev, NULL); | ||
3195 | return; | 3254 | return; |
3196 | } | 3255 | } |
3197 | 3256 | ||
@@ -3205,7 +3264,6 @@ int | |||
3205 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | 3264 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) |
3206 | { | 3265 | { |
3207 | int r, i; | 3266 | int r, i; |
3208 | unsigned long flags; | ||
3209 | 3267 | ||
3210 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3268 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3211 | __func__)); | 3269 | __func__)); |
@@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3214 | if (r) | 3272 | if (r) |
3215 | return r; | 3273 | return r; |
3216 | 3274 | ||
3275 | pci_set_drvdata(ioc->pdev, ioc->shost); | ||
3217 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 3276 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
3218 | if (r) | 3277 | if (r) |
3219 | goto out_free_resources; | 3278 | goto out_free_resources; |
@@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3288 | if (r) | 3347 | if (r) |
3289 | goto out_free_resources; | 3348 | goto out_free_resources; |
3290 | 3349 | ||
3291 | /* initialize fault polling */ | 3350 | mpt2sas_base_start_watchdog(ioc); |
3292 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
3293 | snprintf(ioc->fault_reset_work_q_name, | ||
3294 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
3295 | ioc->fault_reset_work_q = | ||
3296 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
3297 | if (!ioc->fault_reset_work_q) { | ||
3298 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
3299 | ioc->name, __func__, __LINE__); | ||
3300 | goto out_free_resources; | ||
3301 | } | ||
3302 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
3303 | if (ioc->fault_reset_work_q) | ||
3304 | queue_delayed_work(ioc->fault_reset_work_q, | ||
3305 | &ioc->fault_reset_work, | ||
3306 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
3307 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3308 | return 0; | 3351 | return 0; |
3309 | 3352 | ||
3310 | out_free_resources: | 3353 | out_free_resources: |
@@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3312 | ioc->remove_host = 1; | 3355 | ioc->remove_host = 1; |
3313 | mpt2sas_base_free_resources(ioc); | 3356 | mpt2sas_base_free_resources(ioc); |
3314 | _base_release_memory_pools(ioc); | 3357 | _base_release_memory_pools(ioc); |
3358 | pci_set_drvdata(ioc->pdev, NULL); | ||
3315 | kfree(ioc->tm_cmds.reply); | 3359 | kfree(ioc->tm_cmds.reply); |
3316 | kfree(ioc->transport_cmds.reply); | 3360 | kfree(ioc->transport_cmds.reply); |
3317 | kfree(ioc->config_cmds.reply); | 3361 | kfree(ioc->config_cmds.reply); |
@@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3337 | void | 3381 | void |
3338 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | 3382 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) |
3339 | { | 3383 | { |
3340 | unsigned long flags; | ||
3341 | struct workqueue_struct *wq; | ||
3342 | 3384 | ||
3343 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3385 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3344 | __func__)); | 3386 | __func__)); |
3345 | 3387 | ||
3346 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3388 | mpt2sas_base_stop_watchdog(ioc); |
3347 | wq = ioc->fault_reset_work_q; | ||
3348 | ioc->fault_reset_work_q = NULL; | ||
3349 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3350 | if (!cancel_delayed_work(&ioc->fault_reset_work)) | ||
3351 | flush_workqueue(wq); | ||
3352 | destroy_workqueue(wq); | ||
3353 | |||
3354 | mpt2sas_base_free_resources(ioc); | 3389 | mpt2sas_base_free_resources(ioc); |
3355 | _base_release_memory_pools(ioc); | 3390 | _base_release_memory_pools(ioc); |
3391 | pci_set_drvdata(ioc->pdev, NULL); | ||
3356 | kfree(ioc->pfacts); | 3392 | kfree(ioc->pfacts); |
3357 | kfree(ioc->ctl_cmds.reply); | 3393 | kfree(ioc->ctl_cmds.reply); |
3358 | kfree(ioc->base_cmds.reply); | 3394 | kfree(ioc->base_cmds.reply); |