diff options
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index d40d6d15ae20..75e599b85b64 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * For use with LSI PCI chip/adapter(s) | 5 | * For use with LSI PCI chip/adapter(s) |
6 | * running LSI Fusion MPT (Message Passing Technology) firmware. | 6 | * running LSI Fusion MPT (Message Passing Technology) firmware. |
7 | * | 7 | * |
8 | * Copyright (c) 1999-2007 LSI Corporation | 8 | * Copyright (c) 1999-2008 LSI Corporation |
9 | * (mailto:DL-MPTFusionLinux@lsi.com) | 9 | * (mailto:DL-MPTFusionLinux@lsi.com) |
10 | * | 10 | * |
11 | */ | 11 | */ |
@@ -103,7 +103,7 @@ static int mfcounter = 0; | |||
103 | * Public data... | 103 | * Public data... |
104 | */ | 104 | */ |
105 | 105 | ||
106 | struct proc_dir_entry *mpt_proc_root_dir; | 106 | static struct proc_dir_entry *mpt_proc_root_dir; |
107 | 107 | ||
108 | #define WHOINIT_UNKNOWN 0xAA | 108 | #define WHOINIT_UNKNOWN 0xAA |
109 | 109 | ||
@@ -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 | **/ | ||
261 | static void | ||
262 | mpt_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 | ||
@@ -1727,6 +1792,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1727 | iounmap(ioc->memmap); | 1792 | iounmap(ioc->memmap); |
1728 | if (r != -5) | 1793 | if (r != -5) |
1729 | pci_release_selected_regions(pdev, ioc->bars); | 1794 | pci_release_selected_regions(pdev, ioc->bars); |
1795 | |||
1796 | destroy_workqueue(ioc->reset_work_q); | ||
1797 | ioc->reset_work_q = NULL; | ||
1798 | |||
1730 | kfree(ioc); | 1799 | kfree(ioc); |
1731 | pci_set_drvdata(pdev, NULL); | 1800 | pci_set_drvdata(pdev, NULL); |
1732 | return r; | 1801 | return r; |
@@ -1759,6 +1828,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1759 | } | 1828 | } |
1760 | #endif | 1829 | #endif |
1761 | 1830 | ||
1831 | if (!ioc->alt_ioc) | ||
1832 | queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work, | ||
1833 | msecs_to_jiffies(MPT_POLLING_INTERVAL)); | ||
1834 | |||
1762 | return 0; | 1835 | return 0; |
1763 | } | 1836 | } |
1764 | 1837 | ||
@@ -1774,6 +1847,19 @@ mpt_detach(struct pci_dev *pdev) | |||
1774 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 1847 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1775 | char pname[32]; | 1848 | char pname[32]; |
1776 | u8 cb_idx; | 1849 | u8 cb_idx; |
1850 | unsigned long flags; | ||
1851 | struct workqueue_struct *wq; | ||
1852 | |||
1853 | /* | ||
1854 | * Stop polling ioc for fault condition | ||
1855 | */ | ||
1856 | spin_lock_irqsave(&ioc->fault_reset_work_lock, flags); | ||
1857 | wq = ioc->reset_work_q; | ||
1858 | ioc->reset_work_q = NULL; | ||
1859 | spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags); | ||
1860 | cancel_delayed_work(&ioc->fault_reset_work); | ||
1861 | destroy_workqueue(wq); | ||
1862 | |||
1777 | 1863 | ||
1778 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); | 1864 | sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); |
1779 | remove_proc_entry(pname, NULL); | 1865 | remove_proc_entry(pname, NULL); |
@@ -7456,7 +7542,6 @@ EXPORT_SYMBOL(mpt_resume); | |||
7456 | EXPORT_SYMBOL(mpt_suspend); | 7542 | EXPORT_SYMBOL(mpt_suspend); |
7457 | #endif | 7543 | #endif |
7458 | EXPORT_SYMBOL(ioc_list); | 7544 | EXPORT_SYMBOL(ioc_list); |
7459 | EXPORT_SYMBOL(mpt_proc_root_dir); | ||
7460 | EXPORT_SYMBOL(mpt_register); | 7545 | EXPORT_SYMBOL(mpt_register); |
7461 | EXPORT_SYMBOL(mpt_deregister); | 7546 | EXPORT_SYMBOL(mpt_deregister); |
7462 | EXPORT_SYMBOL(mpt_event_register); | 7547 | EXPORT_SYMBOL(mpt_event_register); |