mpt_config() can return EAGAIN. When this happens, fibre channel target discovery can prematurely terminate with fewer than the total number of targets discovered. This patch detects EAGAIN and reschedules the scan work. Generally, this situation only occurs when the lsiutil program is being used to reset the board. Signed-off-by: Michael Reed <mdr@xxxxxxx>
mpt_config() can return EAGAIN. When this happens, fibre channel target discovery can prematurely terminate with fewer than the total number of targets discovered. This patch detects EAGAIN and reschedules the scan work. Generally, this situation only occurs when the lsiutil program is being used to reset the board. Signed-off-by: Michael Reed <mdr@xxxxxxx> --- rc3u/drivers/message/fusion/mptfc.c 2006-05-01 16:06:13.311966423 -0500 +++ rc3/drivers/message/fusion/mptfc.c 2006-05-03 14:16:47.669834844 -0500 @@ -634,6 +634,7 @@ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; int ii; int work_to_do; + int rc=0; u64 pn; unsigned long flags; struct mptfc_rport_info *ri; @@ -651,9 +652,13 @@ * will reregister existing rports */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); + rc = mptbase_GetFcPortPage0(ioc, ii); + if (rc == -EAGAIN) + break; mptfc_init_host_attr(ioc,ii); /* refresh */ - mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); + rc = mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); + if (rc == -EAGAIN) + break; } /* delete devices still missing */ @@ -686,6 +691,20 @@ work_to_do = --ioc->fc_rescan_work_count; spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); } while (work_to_do); + + /* if last pass failed with EAGAIN, reschedule work for a later attempt */ + if (rc == -EAGAIN) { + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + queue_delayed_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work, HZ); + ioc->fc_rescan_work_count = 1; + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_rescan.%d: rescheduling work\n", + ioc->name, + ioc->sh->host_no)); + } } static int @@ -981,6 +1000,7 @@ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); ioc->fc_rescan_work_q = NULL; spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + cancel_delayed_work(&ioc->fc_rescan_work); destroy_workqueue(work_q); }