lpfc_sli.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,535 行 · 第 1/5 页
C
2,535 行
return errcnt;}intlpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask){ uint32_t status; int i = 0; int retval = 0; /* Read the HBA Host Status Register */ status = readl(phba->HSregaddr); /* * Check status register every 100ms for 5 retries, then every * 500ms for 5, then every 2.5 sec for 5, then reset board and * every 2.5 sec for 4. * Break our of the loop if errors occurred during init. */ while (((status & mask) != mask) && !(status & HS_FFERM) && i++ < 20) { if (i <= 5) msleep(10); else if (i <= 10) msleep(500); else msleep(2500); if (i == 15) { phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */ lpfc_sli_brdrestart(phba); } /* Read the HBA Host Status Register */ status = readl(phba->HSregaddr); } /* Check to see if any errors occurred during init */ if ((status & HS_FFERM) || (i >= 20)) { phba->hba_state = LPFC_HBA_ERROR; retval = 1; } return retval;}#define BARRIER_TEST_PATTERN (0xdeadbeef)void lpfc_reset_barrier(struct lpfc_hba * phba){ uint32_t * resp_buf; uint32_t * mbox_buf; volatile uint32_t mbox; uint32_t hc_copy; int i; uint8_t hdrtype; pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); if (hdrtype != 0x80 || (FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID && FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID)) return; /* * Tell the other part of the chip to suspend temporarily all * its DMA activity. */ resp_buf = (uint32_t *)phba->MBslimaddr; /* Disable the error attention */ hc_copy = readl(phba->HCregaddr); writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr); readl(phba->HCregaddr); /* flush */ if (readl(phba->HAregaddr) & HA_ERATT) { /* Clear Chip error bit */ writel(HA_ERATT, phba->HAregaddr); phba->stopped = 1; } mbox = 0; ((MAILBOX_t *)&mbox)->mbxCommand = MBX_KILL_BOARD; ((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP; writel(BARRIER_TEST_PATTERN, (resp_buf + 1)); mbox_buf = (uint32_t *)phba->MBslimaddr; writel(mbox, mbox_buf); for (i = 0; readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++) mdelay(1); if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) { if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE || phba->stopped) goto restore_hc; else goto clear_errat; } ((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST; for (i = 0; readl(resp_buf) != mbox && i < 500; i++) mdelay(1);clear_errat: while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500) mdelay(1); if (readl(phba->HAregaddr) & HA_ERATT) { writel(HA_ERATT, phba->HAregaddr); phba->stopped = 1; }restore_hc: writel(hc_copy, phba->HCregaddr); readl(phba->HCregaddr); /* flush */}intlpfc_sli_brdkill(struct lpfc_hba * phba){ struct lpfc_sli *psli; LPFC_MBOXQ_t *pmb; uint32_t status; uint32_t ha_copy; int retval; int i = 0; psli = &phba->sli; /* Kill HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "%d:0329 Kill HBA Data: x%x x%x\n", phba->brd_no, phba->hba_state, psli->sli_flag); if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) == 0) return 1; /* Disable the error attention */ spin_lock_irq(phba->host->host_lock); status = readl(phba->HCregaddr); status &= ~HC_ERINT_ENA; writel(status, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock); lpfc_kill_board(phba, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); if (retval != MBX_SUCCESS) { if (retval != MBX_BUSY) mempool_free(pmb, phba->mbox_mem_pool); return 1; } psli->sli_flag &= ~LPFC_SLI2_ACTIVE; mempool_free(pmb, phba->mbox_mem_pool); /* There is no completion for a KILL_BOARD mbox cmd. Check for an error * attention every 100ms for 3 seconds. If we don't get ERATT after * 3 seconds we still set HBA_ERROR state because the status of the * board is now undefined. */ ha_copy = readl(phba->HAregaddr); while ((i++ < 30) && !(ha_copy & HA_ERATT)) { mdelay(100); ha_copy = readl(phba->HAregaddr); } del_timer_sync(&psli->mbox_tmo); if (ha_copy & HA_ERATT) { writel(HA_ERATT, phba->HAregaddr); phba->stopped = 1; } spin_lock_irq(phba->host->host_lock); psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irq(phba->host->host_lock); psli->mbox_active = NULL; lpfc_hba_down_post(phba); phba->hba_state = LPFC_HBA_ERROR; return (ha_copy & HA_ERATT ? 0 : 1);}intlpfc_sli_brdreset(struct lpfc_hba * phba){ struct lpfc_sli *psli; struct lpfc_sli_ring *pring; uint16_t cfg_value; int i; psli = &phba->sli; /* Reset HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no, phba->hba_state, psli->sli_flag); /* perform board reset */ phba->fc_eventTag = 0; phba->fc_myDID = 0; phba->fc_prevDID = 0; psli->sli_flag = 0; /* Turn off parity checking and serr during the physical reset */ pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value & ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; /* Now toggle INITFF bit in the Host Control Register */ writel(HC_INITFF, phba->HCregaddr); mdelay(1); readl(phba->HCregaddr); /* flush */ writel(0, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ /* Restore PCI cmd register */ pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value); /* Initialize relevant SLI info */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; pring->flag = 0; pring->rspidx = 0; pring->next_cmdidx = 0; pring->local_getidx = 0; pring->cmdidx = 0; pring->missbufcnt = 0; } phba->hba_state = LPFC_WARM_START; return 0;}intlpfc_sli_brdrestart(struct lpfc_hba * phba){ MAILBOX_t *mb; struct lpfc_sli *psli; uint16_t skip_post; volatile uint32_t word0; void __iomem *to_slim; spin_lock_irq(phba->host->host_lock); psli = &phba->sli; /* Restart HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no, phba->hba_state, psli->sli_flag); word0 = 0; mb = (MAILBOX_t *) &word0; mb->mbxCommand = MBX_RESTART; mb->mbxHc = 1; lpfc_reset_barrier(phba); to_slim = phba->MBslimaddr; writel(*(uint32_t *) mb, to_slim); readl(to_slim); /* flush */ /* Only skip post after fc_ffinit is completed */ if (phba->hba_state) { skip_post = 1; word0 = 1; /* This is really setting up word1 */ } else { skip_post = 0; word0 = 0; /* This is really setting up word1 */ } to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t); writel(*(uint32_t *) mb, to_slim); readl(to_slim); /* flush */ lpfc_sli_brdreset(phba); phba->stopped = 0; phba->hba_state = LPFC_INIT_START; spin_unlock_irq(phba->host->host_lock); if (skip_post) mdelay(100); else mdelay(2000); lpfc_hba_down_post(phba); return 0;}static intlpfc_sli_chipset_init(struct lpfc_hba *phba){ uint32_t status, i = 0; /* Read the HBA Host Status Register */ status = readl(phba->HSregaddr); /* Check status register to see what current state is */ i = 0; while ((status & (HS_FFRDY | HS_MBRDY)) != (HS_FFRDY | HS_MBRDY)) { /* Check every 100ms for 5 retries, then every 500ms for 5, then * every 2.5 sec for 5, then reset board and every 2.5 sec for * 4. */ if (i++ >= 20) { /* Adapter failed to init, timeout, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0436 Adapter failed to init, " "timeout, status reg x%x\n", phba->brd_no, status); phba->hba_state = LPFC_HBA_ERROR; return -ETIMEDOUT; } /* Check to see if any errors occurred during init */ if (status & HS_FFERM) { /* ERROR: During chipset initialization */ /* Adapter failed to init, chipset, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0437 Adapter failed to init, " "chipset, status reg x%x\n", phba->brd_no, status); phba->hba_state = LPFC_HBA_ERROR; return -EIO; } if (i <= 5) { msleep(10); } else if (i <= 10) { msleep(500); } else { msleep(2500); } if (i == 15) { phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */ lpfc_sli_brdrestart(phba); } /* Read the HBA Host Status Register */ status = readl(phba->HSregaddr); } /* Check to see if any errors occurred during init */ if (status & HS_FFERM) { /* ERROR: During chipset initialization */ /* Adapter failed to init, chipset, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0438 Adapter failed to init, chipset, " "status reg x%x\n", phba->brd_no, status); phba->hba_state = LPFC_HBA_ERROR; return -EIO; } /* Clear all interrupt enable conditions */ writel(0, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ /* setup host attn register */ writel(0xffffffff, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ return 0;}intlpfc_sli_hba_setup(struct lpfc_hba * phba){ LPFC_MBOXQ_t *pmb; uint32_t resetcount = 0, rc = 0, done = 0; pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { phba->hba_state = LPFC_HBA_ERROR; return -ENOMEM; } while (resetcount < 2 && !done) { phba->hba_state = LPFC_STATE_UNKNOWN; lpfc_sli_brdrestart(phba); msleep(2500); rc = lpfc_sli_chipset_init(phba); if (rc) break; resetcount++; /* Call pre CONFIG_PORT mailbox command initialization. A value of 0 * means the call was successful. Any other nonzero value is a failure, * but if ERESTART is returned, the driver may reset the HBA and try * again. */ rc = lpfc_config_port_prep(phba); if (rc == -ERESTART) { phba->hba_state = 0; continue; } else if (rc) { break; } phba->hba_state = LPFC_INIT_MBX_CMDS; lpfc_config_port(phba, pmb); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc == MBX_SUCCESS) done = 1; else { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0442 Adapter failed to init, mbxCmd x%x " "CONFIG_PORT, mbxStatus x%x Data: x%x\n", phba->brd_no, pmb->mb.mbxCommand, pmb->mb.mbxStatus, 0); phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; } } if (!done) goto lpfc_sli_hba_setup_error; rc = lpfc_sli_ring_map(phba, pmb); if (rc) goto lpfc_sli_hba_setup_error; phba->sli.sli_flag |= LPFC_PROCESS_LA; rc = lpfc_config_port_post(phba); if (rc) goto lpfc_sli_hba_setup_error; goto lpfc_sli_hba_setup_exit;lpfc_sli_hba_setup_error: phba->hba_state = LPFC_HBA_ERROR;lpfc_sli_hba_setup_exit: mempool_free(pmb, phba->mbox_mem_pool); return rc;}static voidlpfc_mbox_abort(struct lpfc_hba * phba){ LPFC_MBOXQ_t *pmbox; MAILBOX_t *mb; if (phba->sli.mbox_active) { del_timer_sync(&phba->sli.mbox_tmo); phba->work_hba_events &= ~WORKER_MBOX_TMO; pmbox = phba->sli.mbox_active; mb = &pmbox->mb; phba->sli.mbox_active = NULL; if (pmbox->mbox_cmpl) { mb->mbxStatus = MBX_NOT_FINISHED; (pmbox->mbox_cmpl) (phba, pmbox); } phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; } /* Abort all the non active mailbox commands. */ spin_lock_irq(phba->host->host_lock); pmbox = lpfc_mbox_get(phba); while (pmbox) { mb = &pmbox->mb; if (pmbox->mbox_cmpl) { mb->mbxStatus = MBX_NOT_FINISHED; spin_unlock_irq(phba->host->host_lock); (pmbox->mbox_cmpl) (phba, pmbox); spin_lock_irq(phba->host->host_lock); } pmbox = lpfc_mbox_get(phba); } spin_unlock_irq(phba->host->host_lock); return;}/*! lpfc_mbox_timeout * * \pre * \post * \param hba Pointer to per struct lpfc_hba structure * \param l1 Pointer to the driver's mailbox queue. * \return
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?