📄 mptbase.c
字号:
/* 919X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) { ioc->prod_name = "LSIFC939X"; ioc->bus_type = FC; ioc->errata_flag_1064 = 1; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) { ioc->prod_name = "LSIFC949X"; ioc->bus_type = FC; ioc->errata_flag_1064 = 1; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->prod_name = "LSI53C1030"; ioc->bus_type = SCSI; /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); if (revision < C0_1030) { pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { ioc->prod_name = "LSI53C1035"; ioc->bus_type = SCSI; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { ioc->prod_name = "LSISAS1064"; ioc->bus_type = SAS; ioc->errata_flag_1064 = 1; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) { ioc->prod_name = "LSISAS1066"; ioc->bus_type = SAS; ioc->errata_flag_1064 = 1; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { ioc->prod_name = "LSISAS1068"; ioc->bus_type = SAS; ioc->errata_flag_1064 = 1; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { ioc->prod_name = "LSISAS1064E"; ioc->bus_type = SAS; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) { ioc->prod_name = "LSISAS1066E"; ioc->bus_type = SAS; } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { ioc->prod_name = "LSISAS1068E"; ioc->bus_type = SAS; } if (ioc->errata_flag_1064) pci_disable_io_access(pdev); sprintf(ioc->name, "ioc%d", ioc->id); spin_lock_init(&ioc->FreeQlock); /* Disable all! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); /* Set lookup ptr. */ list_add_tail(&ioc->list, &ioc_list); ioc->pci_irq = -1; if (pdev->irq) { r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) {#ifndef __sparc__ printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", ioc->name, pdev->irq);#else printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", ioc->name, __irq_itoa(pdev->irq));#endif list_del(&ioc->list); iounmap(mem); kfree(ioc); return -EBUSY; } ioc->pci_irq = pdev->irq; pci_set_master(pdev); /* ?? */ pci_set_drvdata(pdev, ioc);#ifndef __sparc__ dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));#else dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));#endif } /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); list_del(&ioc->list); free_irq(ioc->pci_irq, ioc); iounmap(mem); kfree(ioc); pci_set_drvdata(pdev, NULL); return r; } /* call per device driver probe entry point */ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { if(MptDeviceDriverHandlers[ii] && MptDeviceDriverHandlers[ii]->probe) { MptDeviceDriverHandlers[ii]->probe(pdev,id); } }#ifdef CONFIG_PROC_FS /* * 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; } }#endif return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_detach - Remove a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure * */voidmpt_detach(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; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { if(MptDeviceDriverHandlers[ii] && MptDeviceDriverHandlers[ii]->remove) { MptDeviceDriverHandlers[ii]->remove(pdev); } } /* Disable interrupts! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; synchronize_irq(pdev->irq); /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); CHIPREG_READ32(&ioc->chip->IntStatus); mpt_adapter_dispose(ioc); pci_set_drvdata(pdev, NULL);}/************************************************************************** * Power Management */#ifdef CONFIG_PM/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_suspend - Fusion MPT base driver suspend routine. * * */intmpt_suspend(struct pci_dev *pdev, pm_message_t state){ u32 device_state; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); device_state=pci_choose_state(pdev, state); printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); pci_save_state(pdev); /* put ioc into READY_STATE */ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { printk(MYIOC_s_ERR_FMT "pci-suspend: IOC msg unit reset failed!\n", ioc->name); } /* disable interrupts */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); pci_disable_device(pdev); pci_set_power_state(pdev, device_state); return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_resume - Fusion MPT base driver resume routine. * * */intmpt_resume(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); u32 device_state = pdev->current_state; int recovery_state; int ii; printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); pci_set_power_state(pdev, 0); pci_restore_state(pdev); pci_enable_device(pdev); /* enable interrupts */ CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->active = 1; /* F/W not running */ if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { /* enable domain validation flags */ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; } } printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), CHIPREG_READ32(&ioc->chip->Doorbell)); /* bring ioc to operational state */ if ((recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) { printk(MYIOC_s_INFO_FMT "pci-resume: Cannot recover, error:[%x]\n", ioc->name, recovery_state); } else { printk(MYIOC_s_INFO_FMT "pci-resume: success\n", ioc->name); } return 0;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mpt_do_ioc_recovery - Initialize or recover MPT adapter. * @ioc: Pointer to MPT adapter structure * @reason: Event word / reason * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * This routine performs all the steps necessary to bring the IOC * to a OPERATIONAL state. * * This routine also pre-fetches the LAN MAC address of a Fibre Channel * MPT adapter. * * Returns: * 0 for success * -1 if failed to get board READY * -2 if READY but IOCFacts Failed * -3 if READY but PrimeIOCFifos Failed * -4 if READY but IOCInit Failed */static intmpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag){ int hard_reset_done = 0; int alt_ioc_ready = 0; int hard; int rc=0; int ii; int handlers; int ret = 0; int reset_alt_ioc_active = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); /* Disable reply interrupts (also blocks FreeQ) */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; if (ioc->alt_ioc) { if (ioc->alt_ioc->active) reset_alt_ioc_active = 1; /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); ioc->alt_ioc->active = 0; } hard = 1; if (reason == MPT_HOSTEVENT_IOC_BRINGUP) hard = 0; if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { if (hard_reset_done == -4) { printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n", ioc->name); if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ 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; } } else { printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", ioc->name); } return -1; } /* hard_reset_done = 0 if a soft reset was performed * and 1 if a hard reset was performed. */ if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) alt_ioc_ready = 1; else printk(KERN_WARNING MYNAM ": alt-%s: Not ready WARNING!\n", ioc->alt_ioc->name); } for (ii=0; ii<5; ii++) { /* Get IOC facts! Allow 5 retries */ if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) break; } if (ii == 5) { dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); ret = -2; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } if (alt_ioc_ready) { if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); /* Retry - alt IOC was initialized once */ rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); } if (rc) { dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc->alt_ioc); } } /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. * If fails, continue with alt-ioc processing */ if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) ret = -3; /* May need to check/upload firmware & data here! * If fails, continue with alt-ioc processing */ if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) ret = -4;// NEW! if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", ioc->alt_ioc->name, rc); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } if (alt_ioc_ready) { if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { alt_ioc_ready = 0; reset_alt_ioc_active = 0; printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", ioc->alt_ioc->name, rc); } } if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ if (ioc->upload_fw) { ddlprintk((MYIOC_s_INFO_FMT "firmware upload required!\n", ioc->name)); /* Controller is not operational, cannot do upload */ if (ret == 0) { rc = mpt_do_upload(ioc, sleepFlag); if (rc == 0) { if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -