Skip to content

Commit

Permalink
[SCSI] lpfc 8.3.4: Various SLI4 fixes
Browse files Browse the repository at this point in the history
Various SLI4 fixes

- Fix switch name not used in the FCF record for FCoE HBAs
- Enabled HBA UE error polling error-condition action code
- Rewrite lpfc_sli4_scmd_to_wqidx_distr() to handle counter rollover cleanly
- Modify resume_rpi mailbox data structure to match current SLI4 spec
- Do not issue mailbox command in MBX_POLL mode when LPFC_HBA_ERROR is set
- Wait for HBA POST completion before checking Online and UE registers
- Fix accumulated total length not being filled in on unsolicited IOCBs
- Use PCI config space register to determine SLI rev of HBA
- Turn on starting ELS tmo function timer during device initialization

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
James Smart authored and James Bottomley committed Aug 22, 2009
1 parent 66d6fae commit 8fa3851
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 99 deletions.
2 changes: 2 additions & 0 deletions drivers/scsi/lpfc/lpfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ struct lpfc_hba {
uint32_t hbq_count; /* Count of configured HBQs */
struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */

uint32_t fcp_qidx; /* next work queue to post work to */

unsigned long pci_bar0_map; /* Physical address for PCI BAR0 */
unsigned long pci_bar1_map; /* Physical address for PCI BAR1 */
unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */
Expand Down
66 changes: 60 additions & 6 deletions drivers/scsi/lpfc/lpfc_hbadisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,39 @@ lpfc_fab_name_match(uint8_t *fab_name, struct fcf_record *new_fcf_record)
return 0;
}

/**
* lpfc_sw_name_match - Check if the fcf switch name match.
* @fab_name: pointer to fabric name.
* @new_fcf_record: pointer to fcf record.
*
* This routine compare the fcf record's switch name with provided
* switch name. If the switch name are identical this function
* returns 1 else return 0.
**/
static uint32_t
lpfc_sw_name_match(uint8_t *sw_name, struct fcf_record *new_fcf_record)
{
if ((sw_name[0] ==
bf_get(lpfc_fcf_record_switch_name_0, new_fcf_record)) &&
(sw_name[1] ==
bf_get(lpfc_fcf_record_switch_name_1, new_fcf_record)) &&
(sw_name[2] ==
bf_get(lpfc_fcf_record_switch_name_2, new_fcf_record)) &&
(sw_name[3] ==
bf_get(lpfc_fcf_record_switch_name_3, new_fcf_record)) &&
(sw_name[4] ==
bf_get(lpfc_fcf_record_switch_name_4, new_fcf_record)) &&
(sw_name[5] ==
bf_get(lpfc_fcf_record_switch_name_5, new_fcf_record)) &&
(sw_name[6] ==
bf_get(lpfc_fcf_record_switch_name_6, new_fcf_record)) &&
(sw_name[7] ==
bf_get(lpfc_fcf_record_switch_name_7, new_fcf_record)))
return 1;
else
return 0;
}

