📄 mptbase.c
字号:
/* * Maintain only one pointer to FW memory * so there will not be two attempt to * downloadboot onboard dual function * chips (mpt_adapter_disable, * mpt_diag_reset) */ ioc->cached_fw = NULL; ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n", ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); } } else { printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); ret = -5; } } } } if (ret == 0) { /* Enable! (reply interrupt) */ CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->active = 1; } if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ dinitprintk((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; } /* Enable MPT base driver management of EventNotification * and EventAck handling. */ if ((ret == 0) && (!ioc->facts.EventState)) (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ /* Add additional "reason" check before call to GetLanConfigPages * (combined with GetIoUnitPage2 call). This prevents a somewhat * recursive scenario; GetLanConfigPages times out, timer expired * routine calls HardResetHandler, which calls into here again, * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { if (ioc->bus_type == SAS) { /* clear persistency table */ if(ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { ret = mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); if(ret != 0) return -1; } /* Find IM volumes */ mpt_findImVolumes(ioc); } else if (ioc->bus_type == FC) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { (void) GetFcPortPage0(ioc, ii); } 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((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] )); }#endif } } else { /* Get NVRAM and adapter maximums from SPP 0 and 2 */ mpt_GetScsiPortSettings(ioc, 0); /* Get version and length of SDP 1 */ mpt_readScsiDevicePageHeaders(ioc, 0); /* Find IM volumes */ if (ioc->facts.MsgVersion >= MPI_VERSION_01_02) mpt_findImVolumes(ioc); /* Check, and possibly reset, the coalescing value */ mpt_read_ioc_pg_1(ioc); mpt_read_ioc_pg_4(ioc); } GetIoUnitPage2(ioc); } /* * Call each currently registered protocol IOC reset handler * with post-reset indication. * NOTE: If we're doing _IOC_BRINGUP, there can be no * MptResetHandlers[] registered yet. */ if (hard_reset_done) { rc = handlers = 0; for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if ((ret == 0) && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); handlers++; } if (alt_ioc_ready && MptResetHandlers[ii]) { drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } /* FIXME? Examine results here? */ } return ret;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_detect_bound_ports - Search for PCI bus/dev_function * which matches PCI bus/dev_function (+/-1) for newly discovered 929, * 929X, 1030 or 1035. * @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_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev){ struct pci_dev *peer=NULL; unsigned int slot = PCI_SLOT(pdev->devfn); unsigned int func = PCI_FUNC(pdev->devfn); MPT_ADAPTER *ioc_srch; dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x," " searching for devfn match on %x or %x\n", ioc->name, pci_name(pdev), pdev->bus->number, pdev->devfn, func-1, func+1)); peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1)); if (!peer) { peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1)); if (!peer) return; } list_for_each_entry(ioc_srch, &ioc_list, list) { struct pci_dev *_pcidev = ioc_srch->pcidev; if (_pcidev == peer) { /* 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; } } pci_dev_put(peer);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_adapter_disable - Disable misbehaving MPT adapter. * @this: Pointer to MPT adapter structure */static voidmpt_adapter_disable(MPT_ADAPTER *ioc){ int sz; int ret; if (ioc->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", ret); } } /* Disable adapter interrupts! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); if (ioc->alloc != NULL) { sz = ioc->alloc_sz; dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n", ioc->name, ioc->alloc, ioc->alloc_sz)); pci_free_consistent(ioc->pcidev, sz, ioc->alloc, ioc->alloc_dma); ioc->reply_frames = NULL; ioc->req_frames = NULL; ioc->alloc = NULL; ioc->alloc_total -= sz; } if (ioc->sense_buf_pool != NULL) { sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); pci_free_consistent(ioc->pcidev, sz, ioc->sense_buf_pool, ioc->sense_buf_pool_dma); ioc->sense_buf_pool = NULL; ioc->alloc_total -= sz; } if (ioc->events != NULL){ sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); kfree(ioc->events); ioc->events = NULL; ioc->alloc_total -= sz; } if (ioc->cached_fw != NULL) { sz = ioc->facts.FWImageSize; pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); ioc->cached_fw = NULL; ioc->alloc_total -= sz; } kfree(ioc->spi_data.nvram); kfree(ioc->raid_data.pIocPg3); ioc->spi_data.nvram = NULL; ioc->raid_data.pIocPg3 = NULL; if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; pci_free_consistent(ioc->pcidev, sz, ioc->spi_data.pIocPg4, ioc->spi_data.IocPg4_dma); ioc->spi_data.pIocPg4 = NULL; ioc->alloc_total -= sz; } if (ioc->ReqToChain != NULL) { kfree(ioc->ReqToChain); kfree(ioc->RequestNB); ioc->ReqToChain = NULL; } kfree(ioc->ChainToChain); ioc->ChainToChain = NULL; if (ioc->HostPageBuffer != NULL) { if((ret = mpt_host_page_access_control(ioc, MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { printk(KERN_ERR MYNAM ": %s: host page buffers free failed (%d)!\n", __FUNCTION__, ret); } dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, ioc->HostPageBuffer, ioc->HostPageBuffer_dma); ioc->HostPageBuffer = NULL; ioc->HostPageBuffer_sz = 0; ioc->alloc_total -= ioc->HostPageBuffer_sz; }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_adapter_dispose - Free all resources associated with a MPT * adapter. * @ioc: 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 *ioc){ int sz_first, sz_last; if (ioc == NULL) return; sz_first = ioc->alloc_total; mpt_adapter_disable(ioc); if (ioc->pci_irq != -1) { free_irq(ioc->pci_irq, ioc); ioc->pci_irq = -1; } if (ioc->memmap != NULL) { iounmap(ioc->memmap); ioc->memmap = NULL; }#if defined(CONFIG_MTRR) && 0 if (ioc->mtrr_reg > 0) { mtrr_del(ioc->mtrr_reg, 0, 0); dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); }#endif /* Zap the adapter lookup ptr! */ list_del(&ioc->list); sz_last = ioc->alloc_total; dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); kfree(ioc);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * 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) { dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. * If PCI Peer, exit. * Else, if no fault conditions are pre
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -