[PATCH] 2.4.21-pre5 cciss fix unlikely startup problem

Stephen Cameron (steve.cameron@hp.com)
Thu, 27 Feb 2003 10:37:41 +0600


* Make driver wait longer for board to enter simple mode to
handle an unlikely corner case. (If you hot replace a 144 GB
failed disk in a RAID 5 set at just the right time prior to
driver initialization, the board can take an extra long time
to become ready when switched into "simple mode" when the
driver is starting up. Without the patch, in those cases, the
driver will give up before the board becomes ready, and will not work.
(Though rebooting will generally "fix" it). This patch avoids
the problem.)
* Fix a couple of affected ioctls to return EAGAIN instead of
inappropriate EFAULT.

--- lx2421p5/drivers/block/cciss.c~cfg_table_wait 2003-02-27 10:11:35.000000000 +0600
+++ lx2421p5-scameron/drivers/block/cciss.c 2003-02-27 10:11:35.000000000 +0600
@@ -94,7 +94,8 @@ static struct board_type products[] = {
};

/* How long to wait (in millesconds) for board to go into simple mode */
-#define MAX_CONFIG_WAIT 1000
+#define MAX_CONFIG_WAIT 30000
+#define MAX_IOCTL_CONFIG_WAIT 1000

/*define how many times we will try a command because of bus resets */
#define MAX_CMD_RETRIES 3
@@ -578,7 +579,7 @@ static int cciss_ioctl(struct inode *ino
&(c->cfgtable->HostWrite.CoalIntCount));
writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);

- for(i=0;i<MAX_CONFIG_WAIT;i++) {
+ for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
if (!(readl(c->vaddr + SA5_DOORBELL)
& CFGTBL_ChangeReq))
break;
@@ -586,8 +587,11 @@ static int cciss_ioctl(struct inode *ino
udelay(1000);
}
spin_unlock_irqrestore(&io_request_lock, flags);
- if (i >= MAX_CONFIG_WAIT)
- return -EFAULT;
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ /* there is an unlikely case where this can happen,
+ * involving hot replacing a failed 144 GB drive in a
+ * RAID 5 set just as we attempt this ioctl. */
+ return -EAGAIN;
return 0;
}
case CCISS_GETNODENAME:
@@ -627,7 +631,7 @@ static int cciss_ioctl(struct inode *ino

writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);

- for(i=0;i<MAX_CONFIG_WAIT;i++) {
+ for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
if (!(readl(c->vaddr + SA5_DOORBELL)
& CFGTBL_ChangeReq))
break;
@@ -635,8 +639,11 @@ static int cciss_ioctl(struct inode *ino
udelay(1000);
}
spin_unlock_irqrestore(&io_request_lock, flags);
- if (i >= MAX_CONFIG_WAIT)
- return -EFAULT;
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ /* there is an unlikely case where this can happen,
+ * involving hot replacing a failed 144 GB drive in a
+ * RAID 5 set just as we attempt this ioctl. */
+ return -EAGAIN;
return 0;
}

@@ -2583,11 +2590,17 @@ static int cciss_pci_init(ctlr_info_t *c
&(c->cfgtable->HostWrite.TransportRequest));
writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);

+ /* Here, we wait, possibly for a long time, (4 secs or more).
+ * In some unlikely cases, (e.g. A failed 144 GB drive in a
+ * RAID 5 set was hot replaced just as we're coming in here) it
+ * can take that long. Normally (almost always) we will wait
+ * less than 1 sec. */
for(i=0;i<MAX_CONFIG_WAIT;i++) {
if (!(readl(c->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
break;
/* delay and try again */
- udelay(1000);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
}

#ifdef CCISS_DEBUG

_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/