diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 213 | 
1 files changed, 135 insertions, 78 deletions
| diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 774663e8e1f..cd9697edf86 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2566,7 +2566,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)  	shost->max_cmd_len = 16;  	if (phba->sli_rev == LPFC_SLI_REV4) {  		shost->dma_boundary = -			phba->sli4_hba.pc_sli4_params.sge_supp_len; +			phba->sli4_hba.pc_sli4_params.sge_supp_len-1;  		shost->sg_tablesize = phba->cfg_sg_seg_cnt;  	} @@ -2600,15 +2600,6 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)  	init_timer(&vport->els_tmofunc);  	vport->els_tmofunc.function = lpfc_els_timeout;  	vport->els_tmofunc.data = (unsigned long)vport; -	if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) { -		phba->menlo_flag |= HBA_MENLO_SUPPORT; -		/* check for menlo minimum sg count */ -		if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT) { -			phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT; -			shost->sg_tablesize = phba->cfg_sg_seg_cnt; -		} -	} -  	error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);  	if (error)  		goto out_put_shost; @@ -3236,12 +3227,26 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)  	if (!vport)  		return NULL; -	ndlp = lpfc_findnode_did(vport, Fabric_DID); -	if (!ndlp) -		return NULL;  	phba = vport->phba;  	if (!phba)  		return NULL; +	ndlp = lpfc_findnode_did(vport, Fabric_DID); +	if (!ndlp) { +		/* Cannot find existing Fabric ndlp, so allocate a new one */ +		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); +		if (!ndlp) +			return 0; +		lpfc_nlp_init(vport, ndlp, Fabric_DID); +		/* Set the node type */ +		ndlp->nlp_type |= NLP_FABRIC; +		/* Put ndlp onto node list */ +		lpfc_enqueue_node(vport, ndlp); +	} else if (!NLP_CHK_NODE_ACT(ndlp)) { +		/* re-setup ndlp without removing from node list */ +		ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); +		if (!ndlp) +			return 0; +	}  	if (phba->pport->port_state <= LPFC_FLOGI)  		return NULL;  	/* If virtual link is not yet instantiated ignore CVL */ @@ -3304,11 +3309,20 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,  	switch (event_type) {  	case LPFC_FCOE_EVENT_TYPE_NEW_FCF:  	case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD: -		lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, -			"2546 New FCF found/FCF parameter modified event: " -			"evt_tag:x%x, fcf_index:x%x\n", -			acqe_fcoe->event_tag, acqe_fcoe->index); - +		if (event_type == LPFC_FCOE_EVENT_TYPE_NEW_FCF) +			lpfc_printf_log(phba, KERN_ERR, LOG_FIP | +					LOG_DISCOVERY, +					"2546 New FCF found event: " +					"evt_tag:x%x, fcf_index:x%x\n", +					acqe_fcoe->event_tag, +					acqe_fcoe->index); +		else +			lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | +					LOG_DISCOVERY, +					"2788 FCF parameter modified event: " +					"evt_tag:x%x, fcf_index:x%x\n", +					acqe_fcoe->event_tag, +					acqe_fcoe->index);  		spin_lock_irq(&phba->hbalock);  		if ((phba->fcf.fcf_flag & FCF_SCAN_DONE) ||  		    (phba->hba_flag & FCF_DISC_INPROGRESS)) { @@ -3517,6 +3531,32 @@ lpfc_sli4_async_dcbx_evt(struct lpfc_hba *phba,  }  /** + * lpfc_sli4_async_grp5_evt - Process the asynchronous group5 event + * @phba: pointer to lpfc hba data structure. + * @acqe_link: pointer to the async grp5 completion queue entry. + * + * This routine is to handle the SLI4 asynchronous grp5 event. A grp5 event + * is an asynchronous notified of a logical link speed change.  The Port + * reports the logical link speed in units of 10Mbps. + **/ +static void +lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba, +			 struct lpfc_acqe_grp5 *acqe_grp5) +{ +	uint16_t prev_ll_spd; + +	phba->fc_eventTag = acqe_grp5->event_tag; +	phba->fcoe_eventtag = acqe_grp5->event_tag; +	prev_ll_spd = phba->sli4_hba.link_state.logical_speed; +	phba->sli4_hba.link_state.logical_speed = +		(bf_get(lpfc_acqe_grp5_llink_spd, acqe_grp5)); +	lpfc_printf_log(phba, KERN_INFO, LOG_SLI, +			"2789 GRP5 Async Event: Updating logical link speed " +			"from %dMbps to %dMbps\n", (prev_ll_spd * 10), +			(phba->sli4_hba.link_state.logical_speed*10)); +} + +/**   * lpfc_sli4_async_event_proc - Process all the pending asynchronous event   * @phba: pointer to lpfc hba data structure.   * @@ -3552,6 +3592,10 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)  			lpfc_sli4_async_dcbx_evt(phba,  						 &cq_event->cqe.acqe_dcbx);  			break; +		case LPFC_TRAILER_CODE_GRP5: +			lpfc_sli4_async_grp5_evt(phba, +						 &cq_event->cqe.acqe_grp5); +			break;  		default:  			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,  					"1804 Invalid asynchrous event code: " @@ -3813,6 +3857,13 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)  	/* Get all the module params for configuring this host */  	lpfc_get_cfgparam(phba); +	if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) { +		phba->menlo_flag |= HBA_MENLO_SUPPORT; +		/* check for menlo minimum sg count */ +		if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT) +			phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT; +	} +  	/*  	 * Since the sg_tablesize is module parameter, the sg_dma_buf_size  	 * used to create the sg_dma_buf_pool must be dynamically calculated. @@ -4030,6 +4081,43 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)  	if (unlikely(rc))  		goto out_free_bsmbx; +	mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, +						       GFP_KERNEL); +	if (!mboxq) { +		rc = -ENOMEM; +		goto out_free_bsmbx; +	} + +	/* Get the Supported Pages. It is always available. */ +	lpfc_supported_pages(mboxq); +	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); +	if (unlikely(rc)) { +		rc = -EIO; +		mempool_free(mboxq, phba->mbox_mem_pool); +		goto out_free_bsmbx; +	} + +	mqe = &mboxq->u.mqe; +	memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3), +	       LPFC_MAX_SUPPORTED_PAGES); +	for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) { +		switch (pn_page[i]) { +		case LPFC_SLI4_PARAMETERS: +			phba->sli4_hba.pc_sli4_params.supported = 1; +			break; +		default: +			break; +		} +	} + +	/* Read the port's SLI4 Parameters capabilities if supported. */ +	if (phba->sli4_hba.pc_sli4_params.supported) +		rc = lpfc_pc_sli4_params_get(phba, mboxq); +	mempool_free(mboxq, phba->mbox_mem_pool); +	if (rc) { +		rc = -EIO; +		goto out_free_bsmbx; +	}  	/* Create all the SLI4 queues */  	rc = lpfc_sli4_queue_create(phba);  	if (rc) @@ -4090,43 +4178,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)  		goto out_free_fcp_eq_hdl;  	} -	mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, -						       GFP_KERNEL); -	if (!mboxq) { -		rc = -ENOMEM; -		goto out_free_fcp_eq_hdl; -	} - -	/* Get the Supported Pages. It is always available. */ -	lpfc_supported_pages(mboxq); -	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); -	if (unlikely(rc)) { -		rc = -EIO; -		mempool_free(mboxq, phba->mbox_mem_pool); -		goto out_free_fcp_eq_hdl; -	} - -	mqe = &mboxq->u.mqe; -	memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3), -	       LPFC_MAX_SUPPORTED_PAGES); -	for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) { -		switch (pn_page[i]) { -		case LPFC_SLI4_PARAMETERS: -			phba->sli4_hba.pc_sli4_params.supported = 1; -			break; -		default: -			break; -		} -	} - -	/* Read the port's SLI4 Parameters capabilities if supported. */ -	if (phba->sli4_hba.pc_sli4_params.supported) -		rc = lpfc_pc_sli4_params_get(phba, mboxq); -	mempool_free(mboxq, phba->mbox_mem_pool); -	if (rc) { -		rc = -EIO; -		goto out_free_fcp_eq_hdl; -	}  	return rc;  out_free_fcp_eq_hdl: @@ -5050,6 +5101,8 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)  	memset(phba->slim2p.virt, 0, SLI2_SLIM_SIZE);  	phba->mbox = phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, mbx); +	phba->mbox_ext = (phba->slim2p.virt + +		offsetof(struct lpfc_sli2_slim, mbx_ext_words));  	phba->pcb = (phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, pcb));  	phba->IOCBs = (phba->slim2p.virt +  		       offsetof(struct lpfc_sli2_slim, IOCBs)); @@ -7753,21 +7806,23 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)   * @phba: pointer to lpfc hba data structure.   *   * This routine is called to prepare the SLI3 device for PCI slot recover. It - * aborts and stops all the on-going I/Os on the pci device. + * aborts all the outstanding SCSI I/Os to the pci device.   **/  static void  lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)  { +	struct lpfc_sli *psli = &phba->sli; +	struct lpfc_sli_ring  *pring; +  	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,  			"2723 PCI channel I/O abort preparing for recovery\n"); -	/* Prepare for bringing HBA offline */ -	lpfc_offline_prep(phba); -	/* Clear sli active flag to prevent sysfs access to HBA */ -	spin_lock_irq(&phba->hbalock); -	phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE; -	spin_unlock_irq(&phba->hbalock); -	/* Stop and flush all I/Os and bring HBA offline */ -	lpfc_offline(phba); + +	/* +	 * There may be errored I/Os through HBA, abort all I/Os on txcmplq +	 * and let the SCSI mid-layer to retry them to recover. +	 */ +	pring = &psli->ring[psli->fcp_ring]; +	lpfc_sli_abort_iocb_ring(phba, pring);  }  /** @@ -7781,21 +7836,20 @@ lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)  static void  lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)  { -	struct lpfc_sli *psli = &phba->sli; -	struct lpfc_sli_ring  *pring; -  	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,  			"2710 PCI channel disable preparing for reset\n"); + +	/* Block all SCSI devices' I/Os on the host */ +	lpfc_scsi_dev_block(phba); + +	/* stop all timers */ +	lpfc_stop_hba_timers(phba); +  	/* Disable interrupt and pci device */  	lpfc_sli_disable_intr(phba);  	pci_disable_device(phba->pcidev); -	/* -	 * There may be 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); +	/* Flush all driver's outstanding SCSI I/Os as we are to reset */ +	lpfc_sli_flush_fcp_rings(phba);  }  /** @@ -7811,6 +7865,12 @@ lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba)  {  	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,  			"2711 PCI channel permanent disable for failure\n"); +	/* Block all SCSI devices' I/Os on the host */ +	lpfc_scsi_dev_block(phba); + +	/* stop all timers */ +	lpfc_stop_hba_timers(phba); +  	/* Clean up all driver's outstanding SCSI I/Os */  	lpfc_sli_flush_fcp_rings(phba);  } @@ -7839,9 +7899,6 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state)  	struct Scsi_Host *shost = pci_get_drvdata(pdev);  	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; -	/* Block all SCSI devices' I/Os on the host */ -	lpfc_scsi_dev_block(phba); -  	switch (state) {  	case pci_channel_io_normal:  		/* Non-fatal error, prepare for recovery */ @@ -7948,7 +8005,7 @@ lpfc_io_resume_s3(struct pci_dev *pdev)  	struct Scsi_Host *shost = pci_get_drvdata(pdev);  	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; -	/* Bring the device online */ +	/* Bring device online, it will be no-op for non-fatal error resume */  	lpfc_online(phba);  	/* Clean up Advanced Error Reporting (AER) if needed */ | 