/**
* lpfc_mac_addr_match - Check if the fcf mac address match.
* @phba: pointer to lpfc hba data structure.
Expand Down Expand Up @@ -1123,6 +1156,22 @@ lpfc_copy_fcf_record(struct lpfc_hba *phba, struct fcf_record *new_fcf_record)
bf_get(lpfc_fcf_record_mac_5, new_fcf_record);
phba->fcf.fcf_indx = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
phba->fcf.priority = new_fcf_record->fip_priority;
phba->fcf.switch_name[0] =
bf_get(lpfc_fcf_record_switch_name_0, new_fcf_record);
phba->fcf.switch_name[1] =
bf_get(lpfc_fcf_record_switch_name_1, new_fcf_record);
phba->fcf.switch_name[2] =
bf_get(lpfc_fcf_record_switch_name_2, new_fcf_record);
phba->fcf.switch_name[3] =
bf_get(lpfc_fcf_record_switch_name_3, new_fcf_record);
phba->fcf.switch_name[4] =
bf_get(lpfc_fcf_record_switch_name_4, new_fcf_record);
phba->fcf.switch_name[5] =
bf_get(lpfc_fcf_record_switch_name_5, new_fcf_record);
phba->fcf.switch_name[6] =
bf_get(lpfc_fcf_record_switch_name_6, new_fcf_record);
phba->fcf.switch_name[7] =
bf_get(lpfc_fcf_record_switch_name_7, new_fcf_record);
}

/**
Expand Down Expand Up @@ -1239,9 +1288,12 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,

if ((conn_entry->conn_rec.flags & FCFCNCT_FBNM_VALID) &&
!lpfc_fab_name_match(conn_entry->conn_rec.fabric_name,
new_fcf_record))
new_fcf_record))
continue;
if ((conn_entry->conn_rec.flags & FCFCNCT_SWNM_VALID) &&
!lpfc_sw_name_match(conn_entry->conn_rec.switch_name,
new_fcf_record))
continue;

if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) {
/*
* If the vlan bit map does not have the bit set for the
Expand Down Expand Up @@ -1424,7 +1476,9 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
spin_lock_irqsave(&phba->hbalock, flags);
if (phba->fcf.fcf_flag & FCF_IN_USE) {
if (lpfc_fab_name_match(phba->fcf.fabric_name,
new_fcf_record) &&
new_fcf_record) &&
lpfc_sw_name_match(phba->fcf.switch_name,
new_fcf_record) &&
lpfc_mac_addr_match(phba, new_fcf_record)) {
phba->fcf.fcf_flag |= FCF_AVAILABLE;
spin_unlock_irqrestore(&phba->hbalock, flags);
Expand Down Expand Up @@ -1464,9 +1518,9 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
* If there is a record with lower priority value for
* the current FCF, use that record.
*/
if (lpfc_fab_name_match(phba->fcf.fabric_name, new_fcf_record)
&& (new_fcf_record->fip_priority <
phba->fcf.priority)) {
if (lpfc_fab_name_match(phba->fcf.fabric_name,
new_fcf_record) &&
(new_fcf_record->fip_priority < phba->fcf.priority)) {
/* Use this FCF record */
lpfc_copy_fcf_record(phba, new_fcf_record);
phba->fcf.addr_mode = addr_mode;
Expand Down
74 changes: 61 additions & 13 deletions drivers/scsi/lpfc/lpfc_hw4.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,31 @@ struct dma_address {
uint32_t addr_hi;
};

#define LPFC_SLIREV_CONF_WORD 0x58
struct lpfc_sli_intf {
uint32_t word0;
#define lpfc_sli_intf_iftype_MASK 0x00000007
#define lpfc_sli_intf_iftype_SHIFT 0
#define lpfc_sli_intf_iftype_WORD word0
#define lpfc_sli_intf_rev_MASK 0x0000000f
#define lpfc_sli_intf_rev_SHIFT 4
#define lpfc_sli_intf_rev_WORD word0
#define LPFC_SLIREV_CONF_SLI4 4
#define lpfc_sli_intf_family_MASK 0x000000ff
#define lpfc_sli_intf_family_SHIFT 8
#define lpfc_sli_intf_family_WORD word0
#define lpfc_sli_intf_feat1_MASK 0x000000ff
#define lpfc_sli_intf_feat1_SHIFT 16
#define lpfc_sli_intf_feat1_WORD word0
#define lpfc_sli_intf_feat2_MASK 0x0000001f
#define lpfc_sli_intf_feat2_SHIFT 24
#define lpfc_sli_intf_feat2_WORD word0
#define lpfc_sli_intf_valid_MASK 0x00000007
#define lpfc_sli_intf_valid_SHIFT 29
#define lpfc_sli_intf_valid_WORD word0
#define LPFC_SLI_INTF_VALID 6
};

#define LPFC_SLI4_BAR0 1
#define LPFC_SLI4_BAR1 2
#define LPFC_SLI4_BAR2 4
Expand Down Expand Up @@ -1181,6 +1206,32 @@ struct fcf_record {
#define lpfc_fcf_record_fcf_state_MASK 0x0000FFFF
#define lpfc_fcf_record_fcf_state_WORD word8
uint8_t vlan_bitmap[512];
uint32_t word137;
#define lpfc_fcf_record_switch_name_0_SHIFT 0
#define lpfc_fcf_record_switch_name_0_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_0_WORD word137
#define lpfc_fcf_record_switch_name_1_SHIFT 8
#define lpfc_fcf_record_switch_name_1_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_1_WORD word137
#define lpfc_fcf_record_switch_name_2_SHIFT 16
#define lpfc_fcf_record_switch_name_2_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_2_WORD word137
#define lpfc_fcf_record_switch_name_3_SHIFT 24
#define lpfc_fcf_record_switch_name_3_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_3_WORD word137
uint32_t word138;
#define lpfc_fcf_record_switch_name_4_SHIFT 0
#define lpfc_fcf_record_switch_name_4_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_4_WORD word138
#define lpfc_fcf_record_switch_name_5_SHIFT 8
#define lpfc_fcf_record_switch_name_5_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_5_WORD word138
#define lpfc_fcf_record_switch_name_6_SHIFT 16
#define lpfc_fcf_record_switch_name_6_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_6_WORD word138
#define lpfc_fcf_record_switch_name_7_SHIFT 24
#define lpfc_fcf_record_switch_name_7_MASK 0x000000FF
#define lpfc_fcf_record_switch_name_7_WORD word138
};

struct lpfc_mbx_read_fcf_tbl {
Expand Down Expand Up @@ -1385,20 +1436,17 @@ struct lpfc_mbx_unreg_vfi {

struct lpfc_mbx_resume_rpi {
uint32_t word1;
#define lpfc_resume_rpi_rpi_SHIFT 0
#define lpfc_resume_rpi_rpi_MASK 0x0000FFFF
#define lpfc_resume_rpi_rpi_WORD word1
#define lpfc_resume_rpi_index_SHIFT 0
#define lpfc_resume_rpi_index_MASK 0x0000FFFF
#define lpfc_resume_rpi_index_WORD word1
#define lpfc_resume_rpi_ii_SHIFT 30
#define lpfc_resume_rpi_ii_MASK 0x00000003
#define lpfc_resume_rpi_ii_WORD word1
#define RESUME_INDEX_RPI 0
#define RESUME_INDEX_VPI 1
#define RESUME_INDEX_VFI 2
#define RESUME_INDEX_FCFI 3
uint32_t event_tag;
uint32_t word3_rsvd;
uint32_t word4_rsvd;
uint32_t word5_rsvd;
uint32_t word6;
#define lpfc_resume_rpi_vpi_SHIFT 0
#define lpfc_resume_rpi_vpi_MASK 0x0000FFFF
#define lpfc_resume_rpi_vpi_WORD word6
#define lpfc_resume_rpi_vfi_SHIFT 16
#define lpfc_resume_rpi_vfi_MASK 0x0000FFFF
#define lpfc_resume_rpi_vfi_WORD word6
};

#define REG_FCF_INVALID_QID 0xFFFF
Expand Down
48 changes: 23 additions & 25 deletions drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4488,23 +4488,6 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
if (!phba->sli4_hba.STAregaddr)
return -ENODEV;

/* With uncoverable error, log the error message and return error */
onlnreg0 = readl(phba->sli4_hba.ONLINE0regaddr);
onlnreg1 = readl(phba->sli4_hba.ONLINE1regaddr);
if ((onlnreg0 != LPFC_ONLINE_NERR) || (onlnreg1 != LPFC_ONLINE_NERR)) {
uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
if (uerrlo_reg.word0 || uerrhi_reg.word0) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"1422 HBA Unrecoverable error: "
"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
"online0_reg=0x%x, online1_reg=0x%x\n",
uerrlo_reg.word0, uerrhi_reg.word0,
onlnreg0, onlnreg1);
}
return -ENODEV;
}

/* Wait up to 30 seconds for the SLI Port POST done and ready */
for (i = 0; i < 3000; i++) {
sta_reg.word0 = readl(phba->sli4_hba.STAregaddr);
Expand Down Expand Up @@ -4544,6 +4527,23 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
bf_get(lpfc_scratchpad_featurelevel1, &scratchpad),
bf_get(lpfc_scratchpad_featurelevel2, &scratchpad));

/* With uncoverable error, log the error message and return error */
onlnreg0 = readl(phba->sli4_hba.ONLINE0regaddr);
onlnreg1 = readl(phba->sli4_hba.ONLINE1regaddr);
if ((onlnreg0 != LPFC_ONLINE_NERR) || (onlnreg1 != LPFC_ONLINE_NERR)) {
uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
if (uerrlo_reg.word0 || uerrhi_reg.word0) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"1422 HBA Unrecoverable error: "
"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
"online0_reg=0x%x, online1_reg=0x%x\n",
uerrlo_reg.word0, uerrhi_reg.word0,
onlnreg0, onlnreg1);
}
return -ENODEV;
}

