patch-2.2.17 linux/drivers/i2o/i2o_block.c
Next file: linux/drivers/i2o/i2o_core.c
Previous file: linux/drivers/char/vt.c
Back to the patch index
Back to the overall index
- Lines: 407
- Date:
Mon Sep 4 18:39:18 2000
- Orig file:
v2.2.16/drivers/i2o/i2o_block.c
- Orig date:
Mon Sep 4 18:37:42 2000
diff -u --recursive --new-file v2.2.16/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
@@ -166,13 +166,14 @@
static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
static void i2ob_end_request(struct request *);
-static void i2ob_request(struct request * q);
+static void i2ob_request(void);
static int do_i2ob_revalidate(kdev_t, int);
static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
static int i2ob_evt(void *);
static int evt_pid = 0;
static int evt_running = 0;
+static int scan_unit = 0;
static void i2ob_new_device(struct i2o_controller *, struct i2o_device *);
static void i2ob_del_device(struct i2o_controller *, struct i2o_device *);
@@ -375,14 +376,14 @@
}
- if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
- {
- spin_lock(&i2ob_evt_lock);
- memcpy(&evt_msg, m, msg->size);
- spin_unlock(&i2ob_evt_lock);
- wake_up_interruptible(&i2ob_evt_wait);
- return;
- }
+ if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
+ {
+ spin_lock(&i2ob_evt_lock);
+ memcpy(&evt_msg, m, msg->size);
+ spin_unlock(&i2ob_evt_lock);
+ wake_up_interruptible(&i2ob_evt_wait);
+ return;
+ }
if(!dev->i2odev)
{
/*
@@ -404,18 +405,17 @@
return;
}
- /*
- * Lets see what is cooking. We stuffed the
- * request in the context.
- */
+ /*
+ * Lets see what is cooking. We stuffed the
+ * request in the context.
+ */
- ireq=&i2ob_queue[m[3]];
- st=m[4]>>24;
+ ireq=&i2ob_queue[m[3]];
+ st=m[4]>>24;
- if(st!=0)
- {
- char *bsa_errors[] =
- {
+ if(st!=0)
+ {
+ char *bsa_errors[] = {
"Success",
"Media Error",
"Failure communicating to device",
@@ -430,59 +430,57 @@
"Device is write protected",
"Device has reset",
"Volume has changed, waiting for acknowledgement"
- };
- printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, bsa_errors[m[4]&0XFFFF]);
+ };
- if(m[4]&0x00FF0000)
- printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF);
- printk("\n");
+ printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, bsa_errors[m[4]&0XFFFF]);
- ireq->req->errors++;
+ if(m[4]&0x00FF0000)
+ printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF);
+ printk("\n");
- if (ireq->req->errors < MAX_I2OB_RETRIES)
- {
- u32 retry_msg;
+ ireq->req->errors++;
+ if (ireq->req->errors < MAX_I2OB_RETRIES)
+ {
+ u32 retry_msg;
+ printk(KERN_ERR "i2ob: attempting retry %d for request %p\n",ireq->req->errors+1,ireq->req);
+
+ /*
+ * Get a message for this retry.
+ */
+ retry_msg = i2ob_get(dev);
- printk(KERN_ERR "i2ob: attempting retry %d for request %p\n",ireq->req->errors+1,ireq->req);
-
- /*
- * Get a message for this retry.
+ /*
+ * If we cannot get a message then
+ * forget the retry and fail the
+ * request. Note that since this is
+ * being called from the interrupt
+ * handler, a request has just been
+ * completed and there will most likely
+ * be space on the inbound message
+ * fifo so this won't happen often.
+ */
+ if(retry_msg!=0xFFFFFFFF)
+ {
+ /*
+ * Decrement the queue depth since
+ * this request has completed and
+ * it will be incremented again when
+ * i2ob_send is called below.
*/
- retry_msg = i2ob_get(dev);
-
- /*
- * If we cannot get a message then
- * forget the retry and fail the
- * request. Note that since this is
- * being called from the interrupt
- * handler, a request has just been
- * completed and there will most likely
- * be space on the inbound message
- * fifo so this won't happen often.
+ atomic_dec(&queue_depth);
+ /*
+ * Send the request again.
*/
- if(retry_msg!=0xFFFFFFFF)
- {
- /*
- * Decrement the queue depth since
- * this request has completed and
- * it will be incremented again when
- * i2ob_send is called below.
- */
- atomic_dec(&queue_depth);
-
- /*
- * Send the request again.
- */
- i2ob_send(retry_msg, dev,ireq,i2ob[unit].start_sect, (unit&0xF0));
- /*
- * Don't fall through.
- */
- return;
- }
- }
- }
- else
- ireq->req->errors = 0;
+ i2ob_send(retry_msg, dev,ireq,i2ob[unit].start_sect, (unit&0xF0));
+ /*
+ * Don't fall through.
+ */
+ return;
+ }
+ }
+ }
+ else
+ ireq->req->errors = 0;
/*
* Dequeue the request. We use irqsave locks as one day we
@@ -498,7 +496,7 @@
*/
atomic_dec(&queue_depth);
- i2ob_request(NULL);
+ i2ob_request();
spin_unlock_irqrestore(&io_request_lock, flags);
}
@@ -675,7 +673,7 @@
/*
* Restart any requests.
*/
- i2ob_request(NULL);
+ i2ob_request();
/*
* Free the lock.
@@ -691,7 +689,7 @@
* we use it.
*/
-static void i2ob_request(struct request * q)
+static void i2ob_request(void)
{
unsigned long flags;
struct request *req;
@@ -732,10 +730,9 @@
CURRENT = CURRENT->next;
req->sem = NULL;
i2ob_end_request(req);
+ continue;
}
- else
- {
/* Get a message */
m = i2ob_get(dev);
@@ -778,7 +775,6 @@
ireq->req = req;
i2ob_send(m, dev, ireq, i2ob[unit].start_sect, (unit&0xF0));
- }
}
}
@@ -1190,68 +1186,127 @@
return 0;
}
-static void i2ob_probe(void)
+static int i2ob_scan(int bios)
{
int i;
- int unit = 0;
int warned = 0;
+ struct i2o_device *d, *b=NULL;
+ struct i2o_controller *c;
+ struct i2ob_device *dev;
for(i=0; i< MAX_I2O_CONTROLLERS; i++)
{
- struct i2o_controller *c=i2o_find_controller(i);
- struct i2o_device *d;
-
+ c=i2o_find_controller(i);
+
if(c==NULL)
continue;
- for(d=c->devices;d!=NULL;d=d->next)
+ /*
+ * The device list connected to the I2O Controller is doubly linked
+ * Here we traverse the end of the list , and start claiming devices
+ * from that end. This assures that within an I2O controller atleast
+ * the newly created volumes get claimed after the older ones, thus
+ * mapping to same major/minor (and hence device file name) after
+ * every reboot.
+ * The exception being:
+ * 1. If there was a TID reuse.
+ * 2. There was more than one I2O controller.
+ */
+
+ if(!bios)
{
- if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
+ for (d=c->devices;d!=NULL;d=d->next)
+ if(d->next == NULL)
+ b = d;
+ }
+ else
+ b = c->devices;
+
+ while(b != NULL)
+ {
+ d=b;
+ if(bios)
+ b = b->next;
+ else
+ b = b->prev;
+
+ if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
continue;
-
if(d->lct_data.user_tid != 0xFFF)
continue;
-
- if(i2o_claim_device(d, &i2o_block_handler))
- {
- printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit,
- d->lct_data.tid);
- printk(KERN_WARNING "\tDevice refused claim! Skipping installation\n");
- continue;
- }
-
- if(unit<MAX_I2OB<<4)
+ if(bios)
{
- /*
+ if(d->lct_data.bios_info != 0x80)
+ continue;
+ printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid);
+ }
+ else
+ {
+ if(d->lct_data.bios_info == 0x80)
+ continue; /* Already claimed on pass 1 */
+ }
+ if(i2o_claim_device(d, &i2o_block_handler))
+ {
+ printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit, d->lct_data.tid);
+ printk(KERN_WARNING "\t%sevice refused claim! Skipping installation\n",
+ bios?"Boot d":"D");
+ continue;
+ }
+ if(scan_unit<MAX_I2OB<<4)
+ {
+ /*
* Get the device and fill in the
* Tid and controller.
*/
- struct i2ob_device *dev=&i2ob_dev[unit];
- dev->i2odev = d;
+ dev=&i2ob_dev[scan_unit];
+ dev->i2odev = d;
dev->controller = c;
- dev->unit = c->unit;
+ dev->unit = c->unit;
dev->tid = d->lct_data.tid;
-
- if(i2ob_install_device(c,d,unit))
- printk(KERN_WARNING "Could not install I2O block device\n");
- else
- {
- unit+=16;
- i2ob_dev_count++;
-
- /* We want to know when device goes away */
- i2o_device_notify_on(d, &i2o_block_handler);
- }
+ if(i2ob_install_device(c,d,scan_unit))
+ printk(KERN_WARNING "Could not install I2O block device\n");
+ else
+ {
+ scan_unit+=16;
+ i2ob_dev_count++;
+ /* We want to know when device goes away */
+ i2o_device_notify_on(d, &i2o_block_handler);
+ }
}
else
{
- if(!warned++)
- printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", unit>>4);
+ if(!warned++)
+ printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit>>4);
}
- i2o_release_device(d, &i2o_block_handler);
+ i2o_release_device(d, &i2o_block_handler);
}
i2o_unlock_controller(c);
}
+ return 0;
+}
+
+static void i2ob_probe(void)
+{
+ /*
+ * Some overhead/redundancy involved here, while trying to
+ * claim the first boot volume encountered as /dev/i2o/hda
+ * everytime. All the i2o_controllers are searched and the
+ * first i2o block device marked as bootable is claimed
+ * If an I2O block device was booted off , the bios sets
+ * its bios_info field to 0x80, this what we search for.
+ * Assuming that the bootable volume is /dev/i2o/hda
+ * everytime will prevent any kernel panic while mounting
+ * root partition
+ */
+
+ printk(KERN_INFO "i2o_block: Checking for Boot device...\n");
+ i2ob_scan(1);
+
+ /*
+ * Now the remainder.
+ */
+ printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n");
+ i2ob_scan(0);
}
/*
@@ -1283,14 +1338,6 @@
break;
}
- /*
- * Creating a RAID 5 volume takes a little while and the UTIL_CLAIM
- * will fail if we don't give the card enough time to do it's magic,
- * so we just sleep for a little while and let it do it's thing
- */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(5*HZ);
-
if(i2o_claim_device(d, &i2o_block_handler))
{
printk(KERN_INFO
@@ -1606,7 +1653,7 @@
* Finally see what is actually plugged in to our controllers
*/
i2ob_probe();
-
+
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)