diff options
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 88 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 2 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 2 |
3 files changed, 64 insertions, 28 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index ed9965e4b96b..c29c4f9851b9 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 |
@@ -3209,7 +3267,6 @@ int | |||
3209 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | 3267 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) |
3210 | { | 3268 | { |
3211 | int r, i; | 3269 | int r, i; |
3212 | unsigned long flags; | ||
3213 | 3270 | ||
3214 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3271 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3215 | __func__)); | 3272 | __func__)); |
@@ -3292,23 +3349,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3292 | if (r) | 3349 | if (r) |
3293 | goto out_free_resources; | 3350 | goto out_free_resources; |
3294 | 3351 | ||
3295 | /* initialize fault polling */ | 3352 | mpt2sas_base_start_watchdog(ioc); |
3296 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
3297 | snprintf(ioc->fault_reset_work_q_name, | ||
3298 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
3299 | ioc->fault_reset_work_q = | ||
3300 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
3301 | if (!ioc->fault_reset_work_q) { | ||
3302 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
3303 | ioc->name, __func__, __LINE__); | ||
3304 | goto out_free_resources; | ||
3305 | } | ||
3306 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
3307 | if (ioc->fault_reset_work_q) | ||
3308 | queue_delayed_work(ioc->fault_reset_work_q, | ||
3309 | &ioc->fault_reset_work, | ||
3310 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
3311 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3312 | return 0; | 3353 | return 0; |
3313 | 3354 | ||
3314 | out_free_resources: | 3355 | out_free_resources: |
@@ -3341,20 +3382,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3341 | void | 3382 | void |
3342 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | 3383 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) |
3343 | { | 3384 | { |
3344 | unsigned long flags; | ||
3345 | struct workqueue_struct *wq; | ||
3346 | 3385 | ||
3347 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3386 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3348 | __func__)); | 3387 | __func__)); |
3349 | 3388 | ||
3350 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3389 | mpt2sas_base_stop_watchdog(ioc); |
3351 | wq = ioc->fault_reset_work_q; | ||
3352 | ioc->fault_reset_work_q = NULL; | ||
3353 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3354 | if (!cancel_delayed_work(&ioc->fault_reset_work)) | ||
3355 | flush_workqueue(wq); | ||
3356 | destroy_workqueue(wq); | ||
3357 | |||
3358 | mpt2sas_base_free_resources(ioc); | 3390 | mpt2sas_base_free_resources(ioc); |
3359 | _base_release_memory_pools(ioc); | 3391 | _base_release_memory_pools(ioc); |
3360 | kfree(ioc->pfacts); | 3392 | kfree(ioc->pfacts); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 286c185fa9e4..a29935726e7a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | |||
673 | 673 | ||
674 | /* base shared API */ | 674 | /* base shared API */ |
675 | extern struct list_head mpt2sas_ioc_list; | 675 | extern struct list_head mpt2sas_ioc_list; |
676 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
677 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
676 | 678 | ||
677 | int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); | 679 | int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); |
678 | void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); | 680 | void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 25c8d8294af6..2e9a4445596f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -5824,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5824 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | 5824 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); |
5825 | u32 device_state; | 5825 | u32 device_state; |
5826 | 5826 | ||
5827 | mpt2sas_base_stop_watchdog(ioc); | ||
5827 | flush_scheduled_work(); | 5828 | flush_scheduled_work(); |
5828 | scsi_block_requests(shost); | 5829 | scsi_block_requests(shost); |
5829 | device_state = pci_choose_state(pdev, state); | 5830 | device_state = pci_choose_state(pdev, state); |
@@ -5866,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev) | |||
5866 | 5867 | ||
5867 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); | 5868 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); |
5868 | scsi_unblock_requests(shost); | 5869 | scsi_unblock_requests(shost); |
5870 | mpt2sas_base_start_watchdog(ioc); | ||
5869 | return 0; | 5871 | return 0; |
5870 | } | 5872 | } |
5871 | #endif /* CONFIG_PM */ | 5873 | #endif /* CONFIG_PM */ |