📄 lpfc_init.c
字号:
* any potential PRLIs to flush thru the SLI sub-system. */ msleep(50); return (0);}/************************************************************************//* *//* lpfc_hba_down_prep *//* This routine will do LPFC uninitialization before the *//* HBA is reset when bringing down the SLI Layer. This will be *//* initialized as a SLI layer callback routine. *//* This routine returns 0 on success. Any other return value *//* indicates an error. *//* *//************************************************************************/intlpfc_hba_down_prep(struct lpfc_hba * phba){ /* Disable interrupts */ writel(0, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ /* Cleanup potential discovery resources */ lpfc_els_flush_rscn(phba); lpfc_els_flush_cmd(phba); lpfc_disc_flush_list(phba); return (0);}/************************************************************************//* *//* lpfc_handle_eratt *//* This routine will handle processing a Host Attention *//* Error Status event. This will be initialized *//* as a SLI layer callback routine. *//* *//************************************************************************/voidlpfc_handle_eratt(struct lpfc_hba * phba){ struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; /* * If a reset is sent to the HBA restore PCI configuration registers. */ if ( phba->hba_state == LPFC_INIT_START ) { 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, phba->pci_cfg_value); } if (phba->work_hs & HS_FFER6) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, "%d:1301 Re-establishing Link " "Data: x%x x%x x%x\n", phba->brd_no, phba->work_hs, phba->work_status[0], phba->work_status[1]); spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_ESTABLISH_LINK; spin_unlock_irq(phba->host->host_lock); /* * Firmware stops when it triggled erratt with HS_FFER6. * That could cause the I/Os dropped by the firmware. * Error iocb (I/O) on txcmplq and let the SCSI layer * retry it after re-establishing link. */ pring = &psli->ring[psli->fcp_ring]; lpfc_sli_abort_iocb_ring(phba, pring); /* * There was a firmware error. Take the hba offline and then * attempt to restart it. */ lpfc_offline(phba); if (lpfc_online(phba) == 0) { /* Initialize the HBA */ mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); return; } } else { /* The if clause above forces this code path when the status * failure is a value other than FFER6. Do not call the offline * twice. This is the adapter hardware error path. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0457 Adapter Hardware Error " "Data: x%x x%x x%x\n", phba->brd_no, phba->work_hs, phba->work_status[0], phba->work_status[1]); lpfc_offline(phba); }}/************************************************************************//* *//* lpfc_handle_latt *//* This routine will handle processing a Host Attention *//* Link Status event. This will be initialized *//* as a SLI layer callback routine. *//* *//************************************************************************/voidlpfc_handle_latt(struct lpfc_hba * phba){ struct lpfc_sli *psli = &phba->sli; LPFC_MBOXQ_t *pmb; volatile uint32_t control; struct lpfc_dmabuf *mp; int rc = -ENOMEM; pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) goto lpfc_handle_latt_err_exit; mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!mp) goto lpfc_handle_latt_free_pmb; mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); if (!mp->virt) goto lpfc_handle_latt_free_mp; rc = -EIO; psli->slistat.link_event++; lpfc_read_la(phba, pmb, mp); pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) goto lpfc_handle_latt_free_mp; /* Clear Link Attention in HA REG */ spin_lock_irq(phba->host->host_lock); writel(HA_LATT, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock); return;lpfc_handle_latt_free_mp: kfree(mp);lpfc_handle_latt_free_pmb: kfree(pmb);lpfc_handle_latt_err_exit: /* Enable Link attention interrupts */ spin_lock_irq(phba->host->host_lock); psli->sli_flag |= LPFC_PROCESS_LA; control = readl(phba->HCregaddr); control |= HC_LAINT_ENA; writel(control, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ /* Clear Link Attention in HA REG */ writel(HA_LATT, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock); lpfc_linkdown(phba); phba->hba_state = LPFC_HBA_ERROR; /* The other case is an error from issue_mbox */ if (rc == -ENOMEM) lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, "%d:0300 READ_LA: no buffers\n", phba->brd_no); return;}/************************************************************************//* *//* lpfc_parse_vpd *//* This routine will parse the VPD data *//* *//************************************************************************/static intlpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd){ uint8_t lenlo, lenhi; uint32_t Length; int i, j; int finished = 0; int index = 0; if (!vpd) return 0; /* Vital Product */ lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0455 Vital Product Data: x%x x%x x%x x%x\n", phba->brd_no, (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[3]); do { switch (vpd[index]) { case 0x82: index += 1; lenlo = vpd[index]; index += 1; lenhi = vpd[index]; index += 1; i = ((((unsigned short)lenhi) << 8) + lenlo); index += i; break; case 0x90: index += 1; lenlo = vpd[index]; index += 1; lenhi = vpd[index]; index += 1; Length = ((((unsigned short)lenhi) << 8) + lenlo); while (Length > 0) { /* Look for Serial Number */ if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) { index += 2; i = vpd[index]; index += 1; j = 0; Length -= (3+i); while(i--) { phba->SerialNumber[j++] = vpd[index++]; if (j == 31) break; } phba->SerialNumber[j] = 0; continue; } else if ((vpd[index] == 'V') && (vpd[index+1] == '1')) { phba->vpd_flag |= VPD_MODEL_DESC; index += 2; i = vpd[index]; index += 1; j = 0; Length -= (3+i); while(i--) { phba->ModelDesc[j++] = vpd[index++]; if (j == 255) break; } phba->ModelDesc[j] = 0; continue; } else if ((vpd[index] == 'V') && (vpd[index+1] == '2')) { phba->vpd_flag |= VPD_MODEL_NAME; index += 2; i = vpd[index]; index += 1; j = 0; Length -= (3+i); while(i--) { phba->ModelName[j++] = vpd[index++]; if (j == 79) break; } phba->ModelName[j] = 0; continue; } else if ((vpd[index] == 'V') && (vpd[index+1] == '3')) { phba->vpd_flag |= VPD_PROGRAM_TYPE; index += 2; i = vpd[index]; index += 1; j = 0; Length -= (3+i); while(i--) { phba->ProgramType[j++] = vpd[index++]; if (j == 255) break; } phba->ProgramType[j] = 0; continue; } else if ((vpd[index] == 'V') && (vpd[index+1] == '4')) { phba->vpd_flag |= VPD_PORT; index += 2; i = vpd[index]; index += 1; j = 0; Length -= (3+i); while(i--) { phba->Port[j++] = vpd[index++]; if (j == 19) break; } phba->Port[j] = 0; continue; } else { index += 2; i = vpd[index]; index += 1; index += i; Length -= (3 + i); } } finished = 0; break; case 0x78: finished = 1; break; default: index ++; break; } } while (!finished && (index < 108)); return(1);}static voidlpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp){ lpfc_vpd_t *vp; uint32_t id; uint8_t hdrtype; char str[16]; vp = &phba->vpd; pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id); pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); switch ((id >> 16) & 0xffff) { case PCI_DEVICE_ID_FIREFLY: strcpy(str, "LP6000 1"); break; case PCI_DEVICE_ID_SUPERFLY: if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) strcpy(str, "LP7000 1"); else strcpy(str, "LP7000E 1"); break; case PCI_DEVICE_ID_DRAGONFLY: strcpy(str, "LP8000 1"); break; case PCI_DEVICE_ID_CENTAUR: if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) strcpy(str, "LP9002 2"); else strcpy(str, "LP9000 1"); break; case PCI_DEVICE_ID_RFLY: strcpy(str, "LP952 2"); break; case PCI_DEVICE_ID_PEGASUS: strcpy(str, "LP9802 2"); break; case PCI_DEVICE_ID_THOR: if (hdrtype == 0x80) strcpy(str, "LP10000DC 2"); else strcpy(str, "LP10000 2"); break; case PCI_DEVICE_ID_VIPER: strcpy(str, "LPX1000 10"); break; case PCI_DEVICE_ID_PFLY: strcpy(str, "LP982 2"); break; case PCI_DEVICE_ID_TFLY: if (hdrtype == 0x80) strcpy(str, "LP1050DC 2"); else strcpy(str, "LP1050 2"); break; case PCI_DEVICE_ID_HELIOS: if (hdrtype == 0x80) strcpy(str, "LP11002 4"); else strcpy(str, "LP11000 4"); break; case PCI_DEVICE_ID_BMID: strcpy(str, "LP1150 4"); break; case PCI_DEVICE_ID_BSMB: strcpy(str, "LP111 4"); break; case PCI_DEVICE_ID_ZEPHYR: if (hdrtype == 0x80) strcpy(str, "LPe11002 4"); else strcpy(str, "LPe11000 4"); break; case PCI_DEVICE_ID_ZMID: strcpy(str, "LPe1150 4"); break; case PCI_DEVICE_ID_ZSMB: strcpy(str, "LPe111 4"); break; case PCI_DEVICE_ID_LP101: strcpy(str, "LP101 2"); break; case PCI_DEVICE_ID_LP10000S: strcpy(str, "LP10000-S 2"); break; default: memset(str, 0, 16); break; } if (mdp) sscanf(str, "%s", mdp); if (descp) sprintf(descp, "Emulex LightPulse %s Gigabit PCI Fibre " "Channel Adapter", str);}/**************************************************//* lpfc_post_buffer *//* *//* This routine will post count buffers to the *//* ring with the QUE_RING_BUF_CN command. This *//* allows 3 buffers / command to be posted. *//* Returns the number of buffers NOT posted. *//**************************************************/intlpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, int type){ IOCB_t *icmd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -