Commit fedd3b7b authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.21: Critical Errors and Bug Fixes



Critical Errors:
- Correctly handle non-zero return lpfc_workq_post_event and return ENOMEM
- Save the irq level when locking the host_lock in lpfc_findnode_did

Bug Fixes:
- Adjust payload_length and request_length for sli4_config mailbox commands.
- Add the freed sgl/XRI to the tail of the list rather than to the head.
- Set the FC_VPORT_NEEDS_INIT_VPI on vport deletes and check it before
  issuing a fdisc on an els retry.
- Only call lpfc_hba_init_link() if phba->cfg_suppress_link_up
  is LPFC_INITIALIZE_LINK.
- Add support for SLI-4 Performance Hints

Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 382be668
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -548,6 +548,8 @@ struct lpfc_hba {
#define LPFC_SLI3_CRP_ENABLED		0x08
#define LPFC_SLI3_BG_ENABLED		0x20
#define LPFC_SLI3_DSS_ENABLED		0x40
#define LPFC_SLI4_PERFH_ENABLED		0x80
#define LPFC_SLI4_PHWQ_ENABLED		0x100
	uint32_t iocb_cmd_size;
	uint32_t iocb_rsp_size;

+24 −5
Original line number Diff line number Diff line
@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
	int status = 0;
	int cnt = 0;
	int i;
	int rc;

	init_completion(&online_compl);
	lpfc_workq_post_event(phba, &status, &online_compl,
	rc = lpfc_workq_post_event(phba, &status, &online_compl,
			      LPFC_EVT_OFFLINE_PREP);
	if (rc == 0)
		return -ENOMEM;

	wait_for_completion(&online_compl);

	if (status != 0)
@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
	}

	init_completion(&online_compl);
	lpfc_workq_post_event(phba, &status, &online_compl, type);
	rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
	if (rc == 0)
		return -ENOMEM;

	wait_for_completion(&online_compl);

	if (status != 0)
@@ -682,6 +689,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
{
	struct completion online_compl;
	int status = 0;
	int rc;

	if (!phba->cfg_enable_hba_reset)
		return -EIO;
@@ -692,8 +700,11 @@ lpfc_selective_reset(struct lpfc_hba *phba)
		return status;

	init_completion(&online_compl);
	lpfc_workq_post_event(phba, &status, &online_compl,
	rc = lpfc_workq_post_event(phba, &status, &online_compl,
			      LPFC_EVT_ONLINE);
	if (rc == 0)
		return -ENOMEM;

	wait_for_completion(&online_compl);

	if (status != 0)
@@ -812,14 +823,17 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
	struct lpfc_hba   *phba = vport->phba;
	struct completion online_compl;
	int status=0;
	int rc;

	if (!phba->cfg_enable_hba_reset)
		return -EACCES;
	init_completion(&online_compl);

	if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
		lpfc_workq_post_event(phba, &status, &online_compl,
		rc = lpfc_workq_post_event(phba, &status, &online_compl,
				      LPFC_EVT_ONLINE);
		if (rc == 0)
			return -ENOMEM;
		wait_for_completion(&online_compl);
	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -1813,6 +1827,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
	int stat1=0, stat2=0;
	unsigned int i, j, cnt=count;
	u8 wwpn[8];
	int rc;

	if (!phba->cfg_enable_hba_reset)
		return -EACCES;
@@ -1863,7 +1878,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
				"0463 lpfc_soft_wwpn attribute set failed to "
				"reinit adapter - %d\n", stat1);
	init_completion(&online_compl);
	lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE);
	rc = lpfc_workq_post_event(phba, &stat2, &online_compl,
				   LPFC_EVT_ONLINE);
	if (rc == 0)
		return -ENOMEM;

	wait_for_completion(&online_compl);
	if (stat2)
		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+2 −2
Original line number Diff line number Diff line
@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_supported_pages(struct lpfcMboxq *);
void lpfc_sli4_params(struct lpfcMboxq *);
void lpfc_pc_sli4_params(struct lpfcMboxq *);
int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *);

int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
+2 −1
Original line number Diff line number Diff line
@@ -2745,6 +2745,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
		}
		break;
	case ELS_CMD_FDISC:
		if (!(vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI))
			lpfc_issue_els_fdisc(vport, ndlp, retry);
		break;
	}
+3 −2
Original line number Diff line number Diff line
@@ -4426,10 +4426,11 @@ lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
{
	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
	struct lpfc_nodelist *ndlp;
	unsigned long iflags;

	spin_lock_irq(shost->host_lock);
	spin_lock_irqsave(shost->host_lock, iflags);
	ndlp = __lpfc_findnode_did(vport, did);
	spin_unlock_irq(shost->host_lock);
	spin_unlock_irqrestore(shost->host_lock, iflags);
	return ndlp;
}

Loading