aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 30a800effe51..9bc35617b871 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -253,6 +253,55 @@ mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
253 return 0; 253 return 0;
254} 254}
255 255
256/**
257 * mpt_fault_reset_work - work performed on workq after ioc fault
258 * @work: input argument, used to derive ioc
259 *
260**/
261static void
262mpt_fault_reset_work(struct work_struct *work)
263{
264 MPT_ADAPTER *ioc =
265 container_of(work, MPT_ADAPTER, fault_reset_work.work);
266 u32 ioc_raw_state;
267 int rc;
268 unsigned long flags;
269
270 if (ioc->diagPending || !ioc->active)
271 goto out;
272
273 ioc_raw_state = mpt_GetIocState(ioc, 0);
274 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
275 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
276 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
277 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
278 ioc->name, __FUNCTION__);
279 rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
280 printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
281 __FUNCTION__, (rc == 0) ? "success" : "failed");
282 ioc_raw_state = mpt_GetIocState(ioc, 0);
283 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
284 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
285 "reset (%04xh)\n", ioc->name, ioc_raw_state &
286 MPI_DOORBELL_DATA_MASK);
287 }
288
289 out:
290 /*
291 * Take turns polling alternate controller
292 */
293 if (ioc->alt_ioc)
294 ioc = ioc->alt_ioc;
295
296 /* rearm the timer */
297 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
298 if (ioc->reset_work_q)
299 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
300 msecs_to_jiffies(MPT_POLLING_INTERVAL));
301 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
302}
303
304
256/* 305/*
257 * Process turbo (context) reply... 306 * Process turbo (context) reply...
258 */ 307 */
@@ -1616,6 +1665,22 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1616 /* Find lookup slot. */ 1665 /* Find lookup slot. */
1617 INIT_LIST_HEAD(&ioc->list); 1666 INIT_LIST_HEAD(&ioc->list);
1618 1667
1668
1669 /* Initialize workqueue */
1670 INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1671 spin_lock_init(&ioc->fault_reset_work_lock);
1672
1673 snprintf(ioc->reset_work_q_name, KOBJ_NAME_LEN, "mpt_poll_%d", ioc->id);
1674 ioc->reset_work_q =
1675 create_singlethread_workqueue(ioc->reset_work_q_name);
1676 if (!ioc->reset_work_q) {
1677 printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1678 ioc->name);
1679 pci_release_selected_regions(pdev, ioc->bars);
1680 kfree(ioc);
1681 return -ENOMEM;
1682 }
1683
1619 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", 1684 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1620 ioc->name, &ioc->facts, &ioc->pfacts[0])); 1685 ioc->name, &ioc->facts, &ioc->pfacts[0]));
1621 1686
@@ -1722,6 +1787,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1722 iounmap(ioc->memmap); 1787 iounmap(ioc->memmap);
1723 if (r != -5) 1788 if (r != -5)
1724 pci_release_selected_regions(pdev, ioc->bars); 1789 pci_release_selected_regions(pdev, ioc->bars);
1790
1791 destroy_workqueue(ioc->reset_work_q);
1792 ioc->reset_work_q = NULL;
1793
1725 kfree(ioc); 1794 kfree(ioc);
1726 pci_set_drvdata(pdev, NULL); 1795 pci_set_drvdata(pdev, NULL);
1727 return r; 1796 return r;
@@ -1754,6 +1823,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1754 } 1823 }
1755#endif 1824#endif
1756 1825
1826 if (!ioc->alt_ioc)
1827 queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1828 msecs_to_jiffies(MPT_POLLING_INTERVAL));
1829
1757 return 0; 1830 return 0;
1758} 1831}
1759 1832
@@ -1769,6 +1842,19 @@ mpt_detach(struct pci_dev *pdev)
1769 MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 1842 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1770 char pname[32]; 1843 char pname[32];
1771 u8 cb_idx; 1844 u8 cb_idx;
1845 unsigned long flags;
1846 struct workqueue_struct *wq;
1847
1848 /*
1849 * Stop polling ioc for fault condition
1850 */
1851 spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
1852 wq = ioc->reset_work_q;
1853 ioc->reset_work_q = NULL;
1854 spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
1855 cancel_delayed_work(&ioc->fault_reset_work);
1856 destroy_workqueue(wq);
1857
1772 1858
1773 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); 1859 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1774 remove_proc_entry(pname, NULL); 1860 remove_proc_entry(pname, NULL);