diff options
Diffstat (limited to 'drivers/i2o/i2o_core.c')
-rw-r--r-- | drivers/i2o/i2o_core.c | 630 |
1 files changed, 229 insertions, 401 deletions
diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c index ff3e2405f..6428af9fc 100644 --- a/drivers/i2o/i2o_core.c +++ b/drivers/i2o/i2o_core.c @@ -18,7 +18,6 @@ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> * Deepak Saxena <deepak@plexity.net> - * */ #include <linux/config.h> @@ -35,7 +34,6 @@ #include <linux/bitops.h> #include <linux/wait.h> -#include <linux/delay.h> #include <linux/timer.h> #include <asm/io.h> @@ -53,19 +51,22 @@ static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES]; static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS]; +struct i2o_controller *i2o_controller_chain; int i2o_num_controllers = 0; static int core_context = 0; -extern int i2o_online_controller(struct i2o_controller *c); +static int i2o_activate_controller(struct i2o_controller *iop); +static int i2o_online_controller(struct i2o_controller *c); static int i2o_init_outbound_q(struct i2o_controller *c); static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *, struct i2o_message *); static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *); static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *); -static void i2o_dump_message(u32 *msg); +void i2o_dump_message(u32 *msg); static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32); +static int i2o_reset_controller(struct i2o_controller *); static int i2o_lct_get(struct i2o_controller *); static int i2o_hrt_get(struct i2o_controller *); @@ -176,9 +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) - i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg); + i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg); status = -(msg[4] & 0xFFFF); } else @@ -233,7 +232,6 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d) d->next=c->devices; c->devices=d; *d->dev_name = 0; - d->owner = NULL; for(i = 0; i < I2O_MAX_MANAGERS; i++) d->managers[i] = NULL; @@ -307,12 +305,7 @@ int i2o_install_controller(struct i2o_controller *c) c->next=i2o_controller_chain; i2o_controller_chain=c; c->unit = i; - c->page_frame = NULL; - c->hrt = NULL; - c->lct = NULL; - c->status_block = NULL; -// printk(KERN_INFO "lct @ %p hrt @ %p status @ %p", -// c->lct, c->hrt, c->status_block); + sprintf(c->name, "i2o/iop%d", i); i2o_num_controllers++; spin_unlock(&i2o_configuration_lock); @@ -328,15 +321,13 @@ int i2o_delete_controller(struct i2o_controller *c) { struct i2o_controller **p; int users; - -#ifdef DRIVERDEBUG - printk(KERN_INFO "Deleting controller iop%d\n", c->unit); -#endif + char name[16]; spin_lock(&i2o_configuration_lock); if((users=atomic_read(&c->users))) { - printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit); + printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users); + c->bus_disable(c); spin_unlock(&i2o_configuration_lock); return -EBUSY; } @@ -345,6 +336,7 @@ int i2o_delete_controller(struct i2o_controller *c) if(__i2o_delete_device(c->devices)<0) { /* Shouldnt happen */ + c->bus_disable(c); spin_unlock(&i2o_configuration_lock); return -EBUSY; } @@ -356,8 +348,8 @@ int i2o_delete_controller(struct i2o_controller *c) { if(*p==c) { - /* Ask the IOP to switch to HOLD state */ - i2o_clear_controller(c); + /* Ask the IOP to switch into RESET state */ + i2o_reset_controller(c); /* Release IRQ */ c->destructor(c); @@ -365,8 +357,6 @@ int i2o_delete_controller(struct i2o_controller *c) *p=c->next; spin_unlock(&i2o_configuration_lock); -// printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n", -// c->hrt, c->lct, c->page_frame, c->status_block); if(c->page_frame) kfree(c->page_frame); if(c->hrt) @@ -376,14 +366,13 @@ int i2o_delete_controller(struct i2o_controller *c) if(c->status_block) kfree(c->status_block); - kfree(c); - i2o_controllers[c->unit]=NULL; - + memcpy(name, c->name, strlen(c->name)+1); + kfree(c); i2o_num_controllers--; -#ifdef DRIVERDEBUG - printk(KERN_INFO "iop deleted\n"); -#endif + + dprintk((KERN_INFO "%s: Deleted from controller chain.\n", name)); + return 0; } p=&((*p)->next); @@ -540,17 +529,20 @@ void i2o_run_queue(struct i2o_controller *c) u32 mv; #ifdef DEBUG_IRQ - printk(KERN_INFO "iop%d interrupt\n", c->unit); + printk(KERN_INFO "%s: interrupt\n", c->name); #endif + /* Sometimes we get here, but a message can't be read. Why? */ + if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF) + mv=I2O_REPLY_READ32(c); - while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF) + while (mv!=0xFFFFFFFF) { struct i2o_handler *i; m=(struct i2o_message *)bus_to_virt(mv); /* * Temporary Debugging */ - if(((m->function_addr>>24)&0xFF)==0x15) + if(m->function==0x15) printk("UTFR!\n"); #ifdef DEBUG_IRQ @@ -562,12 +554,13 @@ void i2o_run_queue(struct i2o_controller *c) i->reply(i,c,m); else { - printk("Spurious reply to handler %d\n", + printk("i2o: Spurious reply to handler %d\n", m->initiator_context&(MAX_I2O_MODULES-1)); i2o_dump_message((u32*)m); } i2o_flush_reply(c,mv); mb(); + mv=I2O_REPLY_READ32(c); } } @@ -699,7 +692,6 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit) } if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)>=0) { - buf[16]=0; printk(" Device: %s", buf); } @@ -707,7 +699,7 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit) if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0) { buf[16]=0; - printk(KERN_INFO "Description: %s\n", buf); + printk("Description: %s", buf); } #endif if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8)>=0) @@ -831,25 +823,17 @@ static int i2o_parse_lct(struct i2o_controller *c) char str[22]; i2o_lct *lct = c->lct; - max = lct->table_size; + if (lct == NULL) { + printk(KERN_ERR "%s: LCT is empty???\n",c->name); + return -1; + } + max = lct->table_size; max -= 3; max /= 9; - if(max==0) - { - printk(KERN_ERR "%s: LCT is empty????\n",c->name); - return -1; - } - printk(KERN_INFO "%s: LCT has %d entries.\n", c->name,max); - if(max > 128) - { - printk(KERN_INFO "%s: LCT was truncated.\n",c->name); - max=128; - } - if(lct->iop_flags&(1<<0)) printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name); @@ -870,7 +854,7 @@ static int i2o_parse_lct(struct i2o_controller *c) d->flags = 0; tid = d->lct_data->tid; - printk(KERN_INFO "Task ID %d.\n", tid); + printk(KERN_INFO "Target ID %d.\n", tid); i2o_report_controller_unit(c, tid); @@ -880,10 +864,10 @@ static int i2o_parse_lct(struct i2o_controller *c) sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id)); printk("%s", str); - - printk(" Subclass: 0x%04X Flags: ", + + printk(" Subclass: 0x%04X Flags: ", d->lct_data->sub_class); - + if(d->lct_data->device_flags&(1<<0)) printk("C"); // ConfigDialog requested if(d->lct_data->device_flags&(1<<1)) @@ -899,37 +883,44 @@ static int i2o_parse_lct(struct i2o_controller *c) } -/* Quiesce IOP */ +/* + * Quiesce IOP. Causes IOP to make external operation quiescend. + * Internal operation of the IOP continues normally. + */ int i2o_quiesce_controller(struct i2o_controller *c) { u32 msg[4]; int ret; - if ((c->status_block->iop_state != ADAPTER_STATE_READY) & - (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)) + /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ + + 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; + return 0; } msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID; - /* msg[2] and msg[3] filled in i2o_post_wait */ + /* msg[2] filled in i2o_post_wait */ + msg[3]=0; /* Long timeout needed for quiesce if lots of devices */ if ((ret = i2o_post_wait(c, msg, sizeof(msg), 120))) - printk(KERN_INFO "%s: Unable to quiesce.\n", c->name); + printk(KERN_INFO "%s: Unable to quiesce (status=%#10x).\n", + c->name, ret); else dprintk((KERN_INFO "%s: Quiesced.\n", c->name)); + i2o_status_get(c); // Reread the Status Block + return ret; } -/* Enable IOP */ +/* + * Enable IOP. Allows the IOP to resume external operations. + */ int i2o_enable_controller(struct i2o_controller *c) { u32 msg[4]; @@ -937,44 +928,80 @@ int i2o_enable_controller(struct i2o_controller *c) msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID; - /* msg[2] and msg[3] filled in i2o_post_wait */ + /* msg[2] filled in i2o_post_wait */ /* How long of a timeout do we need? */ if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240))) - printk(KERN_ERR "%s: Could not enable, %d\n", c->name, ret); + printk(KERN_ERR "%s: Could not enable (status=%#10x).\n", + c->name, ret); + else + dprintk((KERN_INFO "%s: Enabled.\n", c->name)); + + i2o_status_get(c); return ret; } -/* Reset an IOP, but keep message queues alive */ +/* + * Clear an IOP to HOLD state, ie. terminate external operations, clear all + * input queues and prepare for a system restart. IOP's internal operation + * continues normally and the outbound queue is alive. + * IOP is not expected to rebuild its LCT. + */ int i2o_clear_controller(struct i2o_controller *c) { + struct i2o_controller *iop; u32 msg[4]; int ret; + /* Quiesce all IOPs first */ + + for (iop = i2o_controller_chain; iop; iop = iop->next) + i2o_quiesce_controller(iop); + msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID; - /* msg[2] and msg[3] filled in i2o_post_wait */ + /* msg[2] filled in i2o_post_wait */ + msg[3]=0; if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30))) - printk(KERN_INFO "%s: Unable to clear, %#10x\n", + printk(KERN_INFO "%s: Unable to clear (status=%#10x).\n", c->name, ret); + else + dprintk((KERN_INFO "%s: Cleared.\n",c->name)); - i2o_status_get(c); // Reread the Status Block + i2o_status_get(c); + + /* Enable other IOPs */ + + for (iop = i2o_controller_chain; iop; iop = iop->next) + if (iop != c) + i2o_enable_controller(iop); return ret; } -/* Reset the IOP to sane state */ +/* + * Reset the IOP into INIT state and wait until IOP gets into RESET state. + * Terminate all external operations, clear IOP's inbound and outbound + * queues, terminate all DDMs, and reload the IOP's operating environment + * and all local DDMs. IOP rebuilds its LCT. + */ static int i2o_reset_controller(struct i2o_controller *c) { + struct i2o_controller *iop; u32 m; u8 *status; u32 *msg; long time; + /* Quiesce all IOPs first */ + + for (iop = i2o_controller_chain; iop; iop = iop->next) + i2o_quiesce_controller(iop); + m=i2o_wait_message(c, "AdapterReset"); if(m==0xFFFFFFFF) return -ETIMEDOUT; @@ -1013,16 +1040,14 @@ static int i2o_reset_controller(struct i2o_controller *c) barrier(); } - if (status[0]==0x02) - printk(KERN_WARNING "%s: Reset rejected.\n",c->name); - else + if (status[0]==0x01) { /* * Once the reset is sent, the IOP goes into the INIT state - * which is inditerminate. We need to wait until the IOP + * which is indeterminate. 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 + * available. If we can't read one in the given amount of * time, we assume the IOP could not reboot properly. */ @@ -1043,9 +1068,26 @@ static int i2o_reset_controller(struct i2o_controller *c) } i2o_flush_reply(c,m); - printk(KERN_INFO "%s: Reset completed.\n", c->name); + + dprintk((KERN_INFO "%s: Reset completed.\n", c->name)); } + /* If IopReset was rejected or didn't perform reset, try IopClear */ + + i2o_status_get(c); + if (status[0] == 0x02 || c->status_block->iop_state != ADAPTER_STATE_RESET) + { + printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name); + i2o_clear_controller(c); + + } + + /* Enable other IOPs */ + + for (iop = i2o_controller_chain; iop; iop = iop->next) + if (iop != c) + i2o_enable_controller(iop); + kfree(status); return 0; } @@ -1157,13 +1199,14 @@ int i2o_hrt_get(struct i2o_controller *c) 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[2] filled in i2o_post_wait */ + msg[3]= 0; 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); + printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", + c->name, ret); return ret; } @@ -1193,6 +1236,8 @@ static int i2o_systab_send(struct i2o_controller *iop) iop->status->current_io_base; iop->status->current_io_size; #endif + +/* FIXME */ 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 */ @@ -1200,7 +1245,8 @@ static int i2o_systab_send(struct i2o_controller *iop) 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[2] filled in i2o_post_wait */ + msg[3] = 0; msg[4] = (0<<16) | ((iop->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */ msg[5] = 0; /* Segment 0 */ @@ -1217,8 +1263,10 @@ static int i2o_systab_send(struct i2o_controller *iop) msg[11] = virt_to_phys(privio); if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120))) - printk(KERN_INFO "%s: Unable to set SysTab, %d\n", - iop->name, ret); + printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", + iop->name, ret); + else + dprintk((KERN_INFO "%s: SysTab set.\n", iop->name)); return ret; @@ -1229,292 +1277,114 @@ static int i2o_systab_send(struct i2o_controller *iop) */ static void __init i2o_sys_init() { - struct i2o_controller *iop, *niop; - int ret; - u32 m; + struct i2o_controller *iop, *niop = NULL; printk(KERN_INFO "Activating I2O controllers\n"); printk(KERN_INFO "This may take a few minutes if there are many devices\n"); - /* Get the status for each IOP */ - for(iop = i2o_controller_chain; iop; iop = niop) - { - niop = iop->next; -#ifdef DRIVERDEBUG - printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit); -#endif - if(i2o_status_get(iop)<0) - { - printk("Unable to obtain status of IOP, attempting a reset.\n"); - i2o_reset_controller(iop); - if(i2o_status_get(iop)<0) - { - printk("IOP not responding.\n"); - i2o_delete_controller(iop); - continue; - } - } - - if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) - { - printk(KERN_CRIT "i2o: iop%d has hardware fault\n", - iop->unit); - i2o_delete_controller(iop); - continue; - } + /* In INIT state, Activate IOPs */ - if(iop->status_block->iop_state == ADAPTER_STATE_HOLD || - iop->status_block->iop_state == ADAPTER_STATE_READY || - iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || - iop->status_block->iop_state == ADAPTER_STATE_FAILED) - { - int msg[256]; - -#ifdef DRIVERDEBUG - printk(KERN_INFO "iop%d already running...trying to reboot\n", - iop->unit); -#endif - i2o_init_outbound_q(iop); - I2O_REPLY_WRITE32(iop,virt_to_phys(msg)); - i2o_quiesce_controller(iop); - i2o_reset_controller(iop); - if(i2o_status_get(iop) || - iop->status_block->iop_state != ADAPTER_STATE_RESET) - { - printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit); - i2o_delete_controller(iop); - continue; - } - } - } - - /* - * Now init the outbound queue for each one. - */ - for(iop = i2o_controller_chain; iop; iop = niop) - { - int i; - + for (iop = i2o_controller_chain; iop; iop = niop) { niop = iop->next; - - if((ret=i2o_init_outbound_q(iop))) - { - printk(KERN_ERR - "IOP%d initialization failed: Could not initialize outbound q\n", - iop->unit); - i2o_delete_controller(iop); - continue; - } - iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL); - - if(iop->page_frame==NULL) - { - printk(KERN_CRIT "iop%d init failed: no memory for message page.\n", - iop->unit); - i2o_delete_controller(iop); - continue; - } - - m=virt_to_phys(iop->page_frame); - - for(i=0; i< NMBR_MSG_FRAMES; i++) - { - I2O_REPLY_WRITE32(iop,m); - mb(); - m+=MSG_FRAME_SIZE; - mb(); - } + i2o_activate_controller(iop); } - /* - * OK..parse the HRT - */ - for(iop = i2o_controller_chain; iop; iop = niop) - { - niop = iop->next; - if(i2o_hrt_get(iop)) - { - printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit); - i2o_delete_controller(iop); - continue; - } - if(i2o_parse_hrt(iop)) - { - printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit); - i2o_delete_controller(iop); - continue; - } - } + /* Active IOPs in HOLD state */ + +rebuild_sys_tab: + if (i2o_controller_chain == NULL) + return; /* - * 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()) - { - printk(KERN_CRIT "I2O: Error building system table. Aborting!\n"); + if (i2o_build_sys_table() < 0) { i2o_sys_shutdown(); return; } - for(iop = i2o_controller_chain; iop; iop = niop) -#ifdef DRIVERDEBUG - { - niop = iop->next; - printk(KERN_INFO "Sending system table to iop%d\n", iop->unit); -#endif - if(i2o_systab_send(iop)) - { - printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit); - i2o_delete_controller(iop); - continue; - } -#ifdef DRIVERDEBUG - } -#endif - - /* - * Enable - */ - for(iop = i2o_controller_chain; iop; iop = niop) - { - niop = iop->next; -#ifdef DRIVERDEBUG - printk(KERN_INFO "Enabling iop%d\n", iop->unit); -#endif - if(i2o_enable_controller(iop)) - { - printk(KERN_ERR "Could not enable iop%d\n", iop->unit); - i2o_delete_controller(iop); - continue; - } - } - - /* - * OK..one last thing and we're ready to go! - */ - for(iop = i2o_controller_chain; iop; iop = niop) - { + /* If IOP don't get online, we need to rebuild the System table */ + for (iop = i2o_controller_chain; iop; iop = niop) { niop = iop->next; -#ifdef DRIVERDEBUG - printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit); -#endif - if(i2o_lct_get(iop)) - { - printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit); - i2o_delete_controller(iop); - continue; - } - else - i2o_parse_lct(iop); + if (i2o_online_controller(iop) < 0) + goto rebuild_sys_tab; } + + /* Active IOPs now in OPERATIONAL state */ } /* * Shutdown I2O system - * - * 1. Quiesce all controllers - * 2. Delete all controllers */ static void i2o_sys_shutdown(void) { struct i2o_controller *iop, *niop; - for (iop = i2o_controller_chain; iop ; iop=iop->next) { - i2o_quiesce_controller(iop); - i2o_status_get(iop); // Update IOP status block - } + /* Delete all IOPs from the controller chain */ + /* that will reset all IOPs too */ for (iop = i2o_controller_chain; iop; iop = niop) { niop = iop->next; - if (i2o_delete_controller(iop)) - iop->bus_disable(iop); + i2o_delete_controller(iop); } } /* - * Bring an I2O controller into HOLD state. See the 1.5 - * spec. Basically we go - * - * Wait for the message queue to initialise. - * If it didnt -> controller is dead - * - * Send a get status using the message queue - * Poll for a reply block 88 bytes long - * - * Send an initialise outbound queue - * Poll for a reply - * - * Post our blank messages to the queue FIFO - * - * Send GetHRT, Parse it + * Bring an I2O controller into HOLD state. See the spec. */ -int i2o_activate_controller(struct i2o_controller *c) +int i2o_activate_controller(struct i2o_controller *iop) { - return 0; -#ifdef I2O_HOTPLUG_SUPPORT - u32 m; - int i; - int ret; - - 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; + /* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */ + /* In READY state, Get status */ + + if (i2o_status_get(iop) < 0) { + printk("Unable to obtain status of IOP, attempting a reset.\n"); + i2o_reset_controller(iop); + if (i2o_status_get(iop) < 0) { + printk("IOP not responding.\n"); + i2o_delete_controller(iop); + return -1; + } + } - /* not likely to be seen */ - if(c->status_block->iop_state == ADAPTER_STATE_FAULTED) - { - printk(KERN_CRIT "i2o: iop%d has hardware fault\n", - c->unit); + if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) { + printk(KERN_CRIT "%s: hardware fault\n", iop->name); + i2o_delete_controller(iop); return -1; } - /* - * If the board is running, reset it - we have no idea - * what kind of a mess the previous owner left it in. - * We need to feed the IOP a single outbound message - * so that it can reply back to the ExecSysQuiesce. - */ - if(c->status_block->iop_state == ADAPTER_STATE_HOLD || - c->status_block->iop_state == ADAPTER_STATE_READY || - c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || - c->status_block->iop_state == ADAPTER_STATE_FAILED) +// if (iop->status_block->iop_state == ADAPTER_STATE_HOLD || + if (iop->status_block->iop_state == ADAPTER_STATE_READY || + iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || + iop->status_block->iop_state == ADAPTER_STATE_FAILED) { - int msg[256]; - printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit); + dprintk((KERN_INFO "%s: already running...trying to reset\n", + iop->name)); + i2o_reset_controller(iop); - if(i2o_init_outbound_q(c)); - I2O_REPLY_WRITE32(c,virt_to_phys(msg)); - - if((ret=i2o_reset_controller(c))) - return ret; - - if((ret=i2o_status_get(c))) - return ret; + if (i2o_status_get(iop) < 0 || + iop->status_block->iop_state != ADAPTER_STATE_RESET) + { + printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name); + i2o_delete_controller(iop); + return -1; + } } - if ((ret=i2o_init_outbound_q(c))){ - return ret; + if (i2o_init_outbound_q(iop) < 0) { + i2o_delete_controller(iop); + return -1; } - /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */ - - /* - * 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. - */ - - if ((ret=i2o_hrt_get(c))) - return ret; + /* In HOLD state */ + + if (i2o_hrt_get(iop) < 0) { + i2o_delete_controller(iop); + return -1; + } - return i2o_online_controller(c); -#endif + return 0; } /* @@ -1533,7 +1403,6 @@ int i2o_init_outbound_q(struct i2o_controller *c) 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", @@ -1568,6 +1437,8 @@ int i2o_init_outbound_q(struct i2o_controller *c) barrier(); } + /* Alloc space for IOP's outbound queue message frames */ + 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", @@ -1577,6 +1448,8 @@ int i2o_init_outbound_q(struct i2o_controller *c) } m=virt_to_phys(c->page_frame); + /* Post frames */ + for(i=0; i< NMBR_MSG_FRAMES; i++) { I2O_REPLY_WRITE32(c,m); mb(); @@ -1608,15 +1481,16 @@ int i2o_lct_get(struct i2o_controller *c) 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[2] filled in i2o_post_wait */ + msg[3] = 0; 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); + printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", + c->name, ret); return ret; } @@ -1627,83 +1501,39 @@ int i2o_lct_get(struct i2o_controller *c) } } while (c->lct == NULL); + if ((ret=i2o_parse_lct(c)) < 0) + return ret; + return 0; } /* - * Bring a controller online. Needs completing for multiple controllers + * Bring a controller online into OPERATIONAL state. */ -int i2o_online_controller(struct i2o_controller *c) +int i2o_online_controller(struct i2o_controller *iop) { - return 0; -#ifdef I2O_HOTPLUG_SUPPORT - u32 msg[10]; - u32 privmem[2]; - u32 privio[2]; - int ret; + if (i2o_systab_send(iop) < 0) { + i2o_delete_controller(iop); + return -1; + } - /* - * 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(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; + /* In READY state */ - /* - * Grab the LCT, see what is attached - */ - ret=i2o_lct_get(c); - if(ret) - { - /* Maybe we should do also do something else */ - return ret; - } + if (i2o_enable_controller(iop) < 0) { + i2o_delete_controller(iop); + return -1; + } - ret=i2o_parse_lct(c); - if(ret) - return ret; + /* In OPERATIONAL state */ - return 0; -#endif + if (i2o_lct_get(iop) < 0){ + i2o_delete_controller(iop); + return -1; + } + + return 0; } static int i2o_build_sys_table(void) @@ -1923,7 +1753,8 @@ int i2o_event_ack(struct i2o_controller *c, int tid, int context, 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[2] = context; + msg[3] = 0; msg[4] = evt_indicator; memcpy(msg+5, evt_data, evt_data_len); @@ -1947,9 +1778,10 @@ static int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int o else msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid; - /* msg[2] and msg[3] filled in i2o_post_wait */ + /* msg[2] filled in i2o_post_wait */ + msg[3] = 0; msg[4] = type; - + return i2o_post_wait(c, msg, sizeof(msg), 2); } @@ -1970,6 +1802,8 @@ int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid, msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; msg[1] = cmd << 24 | HOST_TID << 12 | tid; + /* msg[2] filled in i2o_post_wait */ + msg[3] = 0; msg[4] = 0; msg[5] = 0x54000000 | oplen; /* OperationBlock */ msg[6] = virt_to_bus(opblk); @@ -2515,7 +2349,7 @@ void i2o_report_status(const char *severity, const char *module, u32 *msg) } /* Used to dump a message to syslog during debugging */ -static void i2o_dump_message(u32 *msg) +void i2o_dump_message(u32 *msg) { #ifdef DRIVERDEBUG int i; @@ -2531,10 +2365,7 @@ static void i2o_dump_message(u32 *msg) EXPORT_SYMBOL(i2o_install_handler); EXPORT_SYMBOL(i2o_remove_handler); -EXPORT_SYMBOL(i2o_install_device); -EXPORT_SYMBOL(i2o_delete_device); -EXPORT_SYMBOL(i2o_quiesce_controller); -EXPORT_SYMBOL(i2o_clear_controller); + EXPORT_SYMBOL(i2o_install_controller); EXPORT_SYMBOL(i2o_delete_controller); EXPORT_SYMBOL(i2o_unlock_controller); @@ -2547,9 +2378,7 @@ EXPORT_SYMBOL(i2o_event_ack); EXPORT_SYMBOL(i2o_claim_device); EXPORT_SYMBOL(i2o_release_device); EXPORT_SYMBOL(i2o_run_queue); -EXPORT_SYMBOL(i2o_report_controller_unit); EXPORT_SYMBOL(i2o_activate_controller); -EXPORT_SYMBOL(i2o_online_controller); EXPORT_SYMBOL(i2o_get_class_name); EXPORT_SYMBOL(i2o_status_get); @@ -2558,7 +2387,6 @@ EXPORT_SYMBOL(i2o_set_scalar); EXPORT_SYMBOL(i2o_query_table); EXPORT_SYMBOL(i2o_clear_table); EXPORT_SYMBOL(i2o_row_add_table); -EXPORT_SYMBOL(i2o_row_delete_table); EXPORT_SYMBOL(i2o_post_this); EXPORT_SYMBOL(i2o_post_wait); @@ -2632,7 +2460,7 @@ int __init i2o_init(void) #endif if(i2o_num_controllers) - i2o_init(); + i2o_sys_init(); i2o_config_init(); #ifdef CONFIG_I2O_BLOCK |