diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
commit | 99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch) | |
tree | 3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/i2o | |
parent | e73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff) |
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/i2o')
-rw-r--r-- | drivers/i2o/i2o_block.c | 26 | ||||
-rw-r--r-- | drivers/i2o/i2o_core.c | 1022 | ||||
-rw-r--r-- | drivers/i2o/i2o_lan.c | 406 | ||||
-rw-r--r-- | drivers/i2o/i2o_pci.c | 5 |
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) |