X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmessage%2Ffusion%2Fmptbase.c;h=b2d7333dc58d501dfefee0a2ba8d14dd564cd560;hb=1be35e94e1da3669db492995cd2c8b1a37016b11;hp=75c07f89e47e60f4d36eb7836ad4dff93042f2b2;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 75c07f89e..b2d7333dc 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -150,8 +150,9 @@ int mpt_ASCQ_TableSz; /* * Private data... */ - /* Adapter link list */ -LIST_HEAD(ioc_list); + /* Adapter lookup table */ + MPT_ADAPTER *mpt_adapters[MPT_MAX_ADAPTERS]; +static MPT_ADAPTER_TRACKER MptAdapters; /* Callback lookup table */ static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS]; /* Protocol driver class lookup table */ @@ -209,6 +210,8 @@ static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); #ifdef CONFIG_PROC_FS +static int procmpt_create(void); +static int procmpt_destroy(void); static int procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data); static int procmpt_version_read(char *buf, char **start, off_t offset, @@ -231,6 +234,31 @@ static void mptbase_shutdown(struct device * ); static int __init fusion_init (void); static void __exit fusion_exit (void); +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * more Private data... + */ +#ifdef CONFIG_PROC_FS +struct _mpt_proc_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} mpt_proc_list[] = { + { "summary", procmpt_summary_read}, + { "version", procmpt_version_read}, +}; +#define MPT_PROC_ENTRIES (sizeof(mpt_proc_list)/sizeof(mpt_proc_list[0])) + +struct _mpt_ioc_proc_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} mpt_ioc_proc_list[] = { + { "info", procmpt_iocinfo_read}, + { "summary", procmpt_summary_read}, +}; +#define MPT_IOC_PROC_ENTRIES (sizeof(mpt_ioc_proc_list)/sizeof(mpt_ioc_proc_list[0])) + +#endif + /**************************************************************************** * Supported hardware */ @@ -254,8 +282,7 @@ static struct pci_device_id mptbase_pci_table[] = { }; MODULE_DEVICE_TABLE(pci, mptbase_pci_table); -#define CHIPREG_READ32(addr) readl_relaxed(addr) -#define CHIPREG_READ32_dmasync(addr) readl(addr) +#define CHIPREG_READ32(addr) readl(addr) #define CHIPREG_WRITE32(addr,val) writel(val, addr) #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr) #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr) @@ -293,6 +320,23 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) ioc = bus_id; +#ifdef MPT_DEBUG_IRQ + /* + * Verify ioc pointer is ok + */ + { + MPT_ADAPTER *iocCmp; + iocCmp = mpt_adapter_find_first(); + while ((ioc != iocCmp) && iocCmp) + iocCmp = mpt_adapter_find_next(iocCmp); + + if (!iocCmp) { + printk(KERN_WARNING "mpt_interrupt: Invalid ioc!\n"); + return IRQ_NONE; + } + } +#endif + /* * Drain the reply FIFO! * @@ -303,7 +347,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) */ while (1) { - if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) + if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) return IRQ_HANDLED; cb_idx = 0; @@ -762,7 +806,8 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; /* call per pci device probe entry point */ - list_for_each_entry(ioc, &ioc_list, list) { + for(ioc = mpt_adapter_find_first(); ioc != NULL; + ioc = mpt_adapter_find_next(ioc)) { if(dd_cbfunc->probe) { error = dd_cbfunc->probe(ioc->pcidev, ioc->pcidev->driver->id_table); @@ -781,19 +826,9 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) void mpt_device_driver_deregister(int cb_idx) { - struct mpt_pci_driver *dd_cbfunc; - MPT_ADAPTER *ioc; - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; - dd_cbfunc = MptDeviceDriverHandlers[cb_idx]; - - list_for_each_entry(ioc, &ioc_list, list) { - if (dd_cbfunc->remove) - dd_cbfunc->remove(ioc->pcidev); - } - MptDeviceDriverHandlers[cb_idx] = NULL; } @@ -809,11 +844,15 @@ mpt_device_driver_deregister(int cb_idx) * or IOC is not active. */ MPT_FRAME_HDR* -mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp) +mpt_get_msg_frame(int handle, int iocid) { MPT_FRAME_HDR *mf; + MPT_ADAPTER *iocp; unsigned long flags; + /* validate handle and ioc identifier */ + iocp = mpt_adapters[iocid]; + #ifdef MFCNT if (!iocp->active) printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n"); @@ -868,39 +907,48 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp) * specific MPT adapter. */ void -mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) +mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf) { - u32 mf_dma_addr; - int req_offset; + MPT_ADAPTER *iocp; + + iocp = mpt_adapters[iocid]; + if (iocp != NULL) { + u32 mf_dma_addr; + int req_offset; - /* ensure values are reset properly! */ - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ - req_offset = (u8 *)mf - (u8 *)iocp->req_frames; + /* ensure values are reset properly! */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ + req_offset = (u8 *)mf - (u8 *)iocp->req_frames; /* u16! */ - mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); + mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; #ifdef MPT_DEBUG_MSG_FRAME - { - u32 *m = mf->u.frame.hwhdr.__hdr; - int ii, n; - - printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", - iocp->name, m); - n = iocp->req_sz/4 - 1; - while (m[n] == 0) - n--; - for (ii=0; ii<=n; ii++) { - if (ii && ((ii%8)==0)) - printk("\n" KERN_INFO " "); - printk(" %08x", le32_to_cpu(m[ii])); + { + u32 *m = mf->u.frame.hwhdr.__hdr; + int ii, n; + + printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", + iocp->name, m); + n = iocp->req_sz/4 - 1; + while (m[n] == 0) + n--; + for (ii=0; ii<=n; ii++) { + if (ii && ((ii%8)==0)) + printk("\n" KERN_INFO " "); + printk(" %08x", le32_to_cpu(m[ii])); + } + printk("\n"); } - printk("\n"); - } #endif - mf_dma_addr = iocp->req_frames_low_dma + req_offset; - CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); + mf_dma_addr = iocp->req_frames_low_dma + req_offset; + CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); + } else { + printk (KERN_ERR + "mpt_put_msg_frame: Invalid iocid=%d\n", iocid); + } + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -914,17 +962,21 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) * FreeQ. */ void -mpt_free_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) +mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf) { + MPT_ADAPTER *iocp; unsigned long flags; - /* Put Request back on FreeQ! */ - spin_lock_irqsave(&iocp->FreeQlock, flags); - Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); + iocp = mpt_adapters[iocid]; + if (iocp != NULL) { + /* Put Request back on FreeQ! */ + spin_lock_irqsave(&iocp->FreeQlock, flags); + Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); #ifdef MFCNT - iocp->mfcnt--; + iocp->mfcnt--; #endif - spin_unlock_irqrestore(&iocp->FreeQlock, flags); + spin_unlock_irqrestore(&iocp->FreeQlock, flags); + } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1010,80 +1062,127 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) * Returns 0 for success, non-zero for failure. */ int -mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req, int sleepFlag) +mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag) { + MPT_ADAPTER *iocp; int r = 0; - u8 *req_as_bytes; - int ii; - /* State is known to be good upon entering - * this function so issue the bus reset - * request. - */ + iocp = mpt_adapters[iocid]; + if (iocp != NULL) { + u8 *req_as_bytes; + int ii; - /* - * Emulate what mpt_put_msg_frame() does /wrt to sanity - * setting cb_idx/req_idx. But ONLY if this request - * is in proper (pre-alloc'd) request buffer range... - */ - ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); - if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) { - MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; - mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; - } + /* State is known to be good upon entering + * this function so issue the bus reset + * request. + */ - /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - CHIPREG_WRITE32(&iocp->chip->Doorbell, - ((MPI_FUNCTION_HANDSHAKE<= 12 && ii >= 0 && ii < iocp->req_depth) { + MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; + } - /* Wait for IOC doorbell int */ - ii = WaitForDoorbellInt(iocp, 5, sleepFlag); - if (ii < 0) - return ii; + /* Make sure there are no doorbells */ + CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - /* Read doorbell and check for active bit */ - if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) - return -5; + CHIPREG_WRITE32(&iocp->chip->Doorbell, + ((MPI_FUNCTION_HANDSHAKE<name, ii)); + /* Wait for IOC doorbell int */ + if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) { + return ii; + } - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); + /* Read doorbell and check for active bit */ + if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) + return -5; - r = WaitForDoorbellAck(iocp, 5, sleepFlag); - if (r < 0) - return -2; + dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", + iocp->name, ii)); - /* Send request via doorbell handshake */ - req_as_bytes = (u8 *) req; - for (ii = 0; ii < reqBytes/4; ii++) { - u32 word; - - word = ((req_as_bytes[(ii*4) + 0] << 0) | - (req_as_bytes[(ii*4) + 1] << 8) | - (req_as_bytes[(ii*4) + 2] << 16) | - (req_as_bytes[(ii*4) + 3] << 24)); - CHIPREG_WRITE32(&iocp->chip->Doorbell, word); - r = WaitForDoorbellAck(iocp, 5, sleepFlag); - if (r < 0) { - r = -3; - break; + CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); + + if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { + return -2; + } + + /* Send request via doorbell handshake */ + req_as_bytes = (u8 *) req; + for (ii = 0; ii < reqBytes/4; ii++) { + u32 word; + + word = ((req_as_bytes[(ii*4) + 0] << 0) | + (req_as_bytes[(ii*4) + 1] << 8) | + (req_as_bytes[(ii*4) + 2] << 16) | + (req_as_bytes[(ii*4) + 3] << 24)); + CHIPREG_WRITE32(&iocp->chip->Doorbell, word); + if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { + r = -3; + break; + } } + + if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) + r = 0; + else + r = -4; + + /* Make sure there are no doorbells */ + CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); } - if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) - r = 0; + return r; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_adapter_find_first - Find first MPT adapter pointer. + * + * Returns first MPT adapter pointer or %NULL if no MPT adapters + * are present. + */ +MPT_ADAPTER * +mpt_adapter_find_first(void) +{ + MPT_ADAPTER *this; + + if (! Q_IS_EMPTY(&MptAdapters)) + this = MptAdapters.head; else - r = -4; + this = NULL; - /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - return r; + return this; } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_adapter_find_next - Find next MPT adapter pointer. + * @prev: Pointer to previous MPT adapter + * + * Returns next MPT adapter pointer or %NULL if there are no more. + */ +MPT_ADAPTER * +mpt_adapter_find_next(MPT_ADAPTER *prev) +{ + MPT_ADAPTER *next; + + if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head)) + next = prev->forw; + else + next = NULL; + + return next; +} + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_verify_adapter - Given a unique IOC identifier, set pointer to @@ -1096,17 +1195,18 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) { - MPT_ADAPTER *ioc; + MPT_ADAPTER *p; - list_for_each_entry(ioc,&ioc_list,list) { - if (ioc->id == iocid) { - *iocpp =ioc; - return iocid; - } - } - *iocpp = NULL; - return -1; + if (iocid >= MPT_MAX_ADAPTERS) + return -1; + + p = mpt_adapters[iocid]; + if (p == NULL) + return -1; + + *iocpp = p; + return iocid; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1140,8 +1240,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) u64 mask = 0xffffffffffffffffULL; u8 revision; u8 pcixcmd; - static int mpt_ids = 0; - struct proc_dir_entry *dent, *ent; if (pci_enable_device(pdev)) return r; @@ -1198,9 +1296,18 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) Q_INIT(&ioc->configQ, Q_ITEM); /* Find lookup slot. */ - INIT_LIST_HEAD(&ioc->list); - ioc->id = mpt_ids++; - + for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) { + if (mpt_adapters[ii] == NULL) { + ioc->id = ii; /* Assign adapter unique id (lookup) */ + break; + } + } + if (ii == MPT_MAX_ADAPTERS) { + printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii); + kfree(ioc); + return -ENFILE; + } + mem_phys = msize = 0; port = psize = 0; for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { @@ -1322,8 +1429,11 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->active = 0; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + /* tack onto tail of our MPT adapter list */ + Q_ADD_TAIL(&MptAdapters, ioc, MPT_ADAPTER); + /* Set lookup ptr. */ - list_add_tail(&ioc->list, &ioc_list); + mpt_adapters[ioc->id] = ioc; ioc->pci_irq = -1; if (pdev->irq) { @@ -1338,7 +1448,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->name, __irq_itoa(pdev->irq)); #endif Q_DEL_ITEM(ioc); - list_del(&ioc->list); + mpt_adapters[ioc->id] = NULL; iounmap(mem); kfree(ioc); return -EBUSY; @@ -1370,7 +1480,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->name, r); Q_DEL_ITEM(ioc); - list_del(&ioc->list); + mpt_adapters[ioc->id] = NULL; free_irq(ioc->pci_irq, ioc); iounmap(mem); kfree(ioc); @@ -1386,23 +1496,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } - /* - * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter. - */ - dent = proc_mkdir(ioc->name, mpt_proc_root_dir); - if (dent) { - ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent); - if (ent) { - ent->read_proc = procmpt_iocinfo_read; - ent->data = ioc; - } - ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent); - if (ent) { - ent->read_proc = procmpt_summary_read; - ent->data = ioc; - } - } - return 0; } @@ -1417,16 +1510,8 @@ static void __devexit mptbase_remove(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - char pname[32]; int ii; - sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); - remove_proc_entry(pname, NULL); - sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name); - remove_proc_entry(pname, NULL); - sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name); - remove_proc_entry(pname, NULL); - /* call per device driver remove entry point */ for(ii=0; iiremove(pdev); } } - + /* Disable interrupts! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); @@ -1446,6 +1531,7 @@ mptbase_remove(struct pci_dev *pdev) CHIPREG_READ32(&ioc->chip->IntStatus); + Q_DEL_ITEM(ioc); mpt_adapter_dispose(ioc); pci_set_drvdata(pdev, NULL); @@ -1683,17 +1769,11 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ioc->alt_ioc->name, r); } - for (ii=0; ii<5; ii++) { - /* Get IOC facts! Allow 1 retry */ - if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) { - dinitprintk((MYIOC_s_INFO_FMT - "ii=%d IocFacts failed r=%x\n", ioc->name, ii, r)); - } else - break; - } + /* Get IOC facts! Allow 1 retry */ + if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) + r = GetIocFacts(ioc, sleepFlag, reason); if (r) { - dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed r=%x\n", ioc->name, r)); ret = -2; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); @@ -1701,13 +1781,11 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (alt_ioc_ready) { if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { - dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed r=%x\n", ioc->name, r)); /* Retry - alt IOC was initialized once */ r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); } if (r) { - dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed r=%x\n", ioc->name, r)); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { @@ -1895,15 +1973,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) { + MPT_ADAPTER *ioc_srch = mpt_adapter_find_first(); unsigned int match_lo, match_hi; - MPT_ADAPTER *ioc_srch; match_lo = pdev->devfn-1; match_hi = pdev->devfn+1; dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n", ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi)); - list_for_each_entry(ioc_srch, &ioc_list, list) { + while (ioc_srch != NULL) { struct pci_dev *_pcidev = ioc_srch->pcidev; if ((_pcidev->device == pdev->device) && @@ -1925,6 +2003,7 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) ioc->alt_ioc = ioc_srch; break; } + ioc_srch = mpt_adapter_find_next(ioc_srch); } } @@ -1939,8 +2018,15 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup) { if (this != NULL) { int sz=0; + u32 state; int ret; + /* Disable the FW */ + state = mpt_GetIocState(this, 1); + if (state == MPI_IOC_STATE_OPERATIONAL) { + SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP); + } + if (this->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n")); @@ -1984,11 +2070,25 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup) } if (freeup && this->cached_fw != NULL) { + int ii = 0; - sz = this->facts.FWImageSize; - pci_free_consistent(this->pcidev, sz, - this->cached_fw, this->cached_fw_dma); + while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) { + sz = this->cached_fw[ii]->size; + pci_free_consistent(this->pcidev, sz, + this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma); + this->cached_fw[ii]->fw = NULL; + this->alloc_total -= sz; + + kfree(this->cached_fw[ii]); + this->cached_fw[ii] = NULL; + this->alloc_total -= sizeof(fw_image_t); + + ii++; + } + + kfree(this->cached_fw); this->cached_fw = NULL; + sz = this->num_fw_frags * sizeof(void *); this->alloc_total -= sz; } @@ -2030,6 +2130,11 @@ mpt_adapter_dispose(MPT_ADAPTER *this) sz_first = this->alloc_total; + if (this->alt_ioc != NULL) { + this->alt_ioc->alt_ioc = NULL; + this->alt_ioc = NULL; + } + mpt_adapter_disable(this, 1); if (this->pci_irq != -1) { @@ -2048,7 +2153,7 @@ mpt_adapter_dispose(MPT_ADAPTER *this) #endif /* Zap the adapter lookup ptr! */ - list_del(&this->list); + mpt_adapters[this->id] = NULL; sz_last = this->alloc_total; dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", @@ -2145,14 +2250,13 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) if ((int)ioc->chip_type <= (int)FC929) return 0; else { - return 0; /* Workaround from broken 1030 FW. * Force a diagnostic reset if fails. */ -/* if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) + if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) return 0; else - statefault = 4; */ + statefault = 4; } } @@ -2171,7 +2275,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Hmmm... Did it get left operational? */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { - dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", + dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. @@ -2315,7 +2419,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name)); + dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name)); /* No non-zero fields in the get_facts request are greater than * 1 byte in size, so we can just fire it off as is. @@ -2415,10 +2519,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return r; } } else { - printk(MYIOC_s_ERR_FMT - "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n", - ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, - RequestFrameSize)/sizeof(u32))); + printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n", + ioc->name); return -66; } @@ -2563,7 +2665,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; - dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", + dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, @@ -2575,9 +2677,6 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) * since we don't even look at it's contents. */ - dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n", - ioc->name, &ioc_init)); - if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) return r; @@ -2672,14 +2771,86 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) * Outputs: frags - number of fragments needed * Return NULL if failed. */ -void -mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) +void * +mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz) { + fw_image_t **cached_fw; + u8 *mem; + dma_addr_t fw_dma; + int alloc_total = 0; + int bytes_left, bytes, num_frags; + int sz, ii; + /* cached_fw */ + sz = ioc->num_fw_frags * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) + return NULL; + + memset(mem, 0, sz); + cached_fw = (fw_image_t **)mem; + alloc_total += sz; + + /* malloc fragment memory + * fw_image_t struct and dma for fw data + */ + bytes_left = size; + ii = 0; + num_frags = 0; + bytes = bytes_left; + while((bytes_left) && (num_frags < ioc->num_fw_frags)) { + if (cached_fw[ii] == NULL) { + mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC); + if (mem == NULL) + break; + + memset(mem, 0, sizeof(fw_image_t)); + cached_fw[ii] = (fw_image_t *)mem; + alloc_total += sizeof(fw_image_t); + } + + mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma); + if (mem == NULL) { + if (bytes > 0x10000) + bytes = 0x10000; + else if (bytes > 0x8000) + bytes = 0x8000; + else if (bytes > 0x4000) + bytes = 0x4000; + else if (bytes > 0x2000) + bytes = 0x2000; + else if (bytes > 0x1000) + bytes = 0x1000; + else + break; + + continue; + } + + cached_fw[ii]->fw = mem; + cached_fw[ii]->fw_dma = fw_dma; + cached_fw[ii]->size = bytes; + memset(mem, 0, bytes); + alloc_total += bytes; + + bytes_left -= bytes; + + num_frags++; + ii++; + } + + if (bytes_left ) { + /* Major Failure. + */ + mpt_free_fw_memory(ioc, cached_fw); + return NULL; + } + + *frags = num_frags; + *alloc_sz = alloc_total; - if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) ) - ioc->alloc_total += size; + return (void *) cached_fw; } /* @@ -2687,14 +2858,45 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) * Else, delete a secondary image in same format. */ void -mpt_free_fw_memory(MPT_ADAPTER *ioc) +mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img) { + fw_image_t **cached_fw; + int ii; int sz; + int alloc_freed = 0; - sz = ioc->facts.FWImageSize; - pci_free_consistent(ioc->pcidev, sz, - ioc->cached_fw, ioc->cached_fw_dma); - ioc->cached_fw = NULL; + if (alt_img != NULL) + cached_fw = alt_img; + else + cached_fw = ioc->cached_fw; + + if (cached_fw == NULL) + return; + + ii = 0; + while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) { + sz = cached_fw[ii]->size; + if (sz > 0) { + pci_free_consistent(ioc->pcidev, sz, + cached_fw[ii]->fw, cached_fw[ii]->fw_dma); + } + cached_fw[ii]->fw = NULL; + alloc_freed += sz; + + kfree(cached_fw[ii]); + cached_fw[ii] = NULL; + alloc_freed += sizeof(fw_image_t); + + ii++; + } + + kfree(cached_fw); + cached_fw = NULL; + sz = ioc->num_fw_frags * sizeof(void *); + alloc_freed += sz; + + if (alt_img == NULL) + ioc->alloc_total -= alloc_freed; return; } @@ -2723,9 +2925,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) FWUploadReply_t *preply; FWUploadTCSGE_t *ptcsge; int sgeoffset; - u32 flagsLength; int ii, sz, reply_sz; int cmdStatus, freeMem = 0; + int num_frags, alloc_sz; /* If the image size is 0 or if the pointer is * not NULL (error), we are done. @@ -2733,21 +2935,24 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw) return 0; - if ( sz & 0x01 ) - sz += 1; - if ( sz & 0x02 ) - sz += 2; + ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1; + ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32); - mpt_alloc_fw_memory(ioc, sz); + ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc, + ioc->facts.FWImageSize, &num_frags, &alloc_sz); if (ioc->cached_fw == NULL) { /* Major Failure. */ + mpt_free_fw_memory(ioc, NULL); + ioc->cached_fw = NULL; + return -ENOMEM; } + ioc->alloc_total += alloc_sz; - dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", - ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); + ddlprintk((KERN_INFO MYNAM ": FW Image @ %p, sz=%d bytes\n", + (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize)); prequest = (FWUpload_t *)&request; preply = (FWUploadReply_t *)&reply; @@ -2760,27 +2965,39 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM; prequest->Function = MPI_FUNCTION_FW_UPLOAD; + prequest->MsgContext = 0; /* anything */ ptcsge = (FWUploadTCSGE_t *) &prequest->SGL; + ptcsge->Reserved = 0; + ptcsge->ContextSize = 0; ptcsge->DetailsLength = 12; ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; + ptcsge->Reserved1 = 0; + ptcsge->ImageOffset = 0; ptcsge->ImageSize = cpu_to_le32(sz); sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; - mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); + for (ii = 0; ii < (num_frags-1); ii++) { + mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT | + MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST | + (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma); + + sgeoffset += sizeof(u32) + sizeof(dma_addr_t); + } + + mpt_add_sge(&request[sgeoffset], + MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size, + ioc->cached_fw[ii]->fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n", - prequest, sgeoffset)); - DBG_DUMP_FW_REQUEST_FRAME(prequest) + + dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n", + ioc->name, prequest, sgeoffset)); ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); - dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii)); - cmdStatus = -EFAULT; if (ii == 0) { /* Handshake transfer was complete and successful. @@ -2794,7 +3011,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) cmdStatus = 0; } } - dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", + ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", ioc->name, cmdStatus)); /* Check to see if we have a copy of this image in @@ -2814,7 +3031,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n", ioc->name, cmdStatus ? "incomplete" : "duplicate")); - mpt_free_fw_memory(ioc); + mpt_free_fw_memory(ioc, NULL); + ioc->cached_fw = NULL; } return cmdStatus; @@ -2837,138 +3055,241 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) { - MpiFwHeader_t *pFwHeader; - MpiExtImageHeader_t *pExtImage; - u32 fwSize; + MpiFwHeader_t *FwHdr; + MpiExtImageHeader_t *ExtHdr; + fw_image_t **pCached=NULL; + int fw_sz; u32 diag0val; #ifdef MPT_DEBUG u32 diag1val = 0; #endif int count = 0; - u32 *ptrFw; + u32 *ptru32; u32 diagRwData; u32 nextImage; + u32 ext_offset; u32 load_addr; - u32 ioc_state; + int max_idx, fw_idx, ext_idx; + int left_u32s; - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", + ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n", + ioc->name)); +#ifdef MPT_DEBUG + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +#endif + + ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n", ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); + if (ioc->alt_ioc) + ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n", + ioc->name, ioc->alt_ioc->cached_fw)); /* Get dma_addr and data transfer size. */ - if ( ioc->facts.FWImageSize == 0 ) + if ((fw_sz = ioc->facts.FWImageSize) == 0) return -1; /* Get the DMA from ioc or ioc->alt_ioc */ - if (ioc->cached_fw == NULL) + if (ioc->cached_fw != NULL) + pCached = (fw_image_t **)ioc->cached_fw; + else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL)) + pCached = (fw_image_t **)ioc->alt_ioc->cached_fw; + else return -2; - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); + ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n", + ioc->name, pCached)); + /* Write magic sequence to WriteSequence register + * until enter diagnostic mode + */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - diag0val |= (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); - } else { - mdelay (100); - } - - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); + while ((diag0val & MPI_DIAG_DRWE) == 0) { + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - for (count = 0; count < 30; count ++) { - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { - ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n", - ioc->name, count)); - break; - } - /* wait 1 sec */ + /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout(100 * HZ / 1000); } else { - mdelay (1000); + mdelay (100); } - } - if ( count == 30 ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n", - ioc->name, diag0val)); - return -3; - } + count++; + if (count > 20) { + printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", + ioc->name, diag0val); + return -EFAULT; - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); - CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); + } + + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +#ifdef MPT_DEBUG + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +#endif + ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", + ioc->name, diag0val)); + } /* Set the DiagRwEn and Disable ARM bits */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, (diag0val | MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); + diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; - fwSize = (pFwHeader->ImageSize + 3)/4; - ptrFw = (u32 *) pFwHeader; +#ifdef MPT_DEBUG + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + + ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); +#endif + + /* max_idx = 1 + maximum valid buffer index + */ + max_idx = 0; + while (pCached[max_idx]) + max_idx++; + + fw_idx = 0; + FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw; + ptru32 = (u32 *) FwHdr; + count = (FwHdr->ImageSize + 3)/4; + nextImage = FwHdr->NextImageHeaderOffset; /* Write the LoadStartAddress to the DiagRw Address Register * using Programmed IO */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress); ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", - ioc->name, pFwHeader->LoadStartAddress)); - - ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n", - ioc->name, fwSize*4, ptrFw)); - while (fwSize--) { - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); + ioc->name, FwHdr->LoadStartAddress)); + + ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n", + ioc->name, count, ptru32)); + left_u32s = pCached[fw_idx]->size/4; + while (count--) { + if (left_u32s == 0) { + fw_idx++; + if (fw_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ptru32 = (u32 *) pCached[fw_idx]->fw; + left_u32s = pCached[fw_idx]->size / 4; + } + left_u32s--; + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); + ptru32++; } - nextImage = pFwHeader->NextImageHeaderOffset; + /* left_u32s, fw_idx and ptru32 are all valid + */ while (nextImage) { - pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage); + ext_idx = 0; + ext_offset = nextImage; + while (ext_offset > pCached[ext_idx]->size) { + ext_idx++; + if (ext_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ext_offset -= pCached[ext_idx]->size; + } + ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset); + left_u32s = pCached[ext_idx]->size - ext_offset; + + if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) { + ExtHdr = (MpiExtImageHeader_t *) ptru32; + count = (ExtHdr->ImageSize + 3 )/4; + nextImage = ExtHdr->NextImageHeaderOffset; + load_addr = ExtHdr->LoadStartAddress; + } else { + u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw; - load_addr = pExtImage->LoadStartAddress; + switch (left_u32s) { + case 5: + count = *(ptru32 + 2); + nextImage = *(ptru32 + 3); + load_addr = *(ptru32 + 4); + break; + case 4: + count = *(ptru32 + 2); + nextImage = *(ptru32 + 3); + load_addr = *ptmp; + break; + case 3: + count = *(ptru32 + 2); + nextImage = *ptmp; + load_addr = *(ptmp + 1); + break; + case 2: + count = *ptmp; + nextImage = *(ptmp + 1); + load_addr = *(ptmp + 2); + break; - fwSize = (pExtImage->ImageSize + 3) >> 2; - ptrFw = (u32 *)pExtImage; + case 1: + count = *(ptmp + 1); + nextImage = *(ptmp + 2); + load_addr = *(ptmp + 3); + break; - ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n", - ioc->name, fwSize*4, ptrFw, load_addr)); + default: + count = 0; + nextImage = 0; + load_addr = 0; + /* FIXME + ERROR CASE + */ + ; + + } + count = (count +3)/4; + } + + ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n", + ioc->name, count, ptru32)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); - while (fwSize--) { - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); + while (count--) { + if (left_u32s == 0) { + fw_idx++; + if (fw_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ptru32 = (u32 *) pCached[fw_idx]->fw; + left_u32s = pCached[fw_idx]->size / 4; + } + left_u32s--; + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); + ptru32++; } - nextImage = pExtImage->NextImageHeaderOffset; } /* Write the IopResetVectorRegAddr */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr); + ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr); /* Write the IopResetVectorValue */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue); - - /* clear the PREVENT_IOC_BOOT bit */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT\n", - ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", - ioc->name, diag0val)); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); + ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue); /* Clear the internal flash bad bit - autoincrementing register, * so must do two writes. @@ -2979,63 +3300,15 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + /* clear the RW enable and DISARM bits */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off DISABLE_ARM, RW_ENABLE, RESET_HISTORY\n", - ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_RESET_HISTORY); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", - ioc->name, diag0val)); + diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { - ddlprintk((MYIOC_s_INFO_FMT "CAN_SLEEP 100 msec before reset the sequencer\n", ioc->name)); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); - } else { - ddlprintk((MYIOC_s_INFO_FMT "mdelay 100 msec before reset the sequencer\n", ioc->name)); - mdelay (100); - } - - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if ( diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM) ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed, diag0val=%x FLASH_BAD_SIG | DISABLE_ARM on\n ", - ioc->name, diag0val)); - } /* Write 0xFF to reset the sequencer */ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); - for (count=0; countname, count, ioc_state)); -/* if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { - if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { - ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed\n", - ioc->name)); - return -EFAULT; - } - } */ - /* wait 2 sec */ -/* if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5000 * HZ / 1000); - } else { - mdelay (5000); - } */ - - return 0; - } - if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } else { - mdelay (10); - } - } - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n", - ioc->name, ioc_state)); - return -EFAULT; + return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -3071,7 +3344,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) u32 ioc_state; int cntdn, cnt = 0; - dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); + dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); if ((int)ioc->chip_type > (int)FC929) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. @@ -3320,7 +3593,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* Write magic sequence to WriteSequence register * Loop until in diagnostic mode */ - CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); @@ -3400,7 +3672,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) u32 state; int cntdn, count; - drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", + dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", ioc->name, reset_type)); CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<name, t, failcnt ? " - MISSING DOORBELL REPLY!" : "")); /* * Copy out the cached reply... @@ -3773,7 +4042,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) { int cntdn; int count = 0; - u32 intstat=0; + u32 intstat; cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; @@ -3797,13 +4066,13 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } if (cntdn) { - dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n", + dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n", ioc->name, count)); return count; } - printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n", - ioc->name, count, intstat); + printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n", + ioc->name, (count+5)/HZ); return -1; } @@ -3824,7 +4093,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) { int cntdn; int count = 0; - u32 intstat=0; + u32 intstat; cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; if (sleepFlag == CAN_SLEEP) { @@ -3847,13 +4116,13 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } if (cntdn) { - dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n", - ioc->name, count, howlong)); + dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n", + ioc->name, count)); return count; } - printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n", - ioc->name, count, intstat); + printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n", + ioc->name, (count+5)/HZ); return -1; } @@ -3899,8 +4168,8 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } } - dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", - ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), + dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n", + ioc->name, le32_to_cpu(*(u32 *)hs_reply), failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); /* @@ -3938,8 +4207,8 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name)); DBG_DUMP_REPLY_FRAME(mptReply) - dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", - ioc->name, t, u16cnt/2)); + dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n", + ioc->name, u16cnt/2)); return u16cnt/2; } @@ -4731,7 +5000,7 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) { EventNotification_t *evnp; - evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); + evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc->id); if (evnp == NULL) { dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", ioc->name)); @@ -4746,7 +5015,7 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) evnp->MsgFlags = 0; evnp->Switch = EvSwitch; - mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp); + mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)evnp); return 0; } @@ -4762,7 +5031,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) { EventAck_t *pAck; - if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { + if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n", ioc->name); return -1; @@ -4777,7 +5046,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) pAck->Event = evnp->Event; pAck->EventContext = evnp->EventContext; - mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck); + mpt_put_msg_frame(mpt_base_index, ioc->id, (MPT_FRAME_HDR *)pAck); return 0; } @@ -4803,7 +5072,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) MPT_FRAME_HDR *mf; unsigned long flags; int ii, rc; - u32 flagsLength; + int flagsLength; int in_isr; /* (Bugzilla:fibrebugs, #513) @@ -4820,7 +5089,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", ioc->name)); return -EAGAIN; @@ -4879,7 +5148,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); - mpt_put_msg_frame(mpt_base_index, ioc, mf); + mpt_put_msg_frame(mpt_base_index, ioc->id, mf); wait_event(mpt_waitq, pCfg->wait_done); /* mf has been freed - do not access */ @@ -4907,11 +5176,10 @@ int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) { ToolboxIstwiReadWriteRequest_t *pReq; - struct pci_dev *pdev; MPT_FRAME_HDR *mf; unsigned long flags; int rc; - u32 flagsLength; + int flagsLength; int in_isr; /* (Bugzilla:fibrebugs, #513) @@ -4928,7 +5196,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n", ioc->name)); return -EAGAIN; @@ -4947,11 +5215,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) pReq->NumAddressBytes = 0x01; pReq->Reserved4 = 0; pReq->DataLength = 0x04; - pdev = (struct pci_dev *) ioc->pcidev; - if (pdev->devfn & 1) - pReq->DeviceAddr = 0xB2; - else - pReq->DeviceAddr = 0xB0; + pReq->DeviceAddr = 0xB0; pReq->Addr1 = 0; pReq->Addr2 = 0; pReq->Addr3 = 0; @@ -4990,7 +5254,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); - mpt_put_msg_frame(mpt_base_index, ioc, mf); + mpt_put_msg_frame(mpt_base_index, ioc->id, mf); wait_event(mpt_waitq, pCfg->wait_done); /* mf has been freed - do not access */ @@ -5104,19 +5368,61 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) static int procmpt_create(void) { + MPT_ADAPTER *ioc; struct proc_dir_entry *ent; + int ii; + /* + * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt" + * (single level) to multi level (e.g. "driver/message/fusion") + * something here needs to change. -sralston + */ mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); if (mpt_proc_root_dir == NULL) return -ENOTDIR; - ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir); - if (ent) - ent->read_proc = procmpt_summary_read; + for (ii=0; ii < MPT_PROC_ENTRIES; ii++) { + ent = create_proc_entry(mpt_proc_list[ii].name, + S_IFREG|S_IRUGO, mpt_proc_root_dir); + if (!ent) { + printk(KERN_WARNING MYNAM + ": WARNING - Could not create /proc/mpt/%s entry\n", + mpt_proc_list[ii].name); + continue; + } + ent->read_proc = mpt_proc_list[ii].f; + ent->data = NULL; + } - ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir); - if (ent) - ent->read_proc = procmpt_version_read; + ioc = mpt_adapter_find_first(); + while (ioc != NULL) { + struct proc_dir_entry *dent; + /* + * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter. + */ + if ((dent = proc_mkdir(ioc->name, mpt_proc_root_dir)) != NULL) { + /* + * And populate it with mpt_ioc_proc_list[] entries. + */ + for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) { + ent = create_proc_entry(mpt_ioc_proc_list[ii].name, + S_IFREG|S_IRUGO, dent); + if (!ent) { + printk(KERN_WARNING MYNAM + ": WARNING - Could not create /proc/mpt/%s/%s entry!\n", + ioc->name, + mpt_ioc_proc_list[ii].name); + continue; + } + ent->read_proc = mpt_ioc_proc_list[ii].f; + ent->data = ioc; + } + } else { + printk(MYIOC_s_WARN_FMT "Could not create /proc/mpt/%s subdir entry!\n", + ioc->name, mpt_ioc_proc_list[ii].name); + } + ioc = mpt_adapter_find_next(ioc); + } return 0; } @@ -5127,12 +5433,49 @@ procmpt_create(void) * * Returns 0 for success, non-zero for failure. */ -static void +static int procmpt_destroy(void) { - remove_proc_entry("version", mpt_proc_root_dir); - remove_proc_entry("summary", mpt_proc_root_dir); - remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL); + MPT_ADAPTER *ioc; + int ii; + + if (!mpt_proc_root_dir) + return 0; + + /* + * BEWARE: If/when MPT_PROCFS_MPTBASEDIR changes from "mpt" + * (single level) to multi level (e.g. "driver/message/fusion") + * something here needs to change. -sralston + */ + + ioc = mpt_adapter_find_first(); + while (ioc != NULL) { + char pname[32]; + int namelen; + + namelen = sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name); + + /* + * Tear down each "/proc/mpt/iocN" subdirectory. + */ + for (ii=0; ii < MPT_IOC_PROC_ENTRIES; ii++) { + (void) sprintf(pname+namelen, "/%s", mpt_ioc_proc_list[ii].name); + remove_proc_entry(pname, NULL); + } + remove_proc_entry(ioc->name, mpt_proc_root_dir); + ioc = mpt_adapter_find_next(ioc); + } + + for (ii=0; ii < MPT_PROC_ENTRIES; ii++) + remove_proc_entry(mpt_proc_list[ii].name, mpt_proc_root_dir); + + if (atomic_read((atomic_t *)&mpt_proc_root_dir->count) == 0) { + remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL); + mpt_proc_root_dir = NULL; + return 0; + } + + return -1; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -5155,25 +5498,26 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo char *out = buf; int len; - if (data) { - int more = 0; - + if (data == NULL) + ioc = mpt_adapter_find_first(); + else ioc = data; - mpt_print_ioc_summary(ioc, out, &more, 0, 1); - out += more; - } else { - list_for_each_entry(ioc, &ioc_list, list) { - int more = 0; + while (ioc) { + int more = 0; - mpt_print_ioc_summary(ioc, out, &more, 0, 1); + mpt_print_ioc_summary(ioc, out, &more, 0, 1); - out += more; - if ((out-buf) >= request) - break; + out += more; + if ((out-buf) >= request) { + break; } - } + if (data == NULL) + ioc = mpt_adapter_find_next(ioc); + else + ioc = NULL; /* force exit for iocN */ + } len = out - buf; MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); @@ -5951,7 +6295,7 @@ mpt_deregister_ascqops_strings(void) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -EXPORT_SYMBOL(ioc_list); +EXPORT_SYMBOL(mpt_adapters); EXPORT_SYMBOL(mpt_proc_root_dir); EXPORT_SYMBOL(DmpService); EXPORT_SYMBOL(mpt_register); @@ -5969,6 +6313,8 @@ EXPORT_SYMBOL(mpt_add_sge); EXPORT_SYMBOL(mpt_add_chain); EXPORT_SYMBOL(mpt_send_handshake_request); EXPORT_SYMBOL(mpt_handshake_req_reply_wait); +EXPORT_SYMBOL(mpt_adapter_find_first); +EXPORT_SYMBOL(mpt_adapter_find_next); EXPORT_SYMBOL(mpt_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); @@ -6023,6 +6369,7 @@ fusion_init(void) show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); + Q_INIT(&MptAdapters, MPT_ADAPTER); /* set to empty */ for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) { MptCallbacks[i] = NULL; MptDriverClass[i] = MPTUNKNOWN_DRIVER; @@ -6046,13 +6393,14 @@ fusion_init(void) /* FIXME! */ } -#ifdef CONFIG_PROC_FS - (void) procmpt_create(); -#endif r = pci_module_init(&mptbase_driver); if(r) return(r); +#ifdef CONFIG_PROC_FS + (void) procmpt_create(); +#endif + return r; } @@ -6067,14 +6415,16 @@ static void __exit fusion_exit(void) { - dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - - pci_unregister_driver(&mptbase_driver); - mpt_reset_deregister(mpt_base_index); + dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); + /* Whups? 20010120 -sralston + * Moved this *above* removal of all MptAdapters! + */ #ifdef CONFIG_PROC_FS - procmpt_destroy(); + (void) procmpt_destroy(); #endif + pci_unregister_driver(&mptbase_driver); + mpt_reset_deregister(mpt_base_index); }