📄 mptbase.c
字号:
printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", state); } } /* 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 * MPT_SENSE_BUFFER_ALLOC); pci_free_consistent(this->pcidev, sz, this->sense_buf_pool, this->sense_buf_pool_dma); this->sense_buf_pool = NULL; this->alloc_total -= sz; } if (freeup && this->events != NULL){ sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); kfree(this->events); this->events = NULL; this->alloc_total -= sz; } if (freeup && this->cached_fw != NULL) { int ii = 0; 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; } if (freeup && this->spi_data.nvram != NULL) { kfree(this->spi_data.nvram); this->spi_data.nvram = NULL; } if (freeup && this->spi_data.pIocPg3 != NULL) { kfree(this->spi_data.pIocPg3); this->spi_data.pIocPg3 = NULL; } }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * 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 * @force: Force hard KickStart of IOC * @sleepFlag: Specifies whether the process can sleep * * Returns: * 1 - DIAG reset and READY * 0 - READY initially OR soft reset and READY * -1 - Any failure on KickStart * -2 - Msg Unit Reset Failed * -3 - IO Unit Reset Failed * -4 - IOC owned by a PEER */static intMakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag){ u32 ioc_state; int statefault = 0; int cntdn; int hard_reset_done = 0; int r; int ii; int whoinit; /* Get current [raw] IOC state */ ioc_state = mpt_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(MYIOC_s_WARN_FMT "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(MYIOC_s_WARN_FMT "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) { dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. * If PCI Peer, exit. * Else, if no fault conditions are present, issue a MessageUnitReset * Else, fall through to KickStart case */ whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; dprintk((KERN_WARNING MYNAM ": whoinit 0x%x\n statefault %d force %d\n", whoinit, statefault, force)); if (whoinit == MPI_WHOINIT_PCI_PEER) return -4; else { if ((statefault == 0 ) && (force == 0)) { if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) return 0; } statefault = 3; } } hard_reset_done = KickStart(ioc, statefault||force, sleepFlag); if (hard_reset_done < 0) return -1; /* * Loop here waiting for IOC to come READY. */ ii = 0; cntdn = HZ * 15; if (sleepFlag != CAN_SLEEP) cntdn *= 10; /* 1500 iterations @ 1msec per */ while ((ioc_state = mpt_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, sleepFlag)) != 0) { printk(MYIOC_s_ERR_FMT "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, sleepFlag)) != 0) { printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name); return -3; } } ii++; cntdn--; if (!cntdn) { printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", ioc->name, (ii+5)/HZ); return -ETIME; } if (sleepFlag == CAN_SLEEP) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } else { mdelay (1); /* 1 msec delay */ } } if (statefault < 3) { printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name, statefault==1 ? "stuck handshake" : "IOC FAULT"); } return hard_reset_done;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_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. */u32mpt_GetIocState(MPT_ADAPTER *ioc, int cooked){ u32 s, sc; /* Get! */ s = CHIPREG_READ32(&ioc->chip->Doorbell);// dprintk((MYIOC_s_INFO_FMT "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 * @sleepFlag: Specifies whether the process can sleep * @reason: If recovery, only update facts. * * Returns 0 for success, non-zero for failure. */static intGetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason){ 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((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. */ r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts, reply_sz, (u16*)facts, 3 /*seconds*/, sleepFlag); 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 (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* * 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->IOCExceptions = le16_to_cpu(facts->IOCExceptions); facts->IOCStatus = le16_to_cpu(facts->IOCStatus); facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo); status = facts->IOCStatus & MPI_IOCSTATUS_MASK; /* CHECKME! IOCStatus, IOCLogInfo */ facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth); facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize); /* * FC f/w version changed between 1.1 and 1.2 * Old: u16{Major(4),Minor(4),SubMinor(8)} * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} */ if (facts->MsgVersion < 0x0102) { /* * Handle old FC f/w style, convert to new... */ u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion); facts->FWVersion.Word = ((oldv<<12) & 0xFF000000) | ((oldv<<8) & 0x000FFF00); } else facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); facts->ProductID = le16_to_cpu(facts->ProductID); facts->CurrentHostMfaHighAddr = le32_to_cpu(facts->CurrentHostMfaHighAddr); facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); facts->CurrentSenseBufferHighAddr = le32_to_cpu(facts->CurrentSenseBufferHighAddr); facts->CurReplyFrameSize = le16_to_cpu(facts->CurReplyFrameSize); /* * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx * Older MPI-1.00.xx struct had 13 dwords, and enlarged * to 14 in MPI-1.01.0x. */ if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && facts->MsgVersion > 0x0100) { facts
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -