patch-2.3.13 linux/drivers/i2o/i2o_core.c
Next file: linux/drivers/i2o/i2o_lan.c
Previous file: linux/drivers/i2o/i2o_config.c
Back to the patch index
Back to the overall index
- Lines: 352
- Date:
Thu Aug 5 15:04:52 1999
- Orig file:
v2.3.12/linux/drivers/i2o/i2o_core.c
- Orig date:
Thu Jul 8 15:42:20 1999
diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
@@ -14,15 +14,20 @@
* Red Creek RCPCI45 adapter driver by Red Creek Communications
*
* Fixes by Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ * Deepak Saxena <deepak@plexity.net>
*/
-
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+
+#if defined(CONFIG_I2O_PCI) || defined (CONFIG_I2O_PCI_MODULE)
#include <linux/i2o.h>
+#endif
+
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/malloc.h>
@@ -32,6 +37,7 @@
#include "i2o_lan.h"
+#define DRIVERDEBUG
/*
* Size of the I2O module table
@@ -46,6 +52,32 @@
extern int i2o_online_controller(struct i2o_controller *c);
static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
struct i2o_message *);
+static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
+static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
+static void i2o_dump_message(u32 *);
+
+#ifdef MODULE
+/*
+ * Function table to send to bus specific layers
+ * See <include/linux/i2o.h> for explanation of this
+ */
+static struct i2o_core_func_table i2o_core_functions =
+{
+ i2o_install_controller,
+ i2o_activate_controller,
+ i2o_find_controller,
+ i2o_unlock_controller,
+ i2o_run_queue,
+ i2o_delete_controller
+};
+
+#ifdef CONFIG_I2O_PCI_MODULE
+extern int i2o_pci_core_attach(struct i2o_core_func_table *);
+extern void i2o_pci_core_detach(void);
+#endif /* CONFIG_I2O_PCI_MODULE */
+
+#endif /* MODULE */
+
/* Message handler */
static struct i2o_handler i2o_core_handler =
@@ -133,12 +165,19 @@
int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
{
+ int i;
+
spin_lock(&i2o_configuration_lock);
d->controller=c;
d->owner=NULL;
d->next=c->devices;
c->devices=d;
*d->dev_name = 0;
+ d->owner = NULL;
+
+ for(i = 0; i < I2O_MAX_MANAGERS; i++)
+ d->managers[i] = NULL;
+
spin_unlock(&i2o_configuration_lock);
return 0;
}
@@ -247,9 +286,12 @@
while(*p)
{
if(*p!=c)
+ {
+ printk("Quiescing controller %p != %p\n", c, *p);
if(i2o_quiesce_controller(*p)<0)
printk(KERN_INFO "Unable to quiesce iop%d\n",
(*p)->unit);
+ }
p=&((*p)->next);
}
@@ -308,11 +350,23 @@
/*
- * Track if a device is being used by a driver
+ * Claim a device for use as either the primary user or just
+ * as a management/secondary user
*/
-
-int i2o_claim_device(struct i2o_device *d, struct i2o_driver *r)
+int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
{
+ /* Device already has a primary user or too many managers */
+ if((type == I2O_CLAIM_PRIMARY && d->owner) ||
+ (d->num_managers == I2O_MAX_MANAGERS))
+ {
+ return -EBUSY;
+ }
+
+ if(i2o_issue_claim(d->controller,d->id, h->context, 1, &reply_flag, type) < 0)
+ {
+ return -EBUSY;
+ }
+
spin_lock(&i2o_configuration_lock);
if(d->owner)
{
@@ -320,25 +374,92 @@
return -EBUSY;
}
atomic_inc(&d->controller->users);
- d->owner=r;
+
+ if(type == I2O_CLAIM_PRIMARY)
+ d->owner=h;
+ else
+ i2o_add_management_user(d, h);
+
spin_unlock(&i2o_configuration_lock);
return 0;
}
-int i2o_release_device(struct i2o_device *d)
+int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
{
+ int err = 0;
+
spin_lock(&i2o_configuration_lock);
- if(d->owner==NULL)
+
+ /* Primary user */
+ if(type == I2O_CLAIM_PRIMARY)
{
+ if(d->owner != h)
+ err = -ENOENT;
+ else
+ {
+ if(i2o_issue_claim(d->controller,d->id, h->context, 0, &reply_flag, type) < 0)
+ {
+ err = -ENXIO;
+ }
+ else
+ {
+ d->owner = NULL;
+ atomic_dec(&d->controller->users);
+ }
+ }
+
spin_unlock(&i2o_configuration_lock);
- return -EINVAL;
+ return err;
}
- atomic_dec(&d->controller->users);
- d->owner=NULL;
+
+ /* Management or other user */
+ if(i2o_remove_management_user(d, h))
+ err = -ENOENT;
+ else
+ {
+ atomic_dec(&d->controller->users);
+
+ if(i2o_issue_claim(d->controller,d->id, h->context, 0,
+ &reply_flag, type) < 0)
+ err = -ENXIO;
+ }
+
spin_unlock(&i2o_configuration_lock);
+ return err;
+}
+
+int i2o_add_management_user(struct i2o_device *d, struct i2o_handler *h)
+{
+ int i;
+
+ if(d->num_managers == I2O_MAX_MANAGERS)
+ return 1;
+
+ for(i = 0; i < I2O_MAX_MANAGERS; i++)
+ if(!d->managers[i])
+ d->managers[i] = h;
+
+ d->num_managers++;
+
return 0;
}
+int i2o_remove_management_user(struct i2o_device *d, struct i2o_handler *h)
+{
+ int i;
+
+ for(i=0; i < I2O_MAX_MANAGERS; i++)
+ {
+ if(d->managers[i] == h)
+ {
+ d->managers[i] = NULL;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
/*
* This is called by the bus specific driver layer when an interrupt
* or poll of this card interface is desired.
@@ -363,7 +484,11 @@
if(i)
i->reply(i,c,m);
else
- printk("Spurious reply\n");
+ {
+ printk("Spurious reply to handler %d\n",
+ m->initiator_context&(MAX_I2O_MODULES-1));
+ i2o_dump_message((u32*)m);
+ }
i2o_flush_reply(c,mv);
mb();
}
@@ -803,7 +928,8 @@
msg[2]=core_context;
msg[3]=(u32)&reply_flag;
- return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10);
+ /* Long timeout needed for quiesce if lots of devices */
+ return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 120);
}
@@ -839,11 +965,15 @@
/* First stop external operations */
for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
{
- if(i2o_quiesce_controller(iop)<0)
- printk(KERN_INFO "Unable to quiesce iop%d\n",
- iop->unit);
- else
- printk(KERN_DEBUG "%s quiesced\n", iop->name);
+ /* Quiesce is rejected on hold state */
+ if(iop->status != ADAPTER_STATE_HOLD)
+ {
+ if(i2o_quiesce_controller(iop)<0)
+ printk(KERN_INFO "Unable to quiesce iop%d\n",
+ iop->unit);
+ else
+ printk(KERN_DEBUG "%s quiesced\n", iop->name);
+ }
}
/* Then reset the IOP */
@@ -1398,7 +1528,7 @@
* Issue UTIL_CLAIM messages
*/
-int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, int *flag)
+int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, int *flag, u32 type)
{
u32 msg[6];
@@ -1412,7 +1542,7 @@
msg[2] = 0x80000000|context;
msg[3] = (u32)flag;
- msg[4] = 0x01<<24; /* Primary user */
+ msg[4] = type;
return i2o_post_wait(c, tid, msg, 20, flag,2);
}
@@ -1999,8 +2129,19 @@
return;
}
+/* Used to dump a message to syslog during debugging */
+static void i2o_dump_message(u32 *msg)
+{
+#ifdef DRIVERDEBUG
+ int i;
+
+ printk(KERN_INFO "Dumping I2O message @ %p\n", msg);
+ for(i = 0; i < ((msg[0]>>16)&0xffff); i++)
+ printk(KERN_INFO "\tmsg[%d] = %#10x\n", i, msg[i]);
+#endif
+}
-#ifdef CONFIG_MODULE
+#ifdef MODULE
EXPORT_SYMBOL(i2o_install_handler);
EXPORT_SYMBOL(i2o_remove_handler);
@@ -2040,19 +2181,31 @@
int init_module(void)
{
- if (i2o_install_handler(&i2o_core_handler) < 0)
- {
- printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
- return 0;
- }
+ if (i2o_install_handler(&i2o_core_handler) < 0)
+ {
+ printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
+ return 0;
+ }
- core_context = i2o_core_handler.context;
+ core_context = i2o_core_handler.context;
- return 0;
+ /*
+ * Attach core to I2O PCI subsystem
+ */
+#ifdef CONFIG_I2O_PCI_MODULE
+ if(i2o_pci_core_attach(&i2o_core_functions) < 0)
+ printk(KERN_INFO "No PCI I2O controllers found\n");
+#endif
+
+ return 0;
}
void cleanup_module(void)
{
+#ifdef CONFIG_I2O_PCI_MODULE
+ i2o_pci_core_detach();
+#endif
+
i2o_remove_handler(&i2o_core_handler);
}
@@ -2093,4 +2246,4 @@
return 0;
}
-#endif
\ No newline at end of file
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)