return port_error;
}

Expand Down Expand Up @@ -7635,19 +7635,17 @@ static int __devinit
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{
int rc;
uint16_t dev_id;
struct lpfc_sli_intf intf;

if (pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id))
if (pci_read_config_dword(pdev, LPFC_SLIREV_CONF_WORD, &intf.word0))
return -ENODEV;

switch (dev_id) {
case PCI_DEVICE_ID_TIGERSHARK:
if ((bf_get(lpfc_sli_intf_valid, &intf) == LPFC_SLI_INTF_VALID) &&
(bf_get(lpfc_sli_intf_rev, &intf) == LPFC_SLIREV_CONF_SLI4))
rc = lpfc_pci_probe_one_s4(pdev, pid);
break;
default:
else
rc = lpfc_pci_probe_one_s3(pdev, pid);
break;
}

return rc;
}

Expand Down
8 changes: 3 additions & 5 deletions drivers/scsi/lpfc/lpfc_mbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,9 +1938,7 @@ lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp)
memset(mbox, 0, sizeof(*mbox));
resume_rpi = &mbox->u.mqe.un.resume_rpi;
bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI);
bf_set(lpfc_resume_rpi_rpi, resume_rpi, ndlp->nlp_rpi);
bf_set(lpfc_resume_rpi_vpi, resume_rpi,
ndlp->vport->vpi + ndlp->vport->phba->vpi_base);
bf_set(lpfc_resume_rpi_vfi, resume_rpi,
ndlp->vport->vfi + ndlp->vport->phba->vfi_base);
bf_set(lpfc_resume_rpi_index, resume_rpi, ndlp->nlp_rpi);
bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI);
resume_rpi->event_tag = ndlp->phba->fc_eventTag;
}
Loading

0 comments on commit 8fa3851

Please sign in to comment.