📄 mptbase.c
字号:
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->FWImageSize = le32_to_cpu(facts->FWImageSize); } if (!facts->RequestFrameSize) { /* Something is wrong! */ printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n", ioc->name); return -55; } if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* * Set values for this IOC's request & reply frame sizes, * and request & reply queue depths... */ ioc->req_sz = MIN(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4); ioc->req_depth = MIN(MPT_DEFAULT_REQ_DEPTH, facts->GlobalCredits); ioc->reply_sz = ioc->req_sz; ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); /* 1030 - should we use a smaller DEFAULT_REPLY_DEPTH? * FIX */ dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", ioc->name, ioc->req_sz, ioc->req_depth)); /* Get port facts! */ if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 ) return r; } } else { printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n", ioc->name); return -66; } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * GetPortFacts - Send PortFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: Port number * @sleepFlag: Specifies whether the process can sleep * * Returns 0 for success, non-zero for failure. */static intGetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag){ PortFacts_t get_pfacts; PortFactsReply_t *pfacts; int ii; int req_sz; int reply_sz; /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n", ioc->name, ioc->last_state ); return -4; } pfacts = &ioc->pfacts[portnum]; /* Destination (reply area)... */ reply_sz = sizeof(*pfacts); memset(pfacts, 0, reply_sz); /* Request area (get_pfacts on the stack right now!) */ req_sz = sizeof(get_pfacts); memset(&get_pfacts, 0, req_sz); get_pfacts.Function = MPI_FUNCTION_PORT_FACTS; get_pfacts.PortNumber = portnum; /* Assert: All other get_pfacts fields are zero! */ dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n", ioc->name, portnum)); /* No non-zero fields in the get_pfacts request are greater than * 1 byte in size, so we can just fire it off as is. */ ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts, reply_sz, (u16*)pfacts, 3 /*seconds*/, sleepFlag); if (ii != 0) return ii; /* Did we get a valid reply? */ /* Now byte swap the necessary fields in the response. */ pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext); pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); pfacts->MaxLanBuckets = le16_to_cpu(pf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -