aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-15 21:58:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-15 21:58:04 -0400
commit89a93f2f4834f8c126e8d9dd6b368d0b9e21ec3d (patch)
treee731456fec0cab1225ad3e806dc8d3efefa0a78b /drivers/message/fusion/mptbase.c
parent260eddf4391f162a69d1d163729249635fa7a78f (diff)
parentfe9233fb6914a0eb20166c967e3020f7f0fba2c9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (102 commits) [SCSI] scsi_dh: fix kconfig related build errors [SCSI] sym53c8xx: Fix bogus sym_que_entry re-implementation of container_of [SCSI] scsi_cmnd.h: remove double inclusion of linux/blkdev.h [SCSI] make struct scsi_{host,target}_type static [SCSI] fix locking in host use of blk_plug_device() [SCSI] zfcp: Cleanup external header file [SCSI] zfcp: Cleanup code in zfcp_erp.c [SCSI] zfcp: zfcp_fsf cleanup. [SCSI] zfcp: consolidate sysfs things into one file. [SCSI] zfcp: Cleanup of code in zfcp_aux.c [SCSI] zfcp: Cleanup of code in zfcp_scsi.c [SCSI] zfcp: Move status accessors from zfcp to SCSI include file. [SCSI] zfcp: Small QDIO cleanups [SCSI] zfcp: Adapter reopen for large number of unsolicited status [SCSI] zfcp: Fix error checking for ELS ADISC requests [SCSI] zfcp: wait until adapter is finished with ERP during auto-port [SCSI] ibmvfc: IBM Power Virtual Fibre Channel Adapter Client Driver [SCSI] sg: Add target reset support [SCSI] lib: Add support for the T10 (SCSI) Data Integrity Field CRC [SCSI] sd: Move scsi_disk() accessor function to sd.h ...
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c91
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
106struct proc_dir_entry *mpt_proc_root_dir; 106static 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**/
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
@@ -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);
7456EXPORT_SYMBOL(mpt_suspend); 7542EXPORT_SYMBOL(mpt_suspend);
7457#endif 7543#endif
7458EXPORT_SYMBOL(ioc_list); 7544EXPORT_SYMBOL(ioc_list);
7459EXPORT_SYMBOL(mpt_proc_root_dir);
7460EXPORT_SYMBOL(mpt_register); 7545EXPORT_SYMBOL(mpt_register);
7461EXPORT_SYMBOL(mpt_deregister); 7546EXPORT_SYMBOL(mpt_deregister);
7462EXPORT_SYMBOL(mpt_event_register); 7547EXPORT_SYMBOL(mpt_event_register);