Skip to content

Commit d54d48b

Browse files
Prakash, Sathyajejb
authored andcommitted
[SCSI] mpt fusion : Adding FAULT Reset polling work
When the firmware is in Fault state it will be identifed only when the next time the driver access the IOC state. This patch includes a polling function in the driver which will be executed in regular interval to check the status of the firmware and if it is in Fault state, then the firmware will be reset by the driver. Signed-off-by: Sathya Prakash <sathya.prakash@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
1 parent cc47244 commit d54d48b

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

drivers/message/fusion/mptbase.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,55 @@ mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
253253
return 0;
254254
}
255255

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+
256305
/*
257306
* Process turbo (context) reply...
258307
*/
@@ -1616,6 +1665,22 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
16161665
/* Find lookup slot. */
16171666
INIT_LIST_HEAD(&ioc->list);
16181667

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+
16191684
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
16201685
ioc->name, &ioc->facts, &ioc->pfacts[0]));
16211686

@@ -1722,6 +1787,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
17221787
iounmap(ioc->memmap);
17231788
if (r != -5)
17241789
pci_release_selected_regions(pdev, ioc->bars);
1790+
1791+
destroy_workqueue(ioc->reset_work_q);
1792+
ioc->reset_work_q = NULL;
1793+
17251794
kfree(ioc);
17261795
pci_set_drvdata(pdev, NULL);
17271796
return r;
@@ -1754,6 +1823,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
17541823
}
17551824
#endif
17561825

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+
17571830
return 0;
17581831
}
17591832

@@ -1769,6 +1842,19 @@ mpt_detach(struct pci_dev *pdev)
17691842
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
17701843
char pname[32];
17711844
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+
17721858

17731859
sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
17741860
remove_proc_entry(pname, NULL);

drivers/message/fusion/mptbase.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@
176176
/* debug print string length used for events and iocstatus */
177177
# define EVENT_DESCR_STR_SZ 100
178178

179+
#define MPT_POLLING_INTERVAL 1000 /* in milliseconds */
180+
179181
#ifdef __KERNEL__ /* { */
180182
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
181183

@@ -709,6 +711,12 @@ typedef struct _MPT_ADAPTER
709711
struct workqueue_struct *fc_rescan_work_q;
710712
struct scsi_cmnd **ScsiLookup;
711713
spinlock_t scsi_lookup_lock;
714+
715+
char reset_work_q_name[KOBJ_NAME_LEN];
716+
struct workqueue_struct *reset_work_q;
717+
struct delayed_work fault_reset_work;
718+
spinlock_t fault_reset_work_lock;
719+
712720
} MPT_ADAPTER;
713721

714722
/*

0 commit comments

Comments
 (0)