lpfc_init.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,888 行 · 第 1/4 页

C
1,888
字号
	struct lpfc_sli *psli = &phba->sli;	struct lpfc_sli_ring *pring;	struct lpfc_dmabuf *mp, *next_mp;	int i;	/* Cleanup preposted buffers on the ELS ring */	pring = &psli->ring[LPFC_ELS_RING];	list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {		list_del(&mp->list);		pring->postbufq_cnt--;		lpfc_mbuf_free(phba, mp->virt, mp->phys);		kfree(mp);	}	for (i = 0; i < psli->num_rings; i++) {		pring = &psli->ring[i];		lpfc_sli_abort_iocb_ring(phba, pring);	}	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 (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;		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;		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);		lpfc_sli_brdrestart(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]);		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;		lpfc_offline(phba);		phba->hba_state = LPFC_HBA_ERROR;		lpfc_hba_down_post(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, int len){	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]);	while (!finished && (index < (len - 4))) {		switch (vpd[index]) {		case 0x82:		case 0x91:			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);			if (Length > len - index)				Length = len - index;			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;		}	}	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;	int max_speed;	char * ports;	struct {		char * name;		int    max_speed;		char * ports;		char * bus;	} m = {"<Unknown>", 0, "", ""};	pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);	ports = (hdrtype == 0x80) ? "2-port " : "";	if (mdp && mdp[0] != '\0'		&& descp && descp[0] != '\0')		return;	if (phba->lmt & LMT_10Gb)		max_speed = 10;	else if (phba->lmt & LMT_8Gb)		max_speed = 8;	else if (phba->lmt & LMT_4Gb)		max_speed = 4;	else if (phba->lmt & LMT_2Gb)		max_speed = 2;	else		max_speed = 1;	vp = &phba->vpd;	switch (dev_id) {	case PCI_DEVICE_ID_FIREFLY:		m = (typeof(m)){"LP6000", max_speed, "", "PCI"};		break;	case PCI_DEVICE_ID_SUPERFLY:		if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)			m = (typeof(m)){"LP7000", max_speed, "", "PCI"};		else			m = (typeof(m)){"LP7000E", max_speed, "", "PCI"};		break;	case PCI_DEVICE_ID_DRAGONFLY:		m = (typeof(m)){"LP8000", max_speed, "", "PCI"};		break;	case PCI_DEVICE_ID_CENTAUR:		if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)			m = (typeof(m)){"LP9002", max_speed, "", "PCI"};		else			m = (typeof(m)){"LP9000", max_speed, "", "PCI"};		break;	case PCI_DEVICE_ID_RFLY:		m = (typeof(m)){"LP952", max_speed, "", "PCI"};		break;	case PCI_DEVICE_ID_PEGASUS:		m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"};		break;	case PCI_DEVICE_ID_THOR:		if (hdrtype == 0x80)			m = (typeof(m)){"LP10000DC",					max_speed, ports, "PCI-X"};		else			m = (typeof(m)){"LP10000",					max_speed, ports, "PCI-X"};		break;	case PCI_DEVICE_ID_VIPER:		m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"};		break;	case PCI_DEVICE_ID_PFLY:		m = (typeof(m)){"LP982", max_speed, "", "PCI-X"};		break;	case PCI_DEVICE_ID_TFLY:		if (hdrtype == 0x80)			m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"};		else			m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"};		break;	case PCI_DEVICE_ID_HELIOS:		if (hdrtype == 0x80)			m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"};		else			m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"};		break;	case PCI_DEVICE_ID_HELIOS_SCSP:		m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"};		break;	case PCI_DEVICE_ID_HELIOS_DCSP:		m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"};		break;	case PCI_DEVICE_ID_NEPTUNE:		if (hdrtype == 0x80)			m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"};		else			m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_NEPTUNE_SCSP:		m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_NEPTUNE_DCSP:		m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_BMID:		m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"};		break;	case PCI_DEVICE_ID_BSMB:		m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"};		break;	case PCI_DEVICE_ID_ZEPHYR:		if (hdrtype == 0x80)			m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"};		else			m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_ZEPHYR_SCSP:		m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_ZEPHYR_DCSP:		m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_ZMID:		m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_ZSMB:		m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"};		break;	case PCI_DEVICE_ID_LP101:		m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"};		break;	case PCI_DEVICE_ID_LP10000S:		m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"};		break;	case PCI_DEVICE_ID_LP11000S:	case PCI_DEVICE_ID_LPE11000S:		switch (dev_subid) {		case PCI_SUBSYSTEM_ID_LP11000S:			m = (typeof(m)){"LP11000-S", max_speed,					ports, "PCI-X2"};			break;		case PCI_SUBSYSTEM_ID_LP11002S:			m = (typeof(m)){"LP11002-S", max_speed,					ports, "PCI-X2"};			break;		case PCI_SUBSYSTEM_ID_LPE11000S:			m = (typeof(m)){"LPe11000-S", max_speed,					ports, "PCIe"};			break;		case PCI_SUBSYSTEM_ID_LPE11002S:			m = (typeof(m)){"LPe11002-S", max_speed,					ports, "PCIe"};			break;		case PCI_SUBSYSTEM_ID_LPE11010S:			m = (typeof(m)){"LPe11010-S", max_speed,					"10-port ", "PCIe"};			break;		default:			m = (typeof(m)){ 0 };			break;		}

⌨️ 快捷键说明

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