lpfc_init.c

来自「linux2.6.16版本」· C语言 代码 · 共 1,815 行 · 第 1/4 页

C
1,815
字号
	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;	/* Cleanup any outstanding ELS commands */	lpfc_els_flush_cmd(phba);	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;	uint16_t dev_id = phba->pcidev->device;	uint16_t dev_subid = phba->pcidev->subsystem_device;	uint8_t hdrtype = phba->pcidev->hdr_type;	char *model_str = "";	vp = &phba->vpd;	switch (dev_id) {	case PCI_DEVICE_ID_FIREFLY:		model_str = "LP6000 1Gb PCI";		break;	case PCI_DEVICE_ID_SUPERFLY:		if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)			model_str = "LP7000 1Gb PCI";		else			model_str = "LP7000E 1Gb PCI";		break;	case PCI_DEVICE_ID_DRAGONFLY:		model_str = "LP8000 1Gb PCI";		break;	case PCI_DEVICE_ID_CENTAUR:		if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)			model_str = "LP9002 2Gb PCI";		else			model_str = "LP9000 1Gb PCI";		break;	case PCI_DEVICE_ID_RFLY:		model_str = "LP952 2Gb PCI";		break;	case PCI_DEVICE_ID_PEGASUS:		model_str = "LP9802 2Gb PCI-X";		break;	case PCI_DEVICE_ID_THOR:		if (hdrtype == 0x80)			model_str = "LP10000DC 2Gb 2-port PCI-X";		else			model_str = "LP10000 2Gb PCI-X";		break;	case PCI_DEVICE_ID_VIPER:		model_str = "LPX1000 10Gb PCI-X";		break;	case PCI_DEVICE_ID_PFLY:		model_str = "LP982 2Gb PCI-X";		break;	case PCI_DEVICE_ID_TFLY:		if (hdrtype == 0x80)			model_str = "LP1050DC 2Gb 2-port PCI-X";		else			model_str = "LP1050 2Gb PCI-X";		break;	case PCI_DEVICE_ID_HELIOS:		if (hdrtype == 0x80)			model_str = "LP11002 4Gb 2-port PCI-X2";		else			model_str = "LP11000 4Gb PCI-X2";		break;	case PCI_DEVICE_ID_HELIOS_SCSP:		model_str = "LP11000-SP 4Gb PCI-X2";		break;	case PCI_DEVICE_ID_HELIOS_DCSP:		model_str = "LP11002-SP 4Gb 2-port PCI-X2";		break;	case PCI_DEVICE_ID_NEPTUNE:		if (hdrtype == 0x80)			model_str = "LPe1002 4Gb 2-port";		else			model_str = "LPe1000 4Gb PCIe";		break;	case PCI_DEVICE_ID_NEPTUNE_SCSP:		model_str = "LPe1000-SP 4Gb PCIe";		break;	case PCI_DEVICE_ID_NEPTUNE_DCSP:		model_str = "LPe1002-SP 4Gb 2-port PCIe";		break;	case PCI_DEVICE_ID_BMID:		model_str = "LP1150 4Gb PCI-X2";		break;	case PCI_DEVICE_ID_BSMB:		model_str = "LP111 4Gb PCI-X2";		break;	case PCI_DEVICE_ID_ZEPHYR:		if (hdrtype == 0x80)			model_str = "LPe11002 4Gb 2-port PCIe";		else			model_str = "LPe11000 4Gb PCIe";		break;	case PCI_DEVICE_ID_ZEPHYR_SCSP:		model_str = "LPe11000-SP 4Gb PCIe";		break;	case PCI_DEVICE_ID_ZEPHYR_DCSP:		model_str = "LPe11002-SP 4Gb 2-port PCIe";		break;	case PCI_DEVICE_ID_ZMID:		model_str = "LPe1150 4Gb PCIe";		break;	case PCI_DEVICE_ID_ZSMB:		model_str = "LPe111 4Gb PCIe";		break;	case PCI_DEVICE_ID_LP101:		model_str = "LP101 2Gb PCI-X";		break;	case PCI_DEVICE_ID_LP10000S:		model_str = "LP10000-S 2Gb PCI";		break;	case PCI_DEVICE_ID_LP11000S:	case PCI_DEVICE_ID_LPE11000S:		switch (dev_subid) {		case PCI_SUBSYSTEM_ID_LP11000S:			model_str = "LP11002-S 4Gb PCI-X2";			break;		case PCI_SUBSYSTEM_ID_LP11002S:			model_str = "LP11000-S 4Gb 2-port PCI-X2";			break;		case PCI_SUBSYSTEM_ID_LPE11000S:			model_str = "LPe11002-S 4Gb PCIe";			break;		case PCI_SUBSYSTEM_ID_LPE11002S:			model_str = "LPe11002-S 4Gb 2-port PCIe";			break;		case PCI_SUBSYSTEM_ID_LPE11010S:			model_str = "LPe11010-S 4Gb 10-port PCIe";			break;		default:			break;		}		break;	default:		break;	}	if (mdp)		sscanf(model_str, "%s", mdp);	if (descp)		sprintf(descp, "Emulex %s Fibre Channel Adapter", model_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.    *//**************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?