summaryrefslogtreecommitdiffstats
path: root/drivers/i2o
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
commit99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch)
tree3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/i2o
parente73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff)
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/i2o')
-rw-r--r--drivers/i2o/i2o_block.c26
-rw-r--r--drivers/i2o/i2o_core.c1022
-rw-r--r--drivers/i2o/i2o_lan.c406
-rw-r--r--drivers/i2o/i2o_pci.c5
4 files changed, 673 insertions, 786 deletions
diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c
index f83ecbe9b..78d3a6c53 100644
--- a/drivers/i2o/i2o_block.c
+++ b/drivers/i2o/i2o_block.c
@@ -175,7 +175,7 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
offset = ((u64)(req->sector+base)) << 9;
__raw_writel( offset & 0xFFFFFFFF, msg+24);
__raw_writel(offset>>32, msg+28);
- mptr=msg+8;
+ mptr=msg+32;
if(req->cmd == READ)
{
@@ -216,7 +216,7 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
bh = bh->b_reqnext;
}
}
- __raw_writel(I2O_MESSAGE_SIZE(mptr-msg) | SGL_OFFSET_8, msg);
+ __raw_writel(I2O_MESSAGE_SIZE(mptr-msg)>>2 | SGL_OFFSET_8, msg);
if(req->current_nr_sectors > 8)
printk("Gathered sectors %ld.\n",
@@ -1006,23 +1006,13 @@ struct notifier_block i2ob_reboot_notifier =
0
};
-static struct file_operations i2ob_fops =
+static struct block_device_operations i2ob_fops =
{
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* select */
- i2ob_ioctl, /* ioctl */
- NULL, /* mmap */
- i2ob_open, /* open */
- NULL, /* flush */
- i2ob_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- i2ob_media_change, /* Media Change */
- i2ob_revalidate, /* Revalidate */
- NULL /* File locks */
+ open: i2ob_open,
+ release: i2ob_release,
+ ioctl: i2ob_ioctl,
+ check_media_change: i2ob_media_change,
+ revalidate: i2ob_revalidate,
};
/*
diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c
index 8bd701ad7..ff3e2405f 100644
--- a/drivers/i2o/i2o_core.c
+++ b/drivers/i2o/i2o_core.c
@@ -45,6 +45,8 @@
// #define DRIVERDEBUG
// #define DEBUG_IRQ
+#define dprintk(x)
+
/*
* Size of the I2O module table
*/
@@ -53,7 +55,6 @@ static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
int i2o_num_controllers = 0;
static int core_context = 0;
-static int reply_flag = 0;
extern int i2o_online_controller(struct i2o_controller *c);
static int i2o_init_outbound_q(struct i2o_controller *c);
@@ -61,9 +62,9 @@ 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 int i2o_quiesce_system(void);
-static int i2o_enable_system(void);
-static void i2o_dump_message(u32 *);
+static void i2o_dump_message(u32 *msg);
+
+static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32);
static int i2o_lct_get(struct i2o_controller *);
static int i2o_hrt_get(struct i2o_controller *);
@@ -149,8 +150,8 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
struct i2o_message *m)
{
u32 *msg=(u32 *)m;
- u32 status;
- u32 context = msg[3];
+ int status;
+ u32 context = msg[2];
#if 0
i2o_report_status(KERN_INFO, "i2o_core", msg);
@@ -158,7 +159,7 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
if (msg[0] & (1<<13)) // Fail bit is set
{
- printk(KERN_ERR "IOP failed to process the msg:\n");
+ printk(KERN_ERR "%s: Failed to process the msg:\n",c->name);
printk(KERN_ERR " Cmd = 0x%02X, InitiatorTid = %d, TargetTid =%d\n",
(msg[1] >> 24) & 0xFF, (msg[1] >> 12) & 0xFFF, msg[1] &
0xFFF);
@@ -176,7 +177,7 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
if (msg[4] >> 24)
{
/* 0x40000000 is used as an error report supress bit */
- if((msg[2]&0x40000000)==0)
+ if(msg[2]&0x40000000)
i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
status = -(msg[4] & 0xFFFF);
}
@@ -356,8 +357,7 @@ int i2o_delete_controller(struct i2o_controller *c)
if(*p==c)
{
/* Ask the IOP to switch to HOLD state */
- if (i2o_clear_controller(c) < 0)
- printk("Unable to clear iop%d\n", c->unit);
+ i2o_clear_controller(c);
/* Release IRQ */
c->destructor(c);
@@ -427,7 +427,7 @@ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
return -EBUSY;
}
- if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 1, &reply_flag, type))
+ if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 1, type))
{
return -EBUSY;
}
@@ -443,7 +443,10 @@ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
if(type == I2O_CLAIM_PRIMARY)
d->owner=h;
else
- i2o_add_management_user(d, h);
+ if (i2o_add_management_user(d, h))
+ printk(KERN_WARNING "i2o: Too many managers for TID %d\n",
+ d->lct_data->tid);
+
spin_unlock(&i2o_configuration_lock);
return 0;
@@ -463,7 +466,7 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
else
{
if(i2o_issue_claim(d->controller, d->lct_data->tid, h->context, 0,
- &reply_flag, type))
+ type))
{
err = -ENXIO;
}
@@ -486,7 +489,7 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
atomic_dec(&d->controller->users);
if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 0,
- &reply_flag, type))
+ type))
err = -ENXIO;
}
@@ -647,10 +650,8 @@ u32 i2o_wait_message(struct i2o_controller *c, char *why)
{
if((jiffies-time)>=5*HZ)
{
-#ifdef DRIVERDEBUG
- printk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n",
- c->name, why);
-#endif
+ dprintk((KERN_ERR "%s: Timeout waiting for message frame (%s).\n",
+ c->name, why));
return 0xFFFFFFFF;
}
schedule();
@@ -673,10 +674,8 @@ u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout)
{
if(jiffies-time >= timeout*HZ )
{
-#ifdef DRIVERDEBUG
- printk(KERN_ERR "%s: timeout waiting for %s reply.\n",
- c->name, why);
-#endif
+ dprintk((KERN_ERR "%s: timeout waiting for %s reply.\n",
+ c->name, why));
return 0xFFFFFFFF;
}
schedule();
@@ -685,106 +684,6 @@ u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout)
}
-static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf, int buflen,
- int group, int field)
-{
- u32 m;
- u32 *msg;
- u16 op[8];
- u32 *p;
- int i;
- u32 *rbuf;
-
- op[0]=1; /* One Operation */
- op[1]=0; /* PAD */
- op[2]=1; /* FIELD_GET */
- op[3]=group; /* group number */
- op[4]=1; /* 1 field */
- op[5]=field; /* Field number */
-
- m=i2o_wait_message(c, "ParamsGet");
- if(m==0xFFFFFFFF)
- {
- return -ETIMEDOUT;
- }
-
- msg=(u32 *)(c->mem_offset+m);
-
- rbuf=kmalloc(buflen+32, GFP_KERNEL);
- if(rbuf==NULL)
- {
- printk(KERN_ERR "No free memory for scalar read.\n");
- return -ENOMEM;
- }
-
- __raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_5, &msg[0]);
- __raw_writel(I2O_CMD_UTIL_PARAMS_GET<<24|HOST_TID<<12|tid, &msg[1]);
- __raw_writel(0, &msg[2]); /* Context */
- __raw_writel(0, &msg[3]);
- __raw_writel(0, &msg[4]);
- __raw_writel(0x54000000|12, &msg[5]);
- __raw_writel(virt_to_bus(op), &msg[6]);
- __raw_writel(0xD0000000|(32+buflen), &msg[7]);
- __raw_writel(virt_to_bus(rbuf), &msg[8]);
-
- i2o_post_message(c,m);
- barrier();
-
- /*
- * Now wait for a reply
- */
-
- m=i2o_wait_reply(c, "ParamsGet", 5);
-
- if(m==0xFFFFFFFF)
- {
- kfree(rbuf);
- return -ETIMEDOUT;
- }
-
- msg = (u32 *)bus_to_virt(m);
- if(msg[4]>>24)
- {
- i2o_report_status(KERN_WARNING, "i2o_core", msg);
- }
-
- p=rbuf;
-
- /* Ok 'p' is the reply block - lets see what happened */
- /* p0->p2 are the header */
-
- /* FIXME: endians - turn p3 to little endian */
-
- if((p[0]&0xFFFF)!=1)
- printk(KERN_WARNING "Suspicious field read return 0x%08X\n", p[0]);
-
- i=(p[1]&0xFFFF)<<2; /* Message size */
- if(i<buflen)
- buflen=i;
-
- /* Do we have an error block ? */
- if(p[1]&0xFF000000)
- {
-#ifdef DRIVERDEBUG
- printk(KERN_ERR "%s: error in field read.\n",
- c->name);
-#endif
- kfree(rbuf);
- return -EBADR;
- }
-
- /* p[1] holds the more flag and row count - we dont care */
-
- /* Ok it worked p[2]-> hold the data */
- memcpy(buf, p+2, buflen);
-
- kfree(rbuf);
-
- /* Finally return the message */
- I2O_REPLY_WRITE32(c,m);
- return buflen;
-}
-
/*
* Dump the information block associated with a given unit (TID)
*/
@@ -832,25 +731,25 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
static int i2o_parse_hrt(struct i2o_controller *c)
{
#ifdef DRIVERDEBUG
- u32 *rows=(u32*)c->hrt;
+ u32 *rows=(u32 *)c->hrt;
u8 *p=(u8 *)c->hrt;
u8 *d;
int count;
int length;
int i;
int state;
-
- if(p[3]!=0)
- {
- printk(KERN_ERR "i2o: HRT table for controller is too new a version.\n");
- return -1;
+
+ if(p[3]!=0) {
+ printk(KERN_ERR "%s: HRT table for controller is too new a version.\n",
+ c->name);
+ return -1;
}
-
+
count=p[0]|(p[1]<<8);
length = p[2];
- printk(KERN_INFO "iop%d: HRT has %d entries of %d bytes each.\n",
- c->unit, count, length<<2);
+ printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n",
+ c->name, count, length<<2);
rows+=2;
@@ -912,6 +811,7 @@ static int i2o_parse_hrt(struct i2o_controller *c)
printk("\n");
rows+=length;
}
+
#endif
return 0;
}
@@ -938,27 +838,27 @@ static int i2o_parse_lct(struct i2o_controller *c)
if(max==0)
{
- printk(KERN_ERR "LCT is empty????\n");
+ printk(KERN_ERR "%s: LCT is empty????\n",c->name);
return -1;
}
-
- printk(KERN_INFO "LCT has %d entries.\n", max);
+
+ printk(KERN_INFO "%s: LCT has %d entries.\n", c->name,max);
if(max > 128)
{
- printk(KERN_INFO "LCT was truncated.\n");
+ printk(KERN_INFO "%s: LCT was truncated.\n",c->name);
max=128;
}
if(lct->iop_flags&(1<<0))
- printk(KERN_WARNING "I2O: Configuration dialog desired by iop%d.\n", c->unit);
+ printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);
for(i=0;i<max;i++)
{
d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
- printk("i2o_core: Out of memory for I2O device data.\n");
+ printk(KERN_CRIT "i2o_core: Out of memory for I2O device data.\n");
return -ENOMEM;
}
@@ -1003,128 +903,65 @@ static int i2o_parse_lct(struct i2o_controller *c)
int i2o_quiesce_controller(struct i2o_controller *c)
{
u32 msg[4];
+ int ret;
- if(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)
+ if ((c->status_block->iop_state != ADAPTER_STATE_READY) &
+ (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))
+ {
+ dprintk((KERN_INFO "%s: Not in READY or OPERATIONAL state\n",
+ c->name));
+ dprintk((KERN_INFO "%s: state = %d\n",
+ c->name, c->status_block->iop_state));
return -EINVAL;
+ }
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=(u32)core_context;
- msg[3]=(u32)&reply_flag;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
/* Long timeout needed for quiesce if lots of devices */
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Posting quiesce message to iop%d\n", c->unit);
-#endif
- if(i2o_post_wait(c, msg, sizeof(msg), 120))
- return -1;
+
+ if ((ret = i2o_post_wait(c, msg, sizeof(msg), 120)))
+ printk(KERN_INFO "%s: Unable to quiesce.\n", c->name);
else
- return 0;
+ dprintk((KERN_INFO "%s: Quiesced.\n", c->name));
+
+ return ret;
}
/* Enable IOP */
int i2o_enable_controller(struct i2o_controller *c)
{
u32 msg[4];
-
+ int ret;
+
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=core_context;
- msg[3]=(u32)&reply_flag;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
/* How long of a timeout do we need? */
- return i2o_post_wait(c, msg, sizeof(msg), 240);
-}
-
-/*
- * Quiesce _all_ IOPs in OP state.
- * Used during init/shutdown time.
- */
-int i2o_quiesce_system(void)
-{
- struct i2o_controller *iop;
- int ret = 0;
-
- for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
- {
- /*
- * Quiesce only needed on operational IOPs
- */
- i2o_status_get(iop);
-
- if(iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
- {
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Attempting to quiesce iop%d\n", iop->unit);
-#endif
- if(i2o_quiesce_controller(iop))
- {
- printk(KERN_INFO "Unable to quiesce iop%d\n", iop->unit);
- ret = -ENXIO;
- }
-#ifdef DRIVERDEBUG
- else
- printk(KERN_INFO "%s quiesced\n", iop->name);
-#endif
-
- i2o_status_get(iop); // Update IOP state information
- }
- }
-
- return ret;
-}
-
-/*
- * (re)Enable _all_ IOPs in READY state.
- */
-int i2o_enable_system(void)
-{
- struct i2o_controller *iop;
- int ret = 0;
-
- for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
- {
- /*
- * Enable only valid for IOPs in READY state
- */
- i2o_status_get(iop);
- if(iop->status_block->iop_state == ADAPTER_STATE_READY)
- {
- if(i2o_enable_controller(iop)<0)
- printk(KERN_INFO "Unable to (re)enable iop%d\n",
- iop->unit);
-
- i2o_status_get(iop); // Update IOP state information
- }
- }
+ if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
+ printk(KERN_ERR "%s: Could not enable, %d\n", c->name, ret);
return ret;
}
-
/* Reset an IOP, but keep message queues alive */
int i2o_clear_controller(struct i2o_controller *c)
{
u32 msg[4];
int ret;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Clearing iop%d\n", c->unit);
-#endif
-
- /* Then clear the IOP */
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=core_context;
- msg[3]=(u32)&reply_flag;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
- if((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
- printk(KERN_INFO "ExecIopClear failed: %#10x\n", ret);
-#ifdef DRIVERDEBUG
- else
- printk(KERN_INFO "ExecIopClear success!\n");
-#endif
+ if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
+ printk(KERN_INFO "%s: Unable to clear, %#10x\n",
+ c->name, ret);
+
+ i2o_status_get(c); // Reread the Status Block
return ret;
}
@@ -1134,97 +971,82 @@ int i2o_clear_controller(struct i2o_controller *c)
static int i2o_reset_controller(struct i2o_controller *c)
{
u32 m;
- u8 *work8;
+ u8 *status;
u32 *msg;
long time;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Reseting iop%d\n", c->unit);
-#endif
-
- /* Get a message */
m=i2o_wait_message(c, "AdapterReset");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
msg=(u32 *)(c->mem_offset+m);
-
- work8=(void *)kmalloc(4, GFP_KERNEL);
- if(work8==NULL) {
- printk(KERN_ERR "IOP reset failed - no free memory.\n");
+
+ status = kmalloc(4,GFP_KERNEL);
+ if (status==NULL) {
+ printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
+ c->name);
return -ENOMEM;
}
-
- memset(work8, 0, 4);
-
+ memset(status,0,4);
+
msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
msg[2]=core_context;
- msg[3]=(u32)&reply_flag;
+ msg[3]=0;
msg[4]=0;
msg[5]=0;
- msg[6]=virt_to_phys(work8);
+ msg[6]=virt_to_phys(status);
msg[7]=0; /* 64bit host FIXME */
- /* Then reset the IOP */
i2o_post_message(c,m);
/* Wait for a reply */
time=jiffies;
-
- /* DPT driver claims they need this */
- mdelay(5);
-
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Reset posted, waiting...\n");
-#endif
- while(work8[0]==0)
+ while (status[0]==0)
{
if((jiffies-time)>=5*HZ)
{
- printk(KERN_ERR "IOP reset timeout.\n");
- kfree(work8);
+ printk(KERN_ERR "%s: IOP reset timeout.\n", c->name);
+ kfree(status);
return -ETIMEDOUT;
}
schedule();
barrier();
}
- if (work8[0]==0x02)
- {
- printk(KERN_WARNING "IOP Reset rejected\n");
- }
+ if (status[0]==0x02)
+ printk(KERN_WARNING "%s: Reset rejected.\n",c->name);
else
{
/*
* Once the reset is sent, the IOP goes into the INIT state
- * which is indeterminate. We need to wait until the IOP
+ * which is inditerminate. We need to wait until the IOP
* has rebooted before we can let the system talk to
* it. We read the inbound Free_List until a message is
* available. If we can't read one in the given ammount of
* time, we assume the IOP could not reboot properly.
*/
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Reset succeeded...waiting for reboot\n");
-#endif
+
time = jiffies;
m = I2O_POST_READ32(c);
while(m == 0XFFFFFFFF)
{
if((jiffies-time) >= 30*HZ)
{
- printk(KERN_ERR "i2o/iop%d: Timeout waiting for IOP reset.\n",
- c->unit);
+ printk(KERN_ERR "%s: Timeout waiting for IOP reset.\n",
+ c->name);
+ kfree(status);
return -ETIMEDOUT;
}
schedule();
barrier();
m = I2O_POST_READ32(c);
}
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Reboot completed\n");
-#endif
+
+ i2o_flush_reply(c,m);
+ printk(KERN_INFO "%s: Reset completed.\n", c->name);
}
+ kfree(status);
return 0;
}
@@ -1235,127 +1057,172 @@ int i2o_status_get(struct i2o_controller *c)
u32 m;
u32 *msg;
u8 *status_block;
- int i;
-
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
-#endif
- if(c->status_block)
- kfree(c->status_block);
- c->status_block =
- (i2o_status_block *)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
- if(c->status_block == NULL)
- {
-#ifdef DRIVERDEBUG
- printk(KERN_ERR "No memory in status get!\n");
-#endif
- return -ENOMEM;
+ if (c->status_block == NULL) {
+ c->status_block = (i2o_status_block *)
+ kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
+ if (c->status_block == NULL)
+ {
+ printk(KERN_CRIT "%s: Get Status Block failed; Out of memory.\n", c->name);
+ return -ENOMEM;
+ }
}
status_block = (u8*)c->status_block;
-
+ memset(c->status_block,0,sizeof(i2o_status_block));
+
m=i2o_wait_message(c, "StatusGet");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
-
- memset(status_block, 0, sizeof(i2o_status_block));
msg=(u32 *)(c->mem_offset+m);
- __raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
- __raw_writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
- __raw_writel(0, &msg[2]);
- __raw_writel(0, &msg[3]);
- __raw_writel(0, &msg[4]);
- __raw_writel(0, &msg[5]);
- __raw_writel(virt_to_bus(c->status_block), &msg[6]);
- __raw_writel(0, &msg[7]); /* 64bit host FIXME */
- __raw_writel(sizeof(i2o_status_block), &msg[8]);
-
+
+ msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
+ msg[2]=core_context;
+ msg[3]=0;
+ msg[4]=0;
+ msg[5]=0;
+ msg[6]=virt_to_phys(c->status_block);
+ msg[7]=0; /* 64bit host FIXME */
+ msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
+
i2o_post_message(c,m);
-
- /* DPT work around */
- mdelay(5);
/* Wait for a reply */
- time=jiffies;
- while((jiffies-time)<=HZ)
+ time=jiffies;
+ while(status_block[87]!=0xFF)
{
- if(status_block[87]!=0)
+ if((jiffies-time)>=5*HZ)
{
- /* Ok the reply has arrived. Fill in the important stuff */
- c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
- return 0;
+ printk(KERN_ERR "%s: Get status timeout.\n",c->name);
+ return -ETIMEDOUT;
}
schedule();
barrier();
}
+
+ /* Ok the reply has arrived. Fill in the important stuff */
+ c->inbound_size = c->status_block->inbound_frame_size *4;
+
#ifdef DRIVERDEBUG
- printk(KERN_ERR "IOP get status timeout.\n");
+ printk(KERN_INFO "%s: State = ", c->name);
+ switch (c->status_block->iop_state) {
+ case 0x01:
+ printk("INIT\n");
+ break;
+ case 0x02:
+ printk("RESET\n");
+ break;
+ case 0x04:
+ printk("HOLD\n");
+ break;
+ case 0x05:
+ printk("READY\n");
+ break;
+ case 0x08:
+ printk("OPERATIONAL\n");
+ break;
+ case 0x10:
+ printk("FAILED\n");
+ break;
+ case 0x11:
+ printk("FAULTED\n");
+ break;
+ default:
+ printk("%x (unknown !!)\n",c->status_block->iop_state);
+ }
#endif
- return -ETIMEDOUT;
+
+ return 0;
}
int i2o_hrt_get(struct i2o_controller *c)
{
u32 msg[6];
+ int ret, size = sizeof(i2o_hrt);
- if(c->hrt)
- kfree(c->hrt);
+ /* Read first just the header to figure out the real size */
- c->hrt=kmalloc(2048, GFP_KERNEL);
- if(c->hrt==NULL)
- {
- printk(KERN_ERR "IOP init failed; no memory.\n");
- return -ENOMEM;
- }
+ do {
+ if (c->hrt == NULL) {
+ c->hrt=kmalloc(size, GFP_KERNEL);
+ if (c->hrt == NULL) {
+ printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", c->name);
+ return -ENOMEM;
+ }
+ }
- msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
- msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2]= core_context;
- msg[3]= 0x0; /* Transaction context */
- msg[4]= (0xD0000000 | 2048); /* Simple transaction , 2K */
- msg[5]= virt_to_phys(c->hrt); /* Dump it here */
+ msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
+ msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
+ msg[4]= (0xD0000000 | size); /* Simple transaction */
+ msg[5]= virt_to_phys(c->hrt); /* Dump it here */
+
+ if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
+ printk(KERN_ERR "%s: Unable to get HRT,"
+ " Status = %d.\n",c->name, ret);
+ return ret;
+ }
+
+ if (c->hrt->num_entries * c->hrt->entry_len << 2 > size) {
+ size = c->hrt->num_entries * c->hrt->entry_len << 2;
+ kfree(c->hrt);
+ c->hrt = NULL;
+ }
+ } while (c->hrt == NULL);
+
+ i2o_parse_hrt(c); // just for debugging
- return i2o_post_wait(c, msg, sizeof(msg), 20);
+ return 0;
}
-static int i2o_systab_send(struct i2o_controller* iop)
+static int i2o_systab_send(struct i2o_controller *iop)
{
- u32 msg[10];
- u32 privmem[2];
- u32 privio[2];
- int ret;
+ u32 msg[12];
+ u32 privmem[2];
+ u32 privio[2];
+ int ret;
- privmem[0]=iop->priv_mem; /* Private memory space base address */
- privmem[1]=iop->priv_mem_size;
- privio[0]=iop->priv_io; /* Private I/O address */
- privio[1]=iop->priv_io_size;
-
- msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6;
- msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2] = 0; /* Context not needed */
- msg[3] = 0;
- msg[4] = (0<<16)|((iop->unit+2)<<12); /* Host 0 IOP ID (unit + 2) */
- msg[5] = 0; /* Segment 0 */
-
- /*
- * Scatter Gather List
+ /* See i2o_status_block */
+#if 0
+ iop->status->current_mem_base;
+ iop->status->current_mem_size;
+ iop->status->current_io_base;
+ iop->status->current_io_size;
+#endif
+ privmem[0]=iop->priv_mem; /* Private memory space base address */
+ privmem[1]=iop->priv_mem_size;
+ privio[0]=iop->priv_io; /* Private I/O address */
+ privio[1]=iop->priv_io_size;
+
+ msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
+ msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
+ /* [2] and [3] filled in i2o_post_wait */
+ msg[4] = (0<<16) | ((iop->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
+ msg[5] = 0; /* Segment 0 */
+
+ /*
+ * Provide three SGL-elements:
+ * System table (SysTab), Private memory space declaration and
+ * Private i/o space declaration
*/
- msg[6] = 0x54000000|sys_tbl_len;
- msg[7] = virt_to_phys(sys_tbl);
- msg[8] = 0xD4000000|48; /* One table for now */
- msg[9] = virt_to_phys(privmem);
-/* msg[10] = virt_to_phys(privio); */
-
- ret=i2o_post_wait(iop, msg, sizeof(msg), 120);
- if(ret)
- return ret;
+ msg[6] = 0x54000000 | sys_tbl_len;
+ msg[7] = virt_to_phys(sys_tbl);
+ msg[8] = 0x54000000 | 0;
+ msg[9] = virt_to_phys(privmem);
+ msg[10] = 0xD4000000 | 0;
+ msg[11] = virt_to_phys(privio);
- return 0;
-}
+ if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
+ printk(KERN_INFO "%s: Unable to set SysTab, %d\n",
+ iop->name, ret);
+
+ return ret;
+
+ }
/*
* Initialize I2O subsystem.
@@ -1550,17 +1417,20 @@ static void __init i2o_sys_init()
*
* 1. Quiesce all controllers
* 2. Delete all controllers
- *
*/
static void i2o_sys_shutdown(void)
{
- struct i2o_controller *iop = NULL;
+ struct i2o_controller *iop, *niop;
- i2o_quiesce_system();
- for(iop = i2o_controller_chain; iop; iop = iop->next)
- {
- if(i2o_delete_controller(iop))
- iop->bus_disable(iop);
+ for (iop = i2o_controller_chain; iop ; iop=iop->next) {
+ i2o_quiesce_controller(iop);
+ i2o_status_get(iop); // Update IOP status block
+ }
+
+ for (iop = i2o_controller_chain; iop; iop = niop) {
+ niop = iop->next;
+ if (i2o_delete_controller(iop))
+ iop->bus_disable(iop);
}
}
@@ -1589,8 +1459,8 @@ int i2o_activate_controller(struct i2o_controller *c)
int i;
int ret;
- printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n",
- (u32)c->mem_phys);
+ printk(KERN_INFO "%s: Configuring I2O controller at 0x%08X.\n",
+ c->name, (u32)c->mem_phys);
if((ret=i2o_status_get(c)))
return ret;
@@ -1627,43 +1497,20 @@ int i2o_activate_controller(struct i2o_controller *c)
return ret;
}
- if((ret=i2o_init_outbound_q(c)))
- {
- printk(KERN_ERR
- "IOP%d initialization failed: Could not initialize outbound queue\n",
- c->unit);
+ if ((ret=i2o_init_outbound_q(c))){
return ret;
}
/* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
- c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
- if(c->page_frame==NULL)
- {
- printk(KERN_ERR "IOP init failed: no memory for message page.\n");
- return -ENOMEM;
- }
-
- m=virt_to_phys(c->page_frame);
-
- for(i=0; i< NMBR_MSG_FRAMES; i++)
- {
- I2O_REPLY_WRITE32(c,m);
- mb();
- m+=MSG_FRAME_SIZE;
- mb();
- }
-
/*
* The outbound queue is initialised and loaded,
*
* Now we need the Hardware Resource Table. We must ask for
* this next we can't issue random messages yet.
*/
- ret=i2o_hrt_get(c); if(ret) return ret;
-
- ret=i2o_parse_hrt(c);
- if(ret)
+
+ if ((ret=i2o_hrt_get(c)))
return ret;
return i2o_online_controller(c);
@@ -1675,23 +1522,26 @@ int i2o_activate_controller(struct i2o_controller *c)
*/
int i2o_init_outbound_q(struct i2o_controller *c)
{
- u8 workspace[88];
+ u8 *status;
u32 m;
u32 *msg;
u32 time;
+ int i;
- memset(workspace, 0, 88);
-
-// printk(KERN_INFO "i2o/iop%d: Initializing Outbound Queue\n", c->unit);
m=i2o_wait_message(c, "OutboundInit");
if(m==0xFFFFFFFF)
- {
- kfree(workspace);
return -ETIMEDOUT;
- }
-
msg=(u32 *)(c->mem_offset+m);
+
+ status = kmalloc(4,GFP_KERNEL);
+ if (status==NULL) {
+ printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
+ c->name);
+ return -ENOMEM;
+ }
+ memset(status, 0, 4);
+
msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
msg[2]= core_context;
@@ -1699,30 +1549,41 @@ int i2o_init_outbound_q(struct i2o_controller *c)
msg[4]= 4096; /* Host page frame size */
msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size and Initcode */
msg[6]= 0xD0000004; /* Simple SG LE, EOB */
- msg[7]= virt_to_bus(workspace);
- *((u32 *)workspace)=0;
+ msg[7]= virt_to_phys(status);
- /*
- * Post it
- */
i2o_post_message(c,m);
- barrier();
-
+ barrier();
time=jiffies;
-
- while(workspace[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE)
+ while(status[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE)
{
if((jiffies-time)>=5*HZ)
{
- printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
- c->unit);
+ printk(KERN_ERR "%s: Outbound Q initialize timeout.\n",
+ c->name);
+ kfree(status);
return -ETIMEDOUT;
}
schedule();
barrier();
}
+ c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
+ if(c->page_frame==NULL) {
+ printk(KERN_CRIT "%s: Outbound Q initialize failed; out of memory.\n",
+ c->name);
+ kfree(status);
+ return -ENOMEM;
+ }
+ m=virt_to_phys(c->page_frame);
+
+ for(i=0; i< NMBR_MSG_FRAMES; i++) {
+ I2O_REPLY_WRITE32(c,m);
+ mb();
+ m += MSG_FRAME_SIZE;
+ }
+
+ kfree(status);
return 0;
}
@@ -1732,34 +1593,41 @@ int i2o_init_outbound_q(struct i2o_controller *c)
int i2o_lct_get(struct i2o_controller *c)
{
u32 msg[8];
+ int ret, size = c->status_block->expected_lct_size;
+
+ do {
+ if (c->lct == NULL) {
+ c->lct = kmalloc(size, GFP_KERNEL);
+ if(c->lct == NULL) {
+ printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
+ c->name);
+ return -ENOMEM;
+ }
+ }
+ memset(c->lct, 0, size);
+
+ msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
+ msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
+ msg[4] = 0xFFFFFFFF; /* All devices */
+ msg[5] = 0x00000000; /* Report now */
+ msg[6] = 0xD0000000|size;
+ msg[7] = virt_to_bus(c->lct);
+
+ if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
+ printk(KERN_ERR "%s: Unable to get LCT,"
+ " Status = %d.\n", c->name,ret);
+ return ret;
+ }
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Getting lct for iop%d\n", c->unit);
-#endif
-
- if(c->lct)
- kfree(c->lct);
+ if (c->lct->table_size << 2 > size) {
+ size = c->lct->table_size << 2;
+ kfree(c->lct);
+ c->lct = NULL;
+ }
+ } while (c->lct == NULL);
- c->lct = kmalloc(8192, GFP_KERNEL);
- if(c->lct==NULL)
- {
- printk(KERN_ERR "i2o/iop%d: No free memory for i2o controller buffer.\n",
- c->unit);
- return -ENOMEM;
- }
-
- memset(c->lct, 0, 8192);
-
- msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
- msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2] = 0; /* Context not needed */
- msg[3] = 0;
- msg[4] = 0xFFFFFFFF; /* All devices */
- msg[5] = 0x00000000; /* Report now */
- msg[6] = 0xD0000000|8192;
- msg[7] = virt_to_bus(c->lct);
-
- return(i2o_post_wait(c, msg, sizeof(msg), 120));
+ return 0;
}
@@ -1774,69 +1642,67 @@ int i2o_online_controller(struct i2o_controller *c)
u32 msg[10];
u32 privmem[2];
u32 privio[2];
- u32 systab[32];
int ret;
- systab[0]=1;
- systab[1]=0;
- systab[2]=0;
- systab[3]=0;
- systab[4]=0; /* Organisation ID */
- systab[5]=2; /* Ident 2 for now */
- systab[6]=0<<24|0<<16|I2OVERSION<<12|1; /* Memory mapped, IOPState, v1.5, segment 1 */
- systab[7]=MSG_FRAME_SIZE>>2; /* Message size */
- systab[8]=0; /* LastChanged */
- systab[9]=0; /* Should be IOP capabilities */
- systab[10]=virt_to_phys(c->post_port);
- systab[11]=0;
-
- i2o_build_sys_table();
+ /*
+ * Build and send the system table
+ *
+ * If build_sys_table fails, we kill everything and bail
+ * as we can't init the IOPs w/o a system table
+ */
+
+ if (i2o_build_sys_table()) {
+ i2o_sys_shutdown();
+ return;
+ }
privmem[0]=c->priv_mem; /* Private memory space base address */
privmem[1]=c->priv_mem_size;
privio[0]=c->priv_io; /* Private I/O address */
privio[1]=c->priv_io_size;
- __raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_6, &msg[0]);
- __raw_writel(I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
- __raw_writel(0, &msg[2]); /* Context not needed */
- __raw_writel(0, &msg[3]);
- __raw_writel((0<<16)|(2<<12), &msg[4]); /* Host 1 I2O 2 */
- __raw_writel(0, &msg[5]); /* Segment 1 */
-
- /*
- * Scatter Gather List
- */
-
- __raw_writel(0x54000000|sys_tbl_len, &msg[6]); /* One table for now */
- __raw_writel(virt_to_phys(sys_tbl), &msg[[7]);
- __raw_writel(0xD4000000|48, &msg[8]); /* One table for now */
- __raw_writel(virt_to_phys(privmem), &msg[9]);
-
- return(i2o_post_wait(c, msg, sizeof(msg), 120));
-
- /*
- * Finally we go online
- */
- ret = i2o_enable_controller(c);
- if(ret)
- return ret;
-
- /*
- * Grab the LCT, see what is attached
- */
- ret=i2o_lct_get(c);
- if(ret)
- {
- /* Maybe we should do also do something else */
- return ret;
- }
+ __raw_writel(TEN_WORD_MSG_SIZE|SGL_OFFSET_6, &msg[0]);
+ __raw_writel(I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID, &msg$
+ __raw_writel(0, &msg[2]); /* Context not needed */
+ __raw_writel(0, &msg[3]);
+ __raw_writel((0<<16)|(2<<12), &msg[4]); /* Host 1 I2O 2 */
+ __raw_writel(0, &msg[5]); /* Segment 1 */
+
+ /*
+ * Scatter Gather List
+ */
+
+ __raw_writel(0x54000000|sys_tbl_len, &msg[6]); /* One table for now */
+ __raw_writel(virt_to_phys(sys_tbl), &msg[[7]);
+ __raw_writel(0xD4000000|48, &msg[8]); /* One table for now */
+ __raw_writel(virt_to_phys(privmem), &msg[9]);
+
+ ret = (i2o_post_wait(c, msg, sizeof(msg), 120);
+ if (ret)
+ return ret;
+
+ /*
+ * Finally we go online
+ */
+ ret = i2o_enable_controller(c);
+ if(ret)
+ return ret;
+
+ /*
+ * Grab the LCT, see what is attached
+ */
+ ret=i2o_lct_get(c);
+ if(ret)
+ {
+ /* Maybe we should do also do something else */
+ return ret;
+ }
- ret=i2o_parse_lct(c);
- if(ret)
- return ret;
+ ret=i2o_parse_lct(c);
+ if(ret)
+ return ret;
- return 0;
+ return 0;
#endif
}
@@ -1844,23 +1710,19 @@ static int i2o_build_sys_table(void)
{
struct i2o_controller *iop = NULL;
int count = 0;
-#ifdef DRIVERDEBUG
- u32 *table;
-#endif
sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
(i2o_num_controllers) *
sizeof(struct i2o_sys_tbl_entry);
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Building system table len = %d\n", sys_tbl_len);
-#endif
if(sys_tbl)
kfree(sys_tbl);
sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL);
- if(!sys_tbl)
+ if(!sys_tbl) {
+ printk(KERN_CRIT "SysTab Set failed. Out of memory.\n");
return -ENOMEM;
+ }
memset((void*)sys_tbl, 0, sys_tbl_len);
sys_tbl->num_entries = i2o_num_controllers;
@@ -1869,8 +1731,11 @@ static int i2o_build_sys_table(void)
for(iop = i2o_controller_chain; iop; iop = iop->next)
{
- // Get updated IOP state so we have the latest information
- i2o_status_get(iop);
+ // Get updated Status Block so we have the latest information
+ if (i2o_status_get(iop)) {
+ sys_tbl->num_entries--;
+ continue; // try next one
+ }
sys_tbl->iops[count].org_id = iop->status_block->org_id;
sys_tbl->iops[count].iop_id = iop->unit + 2;
@@ -1894,9 +1759,12 @@ static int i2o_build_sys_table(void)
}
#ifdef DRIVERDEBUG
- table = (u32*)sys_tbl;
+{
+ u32 *table = (u32*)sys_tbl;
for(count = 0; count < (sys_tbl_len >>2); count++)
- printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
+ printk(KERN_INFO "sys_tbl[%d] = %0#10x\n",
+ count, table[count]);
+}
#endif
return 0;
@@ -1929,12 +1797,13 @@ int i2o_post_this(struct i2o_controller *c, u32 *data, int len)
if(m==0xFFFFFFFF)
{
- printk(KERN_ERR "i2o/iop%d: Timeout waiting for message frame!\n",
- c->unit);
+ printk(KERN_ERR "%s: Timeout waiting for message frame!\n",
+ c->name);
return -ETIMEDOUT;
}
+
msg = (u32 *)(c->mem_offset + m);
- memcpy_toio(msg, data, len);
+ memcpy_toio(msg, data, len);
i2o_post_message(c,m);
return 0;
}
@@ -1947,16 +1816,13 @@ int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
int status = 0;
int flags = 0;
- int ret = 0;
struct i2o_post_wait_data *p1, *p2;
struct i2o_post_wait_data *wait_data =
kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
if(!wait_data)
- return -ETIMEDOUT;
+ return -ENOMEM;
- p1 = p2 = NULL;
-
/*
* The spin locking is needed to keep anyone from playing
* with the queue pointers and id while we do the same
@@ -1964,48 +1830,29 @@ int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
spin_lock_irqsave(&post_wait_lock, flags);
wait_data->next = post_wait_queue;
post_wait_queue = wait_data;
- wait_data->id = ++post_wait_id;
+ wait_data->id = (++post_wait_id) & 0x7fff;
spin_unlock_irqrestore(&post_wait_lock, flags);
wait_data->wq = &wq_i2o_post;
- wait_data->status = -ETIMEDOUT;
+ wait_data->status = -EAGAIN;
- msg[3] = (u32)wait_data->id;
- msg[2] = 0x80000000|(u32)core_context;
+ msg[2]=0x80000000|(u32)core_context|((u32)wait_data->id<<16);
- if((ret=i2o_post_this(c, msg, len)))
- return ret;
- /*
- * Go to sleep and wait for timeout or wake_up call
- */
- interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
-
- /*
- * Grab transaction status
- */
- status = wait_data->status;
+ if ((status = i2o_post_this(c, msg, len))==0) {
+ interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
+ status = wait_data->status;
+ }
- /*
- * Remove the entry from the queue.
- * Since i2o_post_wait() may have been called again by
- * a different thread while we were waiting for this
- * instance to complete, we're not guaranteed that
- * this entry is at the head of the queue anymore, so
- * we need to search for it, find it, and delete it.
- */
+ p2 = NULL;
spin_lock_irqsave(&post_wait_lock, flags);
- for(p1 = post_wait_queue; p1; )
- {
- if(p1 == wait_data)
- {
+ for(p1 = post_wait_queue; p1; p2 = p1, p1 = p1->next) {
+ if(p1 == wait_data) {
if(p2)
p2->next = p1->next;
else
post_wait_queue = p1->next;
-
break;
}
- p1 = p1->next;
}
spin_unlock_irqrestore(&post_wait_lock, flags);
@@ -2020,7 +1867,7 @@ int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
*/
static void i2o_post_wait_complete(u32 context, int status)
{
- struct i2o_post_wait_data *p1 = NULL;
+ struct i2o_post_wait_data *p1;
/*
* We need to search through the post_wait
@@ -2035,42 +1882,75 @@ static void i2o_post_wait_complete(u32 context, int status)
* around while we're looking through them.
*/
spin_lock(&post_wait_lock);
- for(p1 = post_wait_queue; p1; p1 = p1->next)
- {
- if(p1->id == context)
- {
+ for(p1 = post_wait_queue; p1; p1 = p1->next) {
+ if(p1->id == ((context >> 16) & 0x7fff)) {
p1->status = status;
- wake_up_interruptible(p1->wq);
spin_unlock(&post_wait_lock);
+ wake_up_interruptible(p1->wq);
return;
}
}
spin_unlock(&post_wait_lock);
- printk(KERN_DEBUG "i2o_post_wait reply after timeout!");
+ printk(KERN_DEBUG "i2o: i2o_post_wait reply after timeout!");
}
/*
- * Issue UTIL_CLAIM messages
+ * Send UTIL_EVENT messages
+ */
+
+int i2o_event_register(struct i2o_controller *c, int tid, int context,
+ u32 evt_mask)
+{
+ u32 msg[5];
+
+ msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ msg[1] = I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | tid;
+ msg[2] = context;
+ msg[3] = 0;
+ msg[4] = evt_mask;
+
+ if (i2o_post_this(c, msg, sizeof(msg)) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int i2o_event_ack(struct i2o_controller *c, int tid, int context,
+ u32 evt_indicator, void *evt_data, int evt_data_len)
+{
+ u32 msg[c->inbound_size];
+
+ msg[0] = I2O_MESSAGE_SIZE(5 + evt_data_len / 4) | SGL_OFFSET_5;
+ msg[1] = I2O_CMD_UTIL_EVT_ACK << 24 | HOST_TID << 12 | tid;
+ /* msg[2] and msg[3] filled in i2o_post_wait */
+ msg[4] = evt_indicator;
+ memcpy(msg+5, evt_data, evt_data_len);
+
+ if (i2o_post_this(c, msg, sizeof(msg)) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/*
+ * Issue UTIL_CLAIM or UTIL_RELEASE messages
*/
-int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, int *flag, u32 type)
+static int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, u32 type)
{
- u32 msg[6];
+ u32 msg[5];
msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
if(onoff)
msg[1] = I2O_CMD_UTIL_CLAIM << 24 | HOST_TID<<12 | tid;
else
msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid;
-
- /* The 0x80000000 convention for flagging is assumed by this helper */
-
- msg[2] = 0x80000000|context;
- msg[3] = (u32)flag;
+
+ /* msg[2] and msg[3] filled in i2o_post_wait */
msg[4] = type;
- return i2o_post_wait(c, msg, 20, 2);
+ return i2o_post_wait(c, msg, sizeof(msg), 2);
}
/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
@@ -2085,10 +1965,7 @@ int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,
void *opblk, int oplen, void *resblk, int reslen)
{
u32 msg[9];
- u8 *res = (u8 *)resblk;
- int res_count;
- int blk_size;
- int bytes;
+ u32 *res = (u32 *)resblk;
int wait_status;
msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
@@ -2099,31 +1976,21 @@ int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,
msg[7] = 0xD0000000 | reslen; /* ResultBlock */
msg[8] = virt_to_bus(resblk);
- wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10);
- if (wait_status)
- return wait_status; /* -DetailedStatus */
+ if ((wait_status = i2o_post_wait(iop, msg, sizeof(msg), 20)))
+ return wait_status; /* -DetailedStatus */
if (res[1]&0x00FF0000) /* BlockStatus != SUCCESS */
{
- printk(KERN_WARNING "%s - Error:\n ErrorInfoSize = 0x%02x, "
- "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
- (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
- : "PARAMS_GET",
- res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
+ printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, "
+ "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
+ iop->name,
+ (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
+ : "PARAMS_GET",
+ res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
}
- res_count = res[0] & 0xFFFF; /* # of resultblocks */
- bytes = 4;
- res += 4;
- while (res_count--)
- {
- blk_size = (res[0] & 0xFFFF) << 2;
- bytes += blk_size;
- res += blk_size;
- }
-
- return bytes; /* total sizeof Result List in bytes */
+ return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */
}
/*
@@ -2138,10 +2005,10 @@ int i2o_query_scalar(struct i2o_controller *iop, int tid,
if (field == -1) /* whole group */
opblk[4] = -1;
-
+
size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid,
opblk, sizeof(opblk), resblk, sizeof(resblk));
-
+
if (size < 0)
return size;
@@ -2673,6 +2540,10 @@ EXPORT_SYMBOL(i2o_delete_controller);
EXPORT_SYMBOL(i2o_unlock_controller);
EXPORT_SYMBOL(i2o_find_controller);
EXPORT_SYMBOL(i2o_num_controllers);
+
+EXPORT_SYMBOL(i2o_event_register);
+EXPORT_SYMBOL(i2o_event_ack);
+
EXPORT_SYMBOL(i2o_claim_device);
EXPORT_SYMBOL(i2o_release_device);
EXPORT_SYMBOL(i2o_run_queue);
@@ -2691,7 +2562,6 @@ EXPORT_SYMBOL(i2o_row_delete_table);
EXPORT_SYMBOL(i2o_post_this);
EXPORT_SYMBOL(i2o_post_wait);
-EXPORT_SYMBOL(i2o_issue_claim);
EXPORT_SYMBOL(i2o_issue_params);
EXPORT_SYMBOL(i2o_report_status);
@@ -2699,25 +2569,23 @@ EXPORT_SYMBOL(i2o_report_status);
MODULE_AUTHOR("Red Hat Software");
MODULE_DESCRIPTION("I2O Core");
-
int init_module(void)
{
- printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
+ printk(KERN_INFO "I2O Core - (c) Copyright 1999 Red Hat Software.\n");
if (i2o_install_handler(&i2o_core_handler) < 0)
{
printk(KERN_ERR
- "i2o_core: Unable to install core handler.\nI2O stack not loaded!");
+ "i2o: Unable to install core handler.\nI2O stack not loaded!");
return 0;
}
core_context = i2o_core_handler.context;
-
/*
* Attach core to I2O PCI transport (and others as they are developed)
*/
#ifdef CONFIG_I2O_PCI_MODULE
if(i2o_pci_core_attach(&i2o_core_functions) < 0)
- printk(KERN_INFO "No PCI I2O controllers found\n");
+ printk(KERN_INFO "i2o: No PCI I2O controllers found\n");
#endif
if(i2o_num_controllers)
diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c
index c95162863..08fcc2c2c 100644
--- a/drivers/i2o/i2o_lan.c
+++ b/drivers/i2o/i2o_lan.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/i2o/i2o_lan.c
*
- * I2O LAN CLASS OSM Prototyping, November 8th 1999
+ * I2O LAN CLASS OSM December 2nd 1999
*
* (C) Copyright 1999 University of Helsinki,
* Department of Computer Science
@@ -20,8 +20,7 @@
* Tested: in FDDI environment (using SysKonnect's DDM)
* in Ethernet environment (using Intel 82558 DDM proto)
*
- * TODO: batch mode sends
- * error checking / timeouts
+ * TODO: check error checking / timeouts
* code / test for other LAN classes
*/
@@ -45,7 +44,7 @@
#include <linux/i2o.h>
#include "i2o_lan.h"
-#define DRIVERDEBUG
+//#define DRIVERDEBUG
#ifdef DRIVERDEBUG
#define dprintk(s, args...) printk(s, ## args)
#else
@@ -68,16 +67,22 @@ struct i2o_lan_local {
struct fddi_statistics stats; /* see also struct net_device_stats */
unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
u32 bucket_count; /* nbr of buckets sent to DDM */
- u32 tx_count; /* nbr of outstanding TXes */
- u32 max_tx; /* DDM's Tx queue len */
+ u32 tx_count; /* packets in one TX message frame */
+ u32 tx_max; /* DDM's Tx queue len */
+ u32 tx_out; /* outstanding TXes */
+ u32 sgl_max; /* max SGLs in one message frame */
+ u32 m; /* IOP address of msg frame */
+
+ struct sk_buff **i2o_fbl; /* Free bucket list (to reuse skbs) */
+ int i2o_fbl_tail;
spinlock_t lock;
};
static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
- struct i2o_message *m);
-static void i2o_lan_event_reply(struct net_device *dev, u32 *msg);
-static int i2o_lan_receive_post(struct net_device *dev, u32 count);
+ struct i2o_message *m);
+static void i2o_lan_event_reply(struct net_device *dev, u32 *msg);
+static int i2o_lan_receive_post(struct net_device *dev);
static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg);
static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg);
@@ -87,8 +92,11 @@ static struct i2o_handler i2o_lan_handler = {
0, // context
I2O_CLASS_LAN
};
-static int lan_context;
+static int lan_context;
+static struct tq_struct i2o_post_buckets_task = {
+ 0, 0, (void (*)(void *))i2o_lan_receive_post, (void *) 0
+};
static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
struct i2o_message *m)
@@ -116,10 +124,10 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
i2o_report_status(KERN_INFO, dev->name, msg);
switch (msg[1] >> 24) {
- case LAN_RECEIVE_POST:
+ case LAN_RECEIVE_POST:
{
if (dev->start) {
- if(!(msg[4]>>24)) {
+ if (!(msg[4]>>24)) {
i2o_lan_receive_post_reply(dev,msg);
break;
}
@@ -128,27 +136,27 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
printk( KERN_WARNING "i2olan: Device %s rejected bucket post.\n", dev->name);
}
- // Getting unused buckets back
+ // Shutting down, we are getting unused buckets back
i2o_lan_release_buckets(dev,msg);
break;
}
case LAN_PACKET_SEND:
- case LAN_SDU_SEND:
+ case LAN_SDU_SEND:
{
- struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
- u8 trl_count = msg[3] & 0x000000FF;
-
- while (trl_count) {
- // The HDM has handled the outgoing packet
+ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+ u8 trl_count = msg[3] & 0x000000FF;
+
+ while (trl_count) {
+ // The HDM has handled the outgoing packet
dev_kfree_skb((struct sk_buff *)msg[4 + trl_count]);
- printk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n",
+ dprintk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n",
dev->name,trl_count);
- priv->tx_count--;
+ priv->tx_out--;
trl_count--;
}
-
+
if (dev->tbusy) {
clear_bit(0,(void*)&dev->tbusy);
mark_bh(NET_BH); /* inform upper layers */
@@ -217,7 +225,7 @@ static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
break;
case I2O_EVT_IND_DEVICE_RESET:
printk("Device reset.\n");
- break;
+ break;
case I2O_EVT_IND_EVT_MASK_MODIFIED:
printk("Event mask modified, 0x%08X.\n",
evt->evt_data[0]);
@@ -267,22 +275,20 @@ static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
/* else evt->function == I2O_CMD_UTIL_EVT_ACK) */
/* Do we need to do something here too? */
-}
-
+}
-void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
+static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
{
- struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
- u8 trl_count = (u8)(msg[3] & 0x000000FF);
+ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+ u8 trl_count = (u8)(msg[3] & 0x000000FF);
u32 *pskb = &msg[6];
- while (trl_count) {
+ while (trl_count--) {
dprintk("%s: Releasing unused sk_buff %p.\n",dev->name,
(struct sk_buff*)(*pskb));
dev_kfree_skb((struct sk_buff*)(*pskb));
pskb++;
priv->bucket_count--;
- trl_count--;
}
}
@@ -291,50 +297,35 @@ static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_bucket_descriptor *bucket = (struct i2o_bucket_descriptor *)&msg[6];
struct i2o_packet_info *packet;
-
- u8 trl_count = msg[3] & 0x000000FF;
- struct sk_buff *skb, *newskb;
+ u8 trl_count = msg[3] & 0x000000FF;
+ struct sk_buff *skb, *old_skb;
-#if 0
- dprintk(KERN_INFO "TrlFlags = 0x%02X, TrlElementSize = %d, TrlCount = %d\n"
- "msgsize = %d, buckets_remaining = %d\n",
- msg[3]>>24, msg[3]&0x0000FF00, trl_count, msg[0]>>16, msg[5]);
-#endif
while (trl_count--) {
- skb = (struct sk_buff *)(bucket->context);
+ skb = (struct sk_buff *)bucket->context;
packet = (struct i2o_packet_info *)bucket->packet_info;
priv->bucket_count--;
-#if 0
- dprintk(KERN_INFO "Buckets_remaining = %d, bucket_count = %d, trl_count = %d\n",
- msg[5], priv->bucket_count, trl_count);
-
- dprintk(KERN_INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n",
- packet->flags, packet->offset, packet->status, packet->len);
-#endif
if (packet->len < rx_copybreak) {
- newskb = (struct sk_buff *)
- dev_alloc_skb(packet->len+2);
- if (newskb) {
- skb_reserve(newskb,2);
- memcpy(skb_put(newskb,packet->len), skb->data, packet->len);
- newskb->dev = dev;
- newskb->protocol = priv->type_trans(newskb, dev);
-
- netif_rx(newskb);
- dev_kfree_skb(skb); // FIXME: reuse this skb?
- }
- else {
+ old_skb = skb;
+ skb = (struct sk_buff *)dev_alloc_skb(packet->len+2);
+ if (skb == NULL) {
printk("%s: Can't allocate skb.\n", dev->name);
return -ENOMEM;
- }
- } else {
- skb_put(skb,packet->len);
- skb->dev = dev;
- skb->protocol = priv->type_trans(skb, dev);
+ }
+ skb_reserve(skb,2);
+ memcpy(skb_put(skb,packet->len), old_skb->data, packet->len);
+
+ if (priv->i2o_fbl_tail < I2O_BUCKET_COUNT)
+ priv->i2o_fbl[++priv->i2o_fbl_tail] = old_skb;
+ else
+ dev_kfree_skb(old_skb);
+ } else
+ skb_put(skb,packet->len);
+
+ skb->dev = dev;
+ skb->protocol = priv->type_trans(skb, dev);
+ netif_rx(skb);
- netif_rx(skb);
- }
dprintk(KERN_INFO "%s: Incoming packet (%d bytes) delivered "
"to upper level.\n",dev->name,packet->len);
@@ -344,67 +335,74 @@ static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
if ((msg[4] & 0x000000FF) == I2O_LAN_DSC_BUCKET_OVERRUN)
printk(KERN_INFO "%s: DDM out of buckets (count = %d)!\n",
dev->name, msg[5]);
-
- if (priv->bucket_count <= bucketpost - bucketthresh)
- i2o_lan_receive_post(dev, bucketpost - priv->bucket_count);
+ if (priv->bucket_count <= bucketpost - bucketthresh) {
+// i2o_lan_receive_post(dev);
+ i2o_post_buckets_task.data = (void *)dev;
+ queue_task(&i2o_post_buckets_task, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
return 0;
}
+
/*
* i2o_lan_receive_post(): Post buckets to receive packets.
*/
-static int i2o_lan_receive_post(struct net_device *dev, u32 count)
-{
- struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+static int i2o_lan_receive_post(struct net_device *dev)
+{
+ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
struct i2o_controller *iop = i2o_dev->controller;
struct sk_buff *skb;
- u32 m; u32 *msg;
-
- u32 bucket_len = (dev->mtu + dev->hard_header_len);
- u32 bucket_count;
- int n_elems = (iop->inbound_size - 16 ) / 12; /* msg header + SGLs */
- u32 total = 0;
- int i;
-
- while (total < count) {
- m = I2O_POST_READ32(iop);
- if (m == 0xFFFFFFFF)
- return -ETIMEDOUT;
- msg = (u32 *)(iop->mem_offset + m);
- bucket_count = (total + n_elems < count)
- ? n_elems
- : count - total;
-
- msg[0] = I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4;
- msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
- msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
- msg[3] = bucket_count; // BucketCount
-
- for (i = 0; i < bucket_count; i++) {
- skb = dev_alloc_skb(bucket_len + 2);
- if (skb == NULL)
- return -ENOMEM;
- skb_reserve(skb, 2);
-
- priv->bucket_count++;
-
- msg[4 + 3*i] = 0x51000000 | bucket_len;
- msg[5 + 3*i] = (u32)skb;
- msg[6 + 3*i] = virt_to_bus(skb->data);
- }
- msg[4 + 3*i - 3] |= 0x80000000; // set LE flag
- i2o_post_message(iop,m);
-
- dprintk(KERN_INFO "%s: Sending %d buckets (size %d) to LAN HDM.\n",
- dev->name, bucket_count, bucket_len);
+ u32 m; u32 *msg;
+ u32 bucket_len = (dev->mtu + dev->hard_header_len);
+ u32 total = bucketpost - priv->bucket_count;
+ u32 bucket_count;
+ u32 *sgl_elem;
+
+ while (total) {
+ m = I2O_POST_READ32(iop);
+ if (m == 0xFFFFFFFF)
+ return -ETIMEDOUT;
+ msg = (u32 *)(iop->mem_offset + m);
+
+ bucket_count = (total >= priv->sgl_max) ? priv->sgl_max : total;
+ total -= bucket_count;
+ priv->bucket_count += bucket_count;
+
+ dprintk(KERN_INFO "%s: Sending %d buckets (size %d) to LAN HDM.\n",
+ dev->name, bucket_count, bucket_len);
+
+ __raw_writel(I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4, msg);
+ __raw_writel(LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid, msg+1);
+ __raw_writel(priv->unit << 16 | lan_context, msg+2);
+ __raw_writel(bucket_count, msg+3);
+ sgl_elem = &msg[4];
+
+ while (bucket_count--) {
+ if (priv->i2o_fbl_tail >= 0)
+ skb = priv->i2o_fbl[priv->i2o_fbl_tail--];
+ else {
+ skb = dev_alloc_skb(bucket_len + 2);
+ if (skb == NULL)
+ return -ENOMEM;
+ skb_reserve(skb, 2);
+ }
+ __raw_writel(0x51000000 | bucket_len, sgl_elem);
+ __raw_writel((u32)skb, sgl_elem+1);
+ __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
+ sgl_elem += 3;
+ }
- total += bucket_count;
- }
+ /* set LE flag and post buckets */
+ __raw_writel(__raw_readl(sgl_elem-3) | 0x80000000, (sgl_elem-3));
+ i2o_post_message(iop,m);
+ }
- return 0;
-}
+ return 0;
+}
/*
* i2o_lan_reset(): Reset the LAN adapter into the operational state and
@@ -441,7 +439,7 @@ static int i2o_lan_suspend(struct net_device *dev)
struct i2o_controller *iop = i2o_dev->controller;
u32 msg[5];
- dprintk( "%s: LAN SUSPEND MESSAGE.\n", dev->name );
+ dprintk(KERN_INFO "%s: LAN SUSPEND MESSAGE.\n", dev->name);
msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
@@ -459,12 +457,6 @@ static int i2o_lan_suspend(struct net_device *dev)
*/
static void i2o_set_batch_mode(struct net_device *dev)
{
-
-/*
- * NOTE: we have not been able to test batch mode
- * since HDMs we have, don't implement it
- */
-
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
struct i2o_controller *iop = i2o_dev->controller;
@@ -474,13 +466,11 @@ static void i2o_set_batch_mode(struct net_device *dev)
// enable batch mode, toggle automatically
val = 0x00000000;
-// val = 0x00000001; // turn off batch mode
if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, sizeof(val)) <0)
printk(KERN_WARNING "%s: Unable to enter I2O LAN batch mode.\n",
dev->name);
- else
+ else
dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name);
-// dprintk(KERN_INFO "%s: I2O LAN batch mode disabled.\n",dev->name);
/*
* When PacketOrphanlimit is same as the maximum packet length,
@@ -508,28 +498,32 @@ static int i2o_lan_open(struct net_device *dev)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
- struct i2o_controller *iop = i2o_dev->controller;
+ struct i2o_controller *iop = i2o_dev->controller;
u32 evt_mask = 0xFFC00007; // All generic events, all lan evenst
if (i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) {
printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
return -EAGAIN;
}
- dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n",
+ dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n",
dev->name, i2o_dev->lct_data->tid);
#if 0
if (i2o_event_register(iop, i2o_dev->lct_data->tid,
priv->unit << 16 | lan_context, evt_mask) < 0)
- printk(KERN_WARNING "%s: Unable to set the event mask.\n",
- dev->name);
+ printk(KERN_WARNING "%s: Unable to set the event mask.\n", dev->name);
#endif
i2o_lan_reset(dev);
+ priv->i2o_fbl = kmalloc(bucketpost * sizeof(struct sk_buff *),GFP_KERNEL);
+ if (priv->i2o_fbl == NULL)
+ return -ENOMEM;
+ priv->i2o_fbl_tail = -1;
+
dev->tbusy = 0;
dev->start = 1;
i2o_set_batch_mode(dev);
- i2o_lan_receive_post(dev, bucketpost);
+ i2o_lan_receive_post(dev);
MOD_INC_USE_COUNT;
@@ -543,14 +537,14 @@ static int i2o_lan_close(struct net_device *dev)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
-//#if 0
- struct i2o_controller *iop = i2o_dev->controller;
+#if 0
+ struct i2o_controller *iop = i2o_dev->controller;
if (i2o_event_register(iop, i2o_dev->lct_data->tid,
priv->unit << 16 | lan_context, 0) < 0)
- printk(KERN_WARNING "%s: Unable to clear the event mask.\n",
+ printk(KERN_WARNING "%s: Unable to clear the event mask.\n",
dev->name);
-//#endif
+#endif
dev->tbusy = 1;
dev->start = 0;
i2o_lan_suspend(dev);
@@ -559,6 +553,10 @@ static int i2o_lan_close(struct net_device *dev)
printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device "
"(tid=%d).\n", dev->name, i2o_dev->lct_data->tid);
+ while (priv->i2o_fbl_tail >= 0)
+ dev_kfree_skb(priv->i2o_fbl[priv->i2o_fbl_tail--]);
+ kfree(priv->i2o_fbl);
+
MOD_DEC_USE_COUNT;
return 0;
@@ -576,6 +574,22 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
}
#endif
+static void i2o_lan_batch_send(struct net_device *dev)
+{
+ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+ struct i2o_controller *iop = priv->i2o_dev->controller;
+
+ if (priv->tx_count != 0) {
+ i2o_post_message(iop, priv->m);
+ dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);
+ priv->tx_count = 0;
+ }
+}
+
+struct tq_struct i2o_post_send_task = {
+ 0, 0, (void (*)(void *))i2o_lan_batch_send, (void *) 0
+};
+
/*
* i2o_lan_packet_send(): Send a packet as is, including the MAC header.
*
@@ -588,63 +602,75 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
struct i2o_device *i2o_dev = priv->i2o_dev;
struct i2o_controller *iop = i2o_dev->controller;
u32 m, *msg;
- u32 flags = 0;
+ u32 *sgl_elem;
/*
* Keep interrupt from changing dev->tbusy from underneath us
* (Do we really need to do this?)
*/
- spin_lock_irqsave(&priv->lock, flags);
- if(test_and_set_bit(0,(void*)&dev->tbusy) != 0) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return 1;
- }
+ if (test_and_set_bit(0,(void*)&dev->tbusy) != 0) {
+ return 1;
+ }
- m = I2O_POST_READ32(iop);
- if (m == 0xFFFFFFFF) {
- spin_unlock_irqrestore(&priv->lock, flags);
- dev_kfree_skb(skb);
- return -ETIMEDOUT;
- }
- msg = (u32 *)(iop->mem_offset + m);
+ priv->tx_count++;
+ priv->tx_out++;
-#if 0
- __raw_writel(SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4,&msg[0]);
- __raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid, &msg[1]);
- __raw_writel(priv->unit << 16 | lan_context, &msg[2]); // InitiatorContext
- __raw_writel(1 << 4, &msg[3]); // TransmitControlWord
- __raw_writel(0xD5000000 | skb->len, &msg[4]); // MAC hdr included
- __raw_writel((u32)skb, &msg[5]); // TransactionContext
- __raw_writel(virt_to_bus(skb->data),&msg[6]);
-#endif
+ if (priv->tx_count == 1) {
+ dprintk("%s: New message frame\n", dev->name);
- msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4;
- msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
- msg[2] = priv->unit << 16 | lan_context; // IntiatorContext
- msg[3] = 1 << 4; // TransmitControlWord
+ m = I2O_POST_READ32(iop);
+ if (m == 0xFFFFFFFF) {
+ dev_kfree_skb(skb);
+ return -ETIMEDOUT;
+ }
+ msg = (u32 *)(iop->mem_offset + m);
+ priv->m = m;
+
+ __raw_writel(SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4, msg);
+ __raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid, msg+1);
+ __raw_writel(priv->unit << 16 | lan_context, msg+2); // InitiatorContext
+ __raw_writel(1 << 4, msg+3); // TransmitControlWord
+ __raw_writel(0xD5000000 | skb->len, msg+4); // MAC hdr included
+ __raw_writel((u32)skb, msg+5); // TransactionContext
+ __raw_writel(virt_to_bus(skb->data), msg+6);
+
+ i2o_post_send_task.data = (void *)dev;
+ queue_task(&i2o_post_send_task, &tq_scheduler);
- // create a simple SGL, see fig. 3-26
- // D5 = 1101 0101 = LE eob 0 1 LA dir bc1 bc0
+ if (priv->tx_out < priv->tx_max)
+ clear_bit(0, (void *)&dev->tbusy);
- msg[4] = 0xD5000000 | skb->len; // MAC hdr included
- msg[5] = (u32)skb; // TransactionContext
- msg[6] = virt_to_bus(skb->data);
+ return 0;
+ }
+
+ /* Else add new SGL element to the previous message frame */
+
+ dprintk("%s: Adding packet %d to msg frame\n", dev->name, priv->tx_count);
- i2o_post_message(iop,m);
+ msg = (u32 *)(iop->mem_offset + priv->m);
+ sgl_elem = &msg[priv->tx_count * 3 + 1];
+
+ __raw_writel(I2O_MESSAGE_SIZE((__raw_readl(msg)>>16) + 3) | 1<<12 | SGL_OFFSET_4, msg);
+ __raw_writel(__raw_readl(sgl_elem-3) & 0x7FFFFFFF, sgl_elem-3); /* clear LE flag */
+ __raw_writel(0xD5000000 | skb->len, sgl_elem);
+ __raw_writel((u32)skb, sgl_elem+1);
+ __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
+
+ if (priv->tx_count == priv->sgl_max) { /* frame full, send now */
+// i2o_lan_batch_send(dev);
+ i2o_post_message(iop, priv->m);
+ dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);
+ priv->tx_count = 0;
+ }
- // Check to see if HDM queue is full..if so...stay busy
- if(++priv->tx_count < priv->max_tx)
+ if (priv->tx_out < priv->tx_max)
clear_bit(0, (void *)&dev->tbusy);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- dprintk(KERN_INFO "%s: Packet (%d bytes) sent to network.\n",
- dev->name, skb->len);
-
return 0;
}
+
static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -653,7 +679,7 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
u64 val64[16];
u64 supported_group[4] = { 0, 0, 0, 0 };
- if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, val64,
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, val64,
sizeof(val64)) < 0)
printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name);
else {
@@ -703,8 +729,7 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
if (supported_stats != 0) {
if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1,
val64, sizeof(val64)) < 0)
-;
-// printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
+ printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
else {
dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name);
if (supported_stats & 0x1)
@@ -713,7 +738,6 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
priv->stats.tx_heartbeat_errors = val64[2];
}
}
-
}
#ifdef CONFIG_TR
@@ -724,7 +748,7 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
else {
struct tr_statistics *stats =
(struct tr_statistics *)&priv->stats;
-// dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name);
+ dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name);
stats->line_errors = val64[0];
stats->internal_errors = val64[7];
@@ -747,7 +771,7 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name);
else {
-// dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name);
+ dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name);
priv->stats.smt_cf_state = val64[0];
memcpy(priv->stats.mac_upstream_nbr, &val64[1], FDDI_K_ALEN);
memcpy(priv->stats.mac_downstream_nbr, &val64[2], FDDI_K_ALEN);
@@ -782,7 +806,7 @@ static void i2o_lan_set_mc_list(struct net_device *dev)
if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1,
&mc_addr_group, sizeof(mc_addr_group)) < 0 ) {
- printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name);
+ printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name);
return;
}
@@ -863,7 +887,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
struct net_device *dev = NULL;
struct i2o_lan_local *priv = NULL;
u8 hw_addr[8];
- u32 max_tx = 0;
+ u32 tx_max = 0;
unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
void (*unregister_dev)(struct net_device *dev);
@@ -934,6 +958,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
priv->i2o_dev = i2o_dev;
priv->type_trans = type_trans;
priv->bucket_count = 0;
+ priv->sgl_max = (i2o_dev->controller->inbound_size - 16) / 12;
unit++;
i2o_landevs[unit] = dev;
@@ -956,7 +981,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
memcpy(dev->dev_addr, hw_addr, 6);
if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
- 0x0007, 2, &max_tx, sizeof(max_tx)) < 0)
+ 0x0007, 2, &tx_max, sizeof(tx_max)) < 0)
{
printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
unit--;
@@ -964,11 +989,11 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
kfree(dev);
return NULL;
}
- dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, max_tx);
- priv->max_tx = max_tx;
- priv->tx_count = 0;
-
- priv->lock = SPIN_LOCK_UNLOCKED;
+ dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max);
+ priv->tx_max = tx_max;
+ priv->tx_out = 0;
+ priv->tx_count = 0;
+ priv->lock = SPIN_LOCK_UNLOCKED;
dev->open = i2o_lan_open;
dev->stop = i2o_lan_close;
@@ -989,7 +1014,12 @@ int __init i2o_lan_init(void)
int i;
printk(KERN_INFO "Linux I2O LAN OSM (c) 1999 University of Helsinki.\n");
-
+
+ if (bucketpost > I2O_BUCKET_COUNT)
+ bucketpost = I2O_BUCKET_COUNT;
+ if (bucketthresh > bucketpost)
+ bucketthresh = bucketpost;
+
if (i2o_install_handler(&i2o_lan_handler) < 0) {
printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n");
return -EINVAL;
@@ -1085,7 +1115,7 @@ EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Univ of Helsinki, CS Department");
MODULE_DESCRIPTION("I2O Lan OSM");
-MODULE_PARM(bucketpost, "i"); // Number of buckets to post
+MODULE_PARM(bucketpost, "i"); // Total number of buckets to post
MODULE_PARM(bucketthresh, "i"); // Bucket post threshold
MODULE_PARM(rx_copybreak, "i");
diff --git a/drivers/i2o/i2o_pci.c b/drivers/i2o/i2o_pci.c
index d44f801df..c57bd390d 100644
--- a/drivers/i2o/i2o_pci.c
+++ b/drivers/i2o/i2o_pci.c
@@ -229,9 +229,8 @@ int __init i2o_pci_scan(void)
int count=0;
printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
-
- for(dev=pci_devices; dev!=NULL; dev=dev->next)
- {
+
+ pci_for_each_dev(dev) {
if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O)
continue;
if((dev->class&0xFF)>1)