📄 mptbase.c
字号:
if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* * Pre-fetch the ports LAN MAC address! * (LANPage1_t stuff) */ (void) GetLanConfigPages(ioc);#ifdef MPT_DEBUG { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; dprintk((KERN_INFO MYNAM ": %s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] )); }#endif } /* Enable! (reply interrupt) */ CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->active = 1;// NEW!#if 0 // Kiss-of-death!?! if (alt_ioc_ready && (r==0)) { /* (re)Enable alt-IOC! (reply interrupt) */ dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->alt_ioc->active = 1; }#endif /* NEW! 20010120 -sralston * Enable MPT base driver management of EventNotification * and EventAck handling. */ if (!ioc->facts.EventState) (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */// NEW!// FIXME!?!// if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) {// (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */// } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_detect_929_bound_ports - Search for PCI bus/dev_function * which matches PCI bus/dev_function (+/-1) for newly discovered 929. * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * * If match on PCI dev_function +/-1 is found, bind the two MPT adapters * using alt_ioc pointer fields in their %MPT_ADAPTER structures. */static voidmpt_detect_929_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev){ MPT_ADAPTER *ioc_srch = mpt_adapter_find_first(); unsigned int match_lo, match_hi; match_lo = pdev->devfn-1; match_hi = pdev->devfn+1; dprintk((KERN_INFO MYNAM ": %s: 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)); while (ioc_srch != NULL) { struct pci_dev *_pcidev = ioc_srch->pcidev; if ( (_pcidev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) && (_pcidev->bus->number == pdev->bus->number) && (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) { /* Paranoia checks */ if (ioc->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc->name, ioc->alt_ioc->name); break; } else if (ioc_srch->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc_srch->name, ioc_srch->alt_ioc->name); break; } dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; ioc->sod_reset = ioc->alt_ioc->sod_reset; ioc->last_kickstart = ioc->alt_ioc->last_kickstart; break; } ioc_srch = mpt_adapter_find_next(ioc_srch); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_adapter_disable - Disable misbehaving MPT adapter. * @this: Pointer to MPT adapter structure * @free: Free up alloc'd reply, request, etc. */static voidmpt_adapter_disable(MPT_ADAPTER *this, int freeup){ if (this != NULL) { int sz; u32 state; /* Disable the FW */ state = GetIocState(this, 1); if (state == MPI_IOC_STATE_OPERATIONAL) { if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET) != 0) (void) KickStart(this, 1); } /* Disable adapter interrupts! */ CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); this->active = 0; /* Clear any lingering interrupt */ CHIPREG_WRITE32(&this->chip->IntStatus, 0); if (freeup && this->reply_alloc != NULL) { sz = (this->reply_sz * this->reply_depth) + 128; pci_free_consistent(this->pcidev, sz, this->reply_alloc, this->reply_alloc_dma); this->reply_frames = NULL; this->reply_alloc = NULL; this->alloc_total -= sz; } if (freeup && this->req_alloc != NULL) { sz = (this->req_sz * this->req_depth) + 128; /* * Rounding UP to nearest 4-kB boundary here... */ sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; pci_free_consistent(this->pcidev, sz, this->req_alloc, this->req_alloc_dma); this->req_frames = NULL; this->req_alloc = NULL; this->alloc_total -= sz; } if (freeup && this->sense_buf_pool != NULL) { sz = (this->req_depth * 256); pci_free_consistent(this->pcidev, sz, this->sense_buf_pool, this->sense_buf_pool_dma); this->sense_buf_pool = NULL; this->alloc_total -= sz; } }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_adapter_dispose - Free all resources associated with a MPT * adapter. * @this: Pointer to MPT adapter structure * * This routine unregisters h/w resources and frees all alloc'd memory * associated with a MPT adapter structure. */static voidmpt_adapter_dispose(MPT_ADAPTER *this){ if (this != NULL) { int sz_first, sz_last; sz_first = this->alloc_total; mpt_adapter_disable(this, 1); if (this->pci_irq != -1) { free_irq(this->pci_irq, this); this->pci_irq = -1; } if (this->memmap != NULL) iounmap((u8 *) this->memmap);#if defined(CONFIG_MTRR) && 0 if (this->mtrr_reg > 0) { mtrr_del(this->mtrr_reg, 0, 0); dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name)); }#endif /* Zap the adapter lookup ptr! */ mpt_adapters[this->id] = NULL; sz_last = this->alloc_total; dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", this->name, sz_first-sz_last+(int)sizeof(*this), sz_first)); kfree(this); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * MptDisplayIocCapabilities - Disply IOC's capacilities. * @ioc: Pointer to MPT adapter structure */static voidMptDisplayIocCapabilities(MPT_ADAPTER *ioc){ int i = 0; printk(KERN_INFO "%s: ", ioc->name); if (ioc->prod_name && strlen(ioc->prod_name) > 3) printk("%s: ", ioc->prod_name+3); printk("Capabilities={"); if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { printk("Initiator"); i++; } if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { printk("%sTarget", i ? "," : ""); i++; } if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { printk("%sLAN", i ? "," : ""); i++; }#if 0 /* * This would probably evoke more questions than it's worth */ if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { printk("%sLogBusAddr", i ? "," : ""); i++; }#endif printk("}\n");}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * MakeIocReady - Get IOC to a READY state, using KickStart if needed. * @ioc: Pointer to MPT_ADAPTER structure * @kick: Force hard KickStart of IOC * * Returns 0 for already-READY, 1 for hard reset success, * else negative for failure. */static intMakeIocReady(MPT_ADAPTER *ioc, int force){ u32 ioc_state; int statefault = 0; int cntdn; int hard_reset_done = 0; int r; int i; /* Get current [raw] IOC state */ ioc_state = GetIocState(ioc, 0); dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); /* * Check to see if IOC got left/stuck in doorbell handshake * grip of death. If so, hard reset the IOC. */ if (ioc_state & MPI_DOORBELL_ACTIVE) { statefault = 1; printk(KERN_WARNING MYNAM ": %s: Uh-oh, unexpected doorbell active!\n", ioc->name); } /* Is it already READY? */ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) return 0; /* * Check to see if IOC is in FAULT state. */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { statefault = 2; printk(KERN_WARNING MYNAM ": %s: Uh-oh, IOC is in FAULT state!!!\n", ioc->name); printk(KERN_WARNING " FAULT code = %04xh\n", ioc_state & MPI_DOORBELL_DATA_MASK); } /* * Hmmm... Did it get left operational? */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { statefault = 3; dprintk((KERN_WARNING MYNAM ": %s: Hmmm... IOC operational unexpected\n", ioc->name)); } hard_reset_done = KickStart(ioc, statefault||force); if (hard_reset_done < 0) return -1; /* * Loop here waiting for IOC to come READY. */ i = 0; cntdn = HZ * 15; while ((ioc_state = GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { /* * BIOS or previous driver load left IOC in OP state. * Reset messaging FIFOs. */ if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)) != 0) { printk(KERN_ERR MYNAM ": %s: ERROR - IOC msg unit reset failed!\n", ioc->name); return -2; } } else if (ioc_state == MPI_IOC_STATE_RESET) { /* * Something is wrong. Try to get IOC back * to a known state. */ if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET)) != 0) { printk(KERN_ERR MYNAM ": %s: ERROR - IO unit reset failed!\n", ioc->name); return -3; } } i++; cntdn--; if (!cntdn) { printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", ioc->name, (i+5)/HZ); return -ETIME; } current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } if (statefault < 3) { printk(KERN_WARNING MYNAM ": %s: Whew! Recovered from %s\n", ioc->name, statefault==1 ? "stuck handshake" : "IOC FAULT"); } return hard_reset_done;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * GetIocState - Get the current state of a MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @cooked: Request raw or cooked IOC state * * Returns all IOC Doorbell register bits if cooked==0, else just the * Doorbell bits in MPI_IOC_STATE_MASK. */static u32GetIocState(MPT_ADAPTER *ioc, int cooked){ u32 s, sc; /* Get! */ s = CHIPREG_READ32(&ioc->chip->Doorbell); dprintk((KERN_INFO MYNAM ": %s: raw state = %08x\n", ioc->name, s)); sc = s & MPI_IOC_STATE_MASK; /* Save! */ ioc->last_state = sc; return cooked ? sc : s;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * GetIocFacts - Send IOCFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * * Returns 0 for success, non-zero for failure. */static intGetIocFacts(MPT_ADAPTER *ioc){ IOCFacts_t get_facts; IOCFactsReply_t *facts; int r; int req_sz; int reply_sz; u32 status; /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", ioc->name, ioc->last_state ); return -44; } facts = &ioc->facts; /* Destination (reply area)... */ reply_sz = sizeof(*facts); memset(facts, 0, reply_sz); /* Request area (get_facts on the stack right now!) */ req_sz = sizeof(get_facts); memset(&get_facts, 0, req_sz); get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ dprintk((KERN_INFO MYNAM ": %s: 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. */ r = HandShakeReqAndReply(ioc, req_sz, (u32*)&get_facts, reply_sz, (u16*)facts, 3); if (r != 0) return r; /* * Now byte swap (GRRR) the necessary fields before any further * inspection of reply contents. * * But need to do some sanity checks on MsgLength (byte) field * to make sure we don't zero IOC's req_sz! */ /* Did we get a valid reply? */ if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) { /* * If not been here, done that, save off first WhoInit value */ if (ioc->FirstWhoInit == WHOINIT_UNKNOWN) ioc->FirstWhoInit = facts->WhoInit; facts->MsgVersion = le16_to_cpu(facts->MsgVersion); facts->MsgContext = le32_to_cpu(facts->MsgContext); facts->IOCStatus = le16_to_cpu(facts->IOCStatus); facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo); status = facts->IOCStatus & MPI_IOCSTATUS_MASK; /* CHECKME! IOCStatus, IOCLogInfo */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -