aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c70
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_compat.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c76
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c17
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h32
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c132
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c36
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
12 files changed, 284 insertions, 112 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3482d5a5aed..a50aa03b8ac 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -775,6 +775,7 @@ struct lpfc_hba {
uint8_t temp_sensor_support;
/* Fields used for heart beat. */
unsigned long last_completion_time;
+ unsigned long skipped_hb;
struct timer_list hb_tmofunc;
uint8_t hb_outstanding;
enum hba_temp_state over_temp_state;
@@ -817,6 +818,8 @@ struct lpfc_hba {
uint32_t iocb_cnt;
uint32_t iocb_max;
atomic_t sdev_cnt;
+ uint8_t fips_spec_rev;
+ uint8_t fips_level;
};
static inline struct Scsi_Host *
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 868874c28f9..23ce4570833 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/aer.h>
#include <linux/gfp.h>
+#include <linux/kernel.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -1239,6 +1240,44 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
}
/**
+ * lpfc_fips_level_show - Return the current FIPS level for the HBA
+ * @dev: class unused variable.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the module description text.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_fips_level_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level);
+}
+
+/**
+ * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA
+ * @dev: class unused variable.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the module description text.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev);
+}
+
+/**
* lpfc_param_show - Return a cfg attribute value in decimal
*
* Description:
@@ -1676,6 +1715,8 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
+static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL);
+static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL);
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
@@ -1795,12 +1836,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
/* Validate and store the new name */
for (i=0, j=0; i < 16; i++) {
- if ((*buf >= 'a') && (*buf <= 'f'))
- j = ((j << 4) | ((*buf++ -'a') + 10));
- else if ((*buf >= 'A') && (*buf <= 'F'))
- j = ((j << 4) | ((*buf++ -'A') + 10));
- else if ((*buf >= '0') && (*buf <= '9'))
- j = ((j << 4) | (*buf++ -'0'));
+ int value;
+
+ value = hex_to_bin(*buf++);
+ if (value >= 0)
+ j = (j << 4) | value;
else
return -EINVAL;
if (i % 2) {
@@ -1888,12 +1928,11 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
/* Validate and store the new name */
for (i=0, j=0; i < 16; i++) {
- if ((*buf >= 'a') && (*buf <= 'f'))
- j = ((j << 4) | ((*buf++ -'a') + 10));
- else if ((*buf >= 'A') && (*buf <= 'F'))
- j = ((j << 4) | ((*buf++ -'A') + 10));
- else if ((*buf >= '0') && (*buf <= '9'))
- j = ((j << 4) | (*buf++ -'0'));
+ int value;
+
+ value = hex_to_bin(*buf++);
+ if (value >= 0)
+ j = (j << 4) | value;
else
return -EINVAL;
if (i % 2) {
@@ -2778,7 +2817,6 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
.attr = {
.name = "lpfc_drvr_stat_data",
.mode = S_IRUSR,
- .owner = THIS_MODULE,
},
.size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET,
.read = sysfs_drvr_stat_data_read,
@@ -3280,7 +3318,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
# - Default will result in registering capabilities for all profiles.
#
*/
-unsigned int lpfc_prot_mask = SHOST_DIX_TYPE0_PROTECTION;
+unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION;
module_param(lpfc_prot_mask, uint, 0);
MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
@@ -3385,6 +3423,8 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_iocb_hw,
&dev_attr_txq_hw,
&dev_attr_txcmplq_hw,
+ &dev_attr_lpfc_fips_level,
+ &dev_attr_lpfc_fips_rev,
NULL,
};
@@ -3411,6 +3451,8 @@ struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_lpfc_max_scsicmpl_time,
&dev_attr_lpfc_stat_data_ctrl,
&dev_attr_lpfc_static_vport,
+ &dev_attr_lpfc_fips_level,
+ &dev_attr_lpfc_fips_rev,
NULL,
};
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index d521569e662..49d0cf99c24 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2724,15 +2724,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
pmboxq->context2 = ext;
pmboxq->in_ext_byte_len =
- mbox_req->inExtWLen *
- sizeof(uint32_t);
- pmboxq->out_ext_byte_len =
- mbox_req->outExtWLen *
- sizeof(uint32_t);
- pmboxq->mbox_offset_word =
- mbox_req->mbOffset;
- pmboxq->context2 = ext;
- pmboxq->in_ext_byte_len =
mbox_req->inExtWLen * sizeof(uint32_t);
pmboxq->out_ext_byte_len =
mbox_req->outExtWLen * sizeof(uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h
index a11f1ae7b98..75e2e569ded 100644
--- a/drivers/scsi/lpfc/lpfc_compat.h
+++ b/drivers/scsi/lpfc/lpfc_compat.h
@@ -82,8 +82,7 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
static inline void
lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes)
{
- /* actually returns 1 byte past dest */
- memcpy_toio( dest, src, bytes);
+ __iowrite32_copy(dest, src, bytes);
}
static inline void
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index afbed6bc31f..8d09191c327 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -600,6 +600,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
spin_unlock_irq(shost->host_lock);
}
+ } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
+ /*
+ * Driver needs to re-reg VPI in order for f/w
+ * to update the MAC address.
+ */
+ lpfc_register_new_vport(phba, vport, ndlp);
+ return 0;
}
if (phba->sli_rev < LPFC_SLI_REV4) {
@@ -801,9 +809,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
(irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS,
"2611 FLOGI failed on registered "
- "FCF record fcf_index:%d, trying "
- "to perform round robin failover\n",
- phba->fcf.current_rec.fcf_indx);
+ "FCF record fcf_index(%d), status: "
+ "x%x/x%x, tmo:x%x, trying to perform "
+ "round robin failover\n",
+ phba->fcf.current_rec.fcf_indx,
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout);
fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba);
if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) {
/*
@@ -841,6 +852,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
}
+ /* FLOGI failure */
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout);
+
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
goto out;
@@ -1291,6 +1308,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
struct serv_parm *sp;
uint8_t name[sizeof(struct lpfc_name)];
uint32_t rc, keepDID = 0;
+ int put_node;
+ int put_rport;
/* Fabric nodes can have the same WWPN so we don't bother searching
* by WWPN. Just return the ndlp that was given to us.
@@ -1379,6 +1398,28 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
/* Two ndlps cannot have the same did */
ndlp->nlp_DID = keepDID;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ /* Since we are swapping the ndlp passed in with the new one
+ * and the did has already been swapped, copy over the
+ * state and names.
+ */
+ memcpy(&new_ndlp->nlp_portname, &ndlp->nlp_portname,
+ sizeof(struct lpfc_name));
+ memcpy(&new_ndlp->nlp_nodename, &ndlp->nlp_nodename,
+ sizeof(struct lpfc_name));
+ new_ndlp->nlp_state = ndlp->nlp_state;
+ /* Fix up the rport accordingly */
+ rport = ndlp->rport;
+ if (rport) {
+ rdata = rport->dd_data;
+ put_node = rdata->pnode != NULL;
+ put_rport = ndlp->rport != NULL;
+ rdata->pnode = NULL;
+ ndlp->rport = NULL;
+ if (put_node)
+ lpfc_nlp_put(ndlp);
+ if (put_rport)
+ put_device(&rport->dev);
+ }
}
return new_ndlp;
}
@@ -2880,6 +2921,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry = 0;
if (retry) {
+ if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) {
+ /* Stop retrying PLOGI and FDISC if in FCF discovery */
+ if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "2849 Stop retry ELS command "
+ "x%x to remote NPORT x%x, "
+ "Data: x%x x%x\n", cmd, did,
+ cmdiocb->retry, delay);
+ return 0;
+ }
+ }
/* Retry ELS command <elsCmd> to remote NPORT <did> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
@@ -6076,8 +6128,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (mb->mbxStatus) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
- "0915 Register VPI failed: 0x%x\n",
- mb->mbxStatus);
+ "0915 Register VPI failed : Status: x%x"
+ " upd bit: x%x \n", mb->mbxStatus,
+ mb->un.varRegVpi.upd);
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ mb->un.varRegVpi.upd)
+ goto mbox_err_exit ;
switch (mb->mbxStatus) {
case 0x11: /* unsupported feature */
@@ -6142,7 +6198,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
} else
lpfc_do_scr_ns_plogi(phba, vport);
}
-
+mbox_err_exit:
/* Now, we decrement the ndlp reference count held for this
* callback function
*/
@@ -6387,6 +6443,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
else
vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG;
spin_unlock_irq(shost->host_lock);
+ } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
+ /*
+ * Driver needs to re-reg VPI in order for f/w
+ * to update the MAC address.
+ */
+ lpfc_register_new_vport(phba, vport, ndlp);
+ return ;
}
if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI)
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 0639c994349..1f62ea8c165 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -588,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba)
(status &
HA_RXMASK));
}
- if (pring->txq_cnt)
+ if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt)
lpfc_drain_txq(phba);
/*
* Turn on Ring interrupts
@@ -1852,8 +1852,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
__lpfc_sli4_stop_fcf_redisc_wait_timer(phba);
else if (phba->fcf.fcf_flag & FCF_REDISC_FOV)
/* If in fast failover, mark it's completed */
- phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV |
- FCF_DISCOVERY);
+ phba->fcf.fcf_flag &= ~FCF_REDISC_FOV;
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
"2836 The new FCF record (x%x) "
@@ -2651,7 +2650,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
"2778 Start FCF table scan at linkup\n");
-
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba,
LPFC_FCOE_FCF_GET_FIRST);
if (rc) {
@@ -2660,6 +2658,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
spin_unlock_irq(&phba->hbalock);
goto out;
}
+ /* Reset FCF roundrobin bmask for new discovery */
+ memset(phba->fcf.fcf_rr_bmask, 0,
+ sizeof(*phba->fcf.fcf_rr_bmask));
}
return;
@@ -5097,6 +5098,7 @@ static void
lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport = mboxq->vport;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (mboxq->u.mb.mbxStatus) {
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
@@ -5104,6 +5106,9 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
"HBA state x%x\n",
mboxq->u.mb.mbxStatus, vport->port_state);
}
+ spin_lock_irq(shost->host_lock);
+ phba->pport->fc_flag &= ~FC_VFI_REGISTERED;
+ spin_unlock_irq(shost->host_lock);
mempool_free(mboxq, phba->mbox_mem_pool);
return;
}
@@ -5285,6 +5290,10 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag |= FCF_INIT_DISC;
spin_unlock_irq(&phba->hbalock);
+
+ /* Reset FCF roundrobin bmask for new discovery */
+ memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
if (rc) {
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index f5dbf2be3ea..1676f61291e 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -2291,7 +2291,8 @@ typedef struct {
typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd1;
- uint32_t rsvd2:8;
+ uint32_t rsvd2:7;
+ uint32_t upd:1;
uint32_t sid:24;
uint32_t wwn[2];
uint32_t rsvd5;
@@ -2300,7 +2301,8 @@ typedef struct {
#else /* __LITTLE_ENDIAN */
uint32_t rsvd1;
uint32_t sid:24;
- uint32_t rsvd2:8;
+ uint32_t upd:1;
+ uint32_t rsvd2:7;
uint32_t wwn[2];
uint32_t rsvd5;
uint16_t vpi;
@@ -2806,11 +2808,15 @@ typedef struct {
uint32_t rsvd6; /* Reserved */
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd7 : 16; /* Reserved */
+ uint32_t fips_rev : 3; /* FIPS Spec Revision */
+ uint32_t fips_level : 4; /* FIPS Level */
+ uint32_t sec_err : 9; /* security crypto error */
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
#else /* __LITTLE_ENDIAN */
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
- uint32_t rsvd7 : 16; /* Reserved */
+ uint32_t sec_err : 9; /* security crypto error */
+ uint32_t fips_level : 4; /* FIPS Level */
+ uint32_t fips_rev : 3; /* FIPS Spec Revision */
#endif
} CONFIG_PORT_VAR;
@@ -3441,63 +3447,63 @@ struct sli3_bg_fields {
static inline uint32_t
lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_BIDIR_BG_PROF_MASK) >>
+ return (bgstat & BGS_BIDIR_BG_PROF_MASK) >>
BGS_BIDIR_BG_PROF_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_bidir_err_cond(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_BIDIR_ERR_COND_FLAGS_MASK) >>
+ return (bgstat & BGS_BIDIR_ERR_COND_FLAGS_MASK) >>
BGS_BIDIR_ERR_COND_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_bg_prof(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_BG_PROFILE_MASK) >>
+ return (bgstat & BGS_BG_PROFILE_MASK) >>
BGS_BG_PROFILE_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_invalid_prof(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_INVALID_PROF_MASK) >>
+ return (bgstat & BGS_INVALID_PROF_MASK) >>
BGS_INVALID_PROF_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_uninit_dif_block(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_UNINIT_DIF_BLOCK_MASK) >>
+ return (bgstat & BGS_UNINIT_DIF_BLOCK_MASK) >>
BGS_UNINIT_DIF_BLOCK_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_HI_WATER_MARK_PRESENT_MASK) >>
+ return (bgstat & BGS_HI_WATER_MARK_PRESENT_MASK) >>
BGS_HI_WATER_MARK_PRESENT_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_reftag_err(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_REFTAG_ERR_MASK) >>
+ return (bgstat & BGS_REFTAG_ERR_MASK) >>
BGS_REFTAG_ERR_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_apptag_err(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_APPTAG_ERR_MASK) >>
+ return (bgstat & BGS_APPTAG_ERR_MASK) >>
BGS_APPTAG_ERR_SHIFT;
}
static inline uint32_t
lpfc_bgs_get_guard_err(uint32_t bgstat)
{
- return (le32_to_cpu(bgstat) & BGS_GUARD_ERR_MASK) >>
+ return (bgstat & BGS_GUARD_ERR_MASK) >>
BGS_GUARD_ERR_SHIFT;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 2786ee3b605..da9ba06ad58 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1032,27 +1032,46 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
/* If there is no heart beat outstanding, issue a heartbeat command */
if (phba->cfg_enable_hba_heartbeat) {
if (!phba->hb_outstanding) {
- pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
- if (!pmboxq) {
- mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
- return;
- }
+ if ((!(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) &&
+ (list_empty(&psli->mboxq))) {
+ pmboxq = mempool_alloc(phba->mbox_mem_pool,
+ GFP_KERNEL);
+ if (!pmboxq) {
+ mod_timer(&phba->hb_tmofunc,
+ jiffies +
+ HZ * LPFC_HB_MBOX_INTERVAL);
+ return;
+ }
- lpfc_heart_beat(phba, pmboxq);
- pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
- pmboxq->vport = phba->pport;
- retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
+ lpfc_heart_beat(phba, pmboxq);
+ pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
+ pmboxq->vport = phba->pport;
+ retval = lpfc_sli_issue_mbox(phba, pmboxq,
+ MBX_NOWAIT);
+
+ if (retval != MBX_BUSY &&
+ retval != MBX_SUCCESS) {
+ mempool_free(pmboxq,
+ phba->mbox_mem_pool);
+ mod_timer(&phba->hb_tmofunc,
+ jiffies +
+ HZ * LPFC_HB_MBOX_INTERVAL);
+ return;
+ }
+ phba->skipped_hb = 0;
+ phba->hb_outstanding = 1;
+ } else if (time_before_eq(phba->last_completion_time,
+ phba->skipped_hb)) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "2857 Last completion time not "
+ " updated in %d ms\n",
+ jiffies_to_msecs(jiffies
+ - phba->last_completion_time));
+ } else
+ phba->skipped_hb = jiffies;
- if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
- mempool_free(pmboxq, phba->mbox_mem_pool);
- mod_timer(&phba->hb_tmofunc,
- jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
- return;
- }
mod_timer(&phba->hb_tmofunc,
jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
- phba->hb_outstanding = 1;
return;
} else {
/*
@@ -3281,10 +3300,10 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)
if (!ndlp)
return 0;
}
- if (phba->pport->port_state <= LPFC_FLOGI)
+ if (phba->pport->port_state < LPFC_FLOGI)
return NULL;
/* If virtual link is not yet instantiated ignore CVL */
- if (vport->port_state <= LPFC_FDISC)
+ if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC))
return NULL;
shost = lpfc_shost_from_vport(vport);
if (!shost)
@@ -3357,21 +3376,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
"evt_tag:x%x, fcf_index:x%x\n",
acqe_fcoe->event_tag,
acqe_fcoe->index);
- /* If the FCF discovery is in progress, do nothing. */
- spin_lock_irq(&phba->hbalock);
- if (phba->hba_flag & FCF_DISC_INPROGRESS) {
- spin_unlock_irq(&phba->hbalock);
- break;
- }
- /* If fast FCF failover rescan event is pending, do nothing */
- if (phba->fcf.fcf_flag & FCF_REDISC_EVT) {
- spin_unlock_irq(&phba->hbalock);
- break;
- }
- spin_unlock_irq(&phba->hbalock);
-
- if ((phba->fcf.fcf_flag & FCF_DISCOVERY) &&
- !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) {
+ if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
/*
* During period of FCF discovery, read the FCF
* table record indexed by the event to update
@@ -3385,13 +3390,26 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
acqe_fcoe->index);
rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index);
}
- /* If the FCF has been in discovered state, do nothing. */
+
+ /* If the FCF discovery is in progress, do nothing. */
spin_lock_irq(&phba->hbalock);
+ if (phba->hba_flag & FCF_DISC_INPROGRESS) {
+ spin_unlock_irq(&phba->hbalock);
+ break;
+ }
+ /* If fast FCF failover rescan event is pending, do nothing */
+ if (phba->fcf.fcf_flag & FCF_REDISC_EVT) {
+ spin_unlock_irq(&phba->hbalock);
+ break;
+ }
+
+ /* If the FCF has been in discovered state, do nothing. */
if (phba->fcf.fcf_flag & FCF_SCAN_DONE) {
spin_unlock_irq(&phba->hbalock);
break;
}
spin_unlock_irq(&phba->hbalock);
+
/* Otherwise, scan the entire FCF table and re-discover SAN */
lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
"2770 Start FCF table scan due to new FCF "
@@ -3417,13 +3435,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
"2549 FCF disconnected from network index 0x%x"
" tag 0x%x\n", acqe_fcoe->index,
acqe_fcoe->event_tag);
- /* If the event is not for currently used fcf do nothing */
- if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index)
- break;
- /* We request port to rediscover the entire FCF table for
- * a fast recovery from case that the current FCF record
- * is no longer valid if we are not in the middle of FCF
- * failover process already.
+ /*
+ * If we are in the middle of FCF failover process, clear
+ * the corresponding FCF bit in the roundrobin bitmap.
*/
spin_lock_irq(&phba->hbalock);
if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
@@ -3432,9 +3446,23 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index);
break;
}
+ spin_unlock_irq(&phba->hbalock);
+
+ /* If the event is not for currently used fcf do nothing */
+ if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index)
+ break;
+
+ /*
+ * Otherwise, request the port to rediscover the entire FCF
+ * table for a fast recovery from case that the current FCF
+ * is no longer valid as we are not in the middle of FCF
+ * failover process already.
+ */
+ spin_lock_irq(&phba->hbalock);
/* Mark the fast failover process in progress */
phba->fcf.fcf_flag |= FCF_DEAD_DISC;
spin_unlock_irq(&phba->hbalock);
+
lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
"2771 Start FCF fast failover process due to "
"FCF DEAD event: evt_tag:x%x, fcf_index:x%x "
@@ -3454,12 +3482,16 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
* as a link down to FCF registration.
*/
lpfc_sli4_fcf_dead_failthrough(phba);
- } else
- /* Handling fast FCF failover to a DEAD FCF event
- * is considered equalivant to receiving CVL to all
- * vports.
+ } else {
+ /* Reset FCF roundrobin bmask for new discovery */
+ memset(phba->fcf.fcf_rr_bmask, 0,
+ sizeof(*phba->fcf.fcf_rr_bmask));
+ /*
+ * Handling fast FCF failover to a DEAD FCF event is
+ * considered equalivant to receiving CVL to all vports.
*/
lpfc_sli4_perform_all_vport_cvl(phba);
+ }
break;
case LPFC_FCOE_EVENT_TYPE_CVL:
lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
@@ -3534,7 +3566,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
* the current registered FCF entry.
*/
lpfc_retry_pport_discovery(phba);
- }
+ } else
+ /*
+ * Reset FCF roundrobin bmask for new
+ * discovery.
+ */
+ memset(phba->fcf.fcf_rr_bmask, 0,
+ sizeof(*phba->fcf.fcf_rr_bmask));
}
break;
default:
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 9c2c7c7140c..0dfa310cd60 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -815,9 +815,15 @@ void
lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb)
{
MAILBOX_t *mb = &pmb->u.mb;
+ struct lpfc_hba *phba = vport->phba;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-
+ /*
+ * Set the re-reg VPI bit for f/w to update the MAC address.
+ */
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI))
+ mb->un.varRegVpi.upd = 1;
mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base;
mb->un.varRegVpi.sid = vport->fc_myDID;
mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c818a725596..2e51aa6b45b 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1325,7 +1325,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
pde5->reftag = reftag;
- /* Endian convertion if necessary for PDE5 */
+ /* Endianness conversion if necessary for PDE5 */
pde5->word0 = cpu_to_le32(pde5->word0);
pde5->reftag = cpu_to_le32(pde5->reftag);
@@ -1347,7 +1347,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde6_ai, pde6, 1);
bf_set(pde6_apptagval, pde6, apptagval);
- /* Endian convertion if necessary for PDE6 */
+ /* Endianness conversion if necessary for PDE6 */
pde6->word0 = cpu_to_le32(pde6->word0);
pde6->word1 = cpu_to_le32(pde6->word1);
pde6->word2 = cpu_to_le32(pde6->word2);
@@ -1459,7 +1459,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
pde5->reftag = reftag;
- /* Endian convertion if necessary for PDE5 */
+ /* Endianness conversion if necessary for PDE5 */
pde5->word0 = cpu_to_le32(pde5->word0);
pde5->reftag = cpu_to_le32(pde5->reftag);
@@ -1479,7 +1479,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde6_ai, pde6, 1);
bf_set(pde6_apptagval, pde6, apptagval);
- /* Endian convertion if necessary for PDE6 */
+ /* Endianness conversion if necessary for PDE6 */
pde6->word0 = cpu_to_le32(pde6->word0);
pde6->word1 = cpu_to_le32(pde6->word1);
pde6->word2 = cpu_to_le32(pde6->word2);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e758eae0d0f..fb8905f893f 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1046,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
} else
spin_unlock_irq(&phba->hbalock);
- lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"0318 Failed to allocate IOTAG.last IOTAG is %d\n",
psli->last_iotag);
@@ -3914,7 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |
LPFC_SLI3_HBQ_ENABLED |
LPFC_SLI3_CRP_ENABLED |
- LPFC_SLI3_BG_ENABLED);
+ LPFC_SLI3_BG_ENABLED |
+ LPFC_SLI3_DSS_ENABLED);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0442 Adapter failed to init, mbxCmd x%x "
@@ -3949,8 +3950,23 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
} else
phba->max_vpi = 0;
- if (pmb->u.mb.un.varCfgPort.gdss)
+ phba->fips_level = 0;
+ phba->fips_spec_rev = 0;
+ if (pmb->u.mb.un.varCfgPort.gdss) {
phba->sli3_options |= LPFC_SLI3_DSS_ENABLED;
+ phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level;
+ phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "2850 Security Crypto Active. FIPS x%d "
+ "(Spec Rev: x%d)",
+ phba->fips_level, phba->fips_spec_rev);
+ }
+ if (pmb->u.mb.un.varCfgPort.sec_err) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2856 Config Port Security Crypto "
+ "Error: x%x ",
+ pmb->u.mb.un.varCfgPort.sec_err);
+ }
if (pmb->u.mb.un.varCfgPort.gerbm)
phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
if (pmb->u.mb.un.varCfgPort.gcrp)
@@ -9040,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
switch (bf_get(lpfc_cqe_code, &cqevt)) {
case CQE_CODE_COMPL_WQE:
/* Process the WQ/RQ complete event */
+ phba->last_completion_time = jiffies;
workposted = lpfc_sli4_sp_handle_els_wcqe(phba,
(struct lpfc_wcqe_complete *)&cqevt);
break;
@@ -9050,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
break;
case CQE_CODE_XRI_ABORTED:
/* Process the WQ XRI abort event */
+ phba->last_completion_time = jiffies;
workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq,
(struct sli4_wcqe_xri_aborted *)&cqevt);
break;
case CQE_CODE_RECEIVE:
/* Process the RQ event */
+ phba->last_completion_time = jiffies;
workposted = lpfc_sli4_sp_handle_rcqe(phba,
(struct lpfc_rcqe *)&cqevt);
break;
@@ -9276,7 +9295,6 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
{
struct lpfc_wcqe_release wcqe;
bool workposted = false;
- unsigned long iflag;
/* Copy the work queue CQE and convert endian order if needed */
lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe));
@@ -9285,9 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
switch (bf_get(lpfc_wcqe_c_code, &wcqe)) {
case CQE_CODE_COMPL_WQE:
/* Process the WQ complete event */
- spin_lock_irqsave(&phba->hbalock, iflag);
phba->last_completion_time = jiffies;
- spin_unlock_irqrestore(&phba->hbalock, iflag);
lpfc_sli4_fp_handle_fcp_wcqe(phba,
(struct lpfc_wcqe_complete *)&wcqe);
break;
@@ -9298,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
break;
case CQE_CODE_XRI_ABORTED:
/* Process the WQ XRI abort event */
+ phba->last_completion_time = jiffies;
workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq,
(struct sli4_wcqe_xri_aborted *)&wcqe);
break;
@@ -12278,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index)
spin_lock_irq(&phba->hbalock);
phba->hba_flag |= FCF_DISC_INPROGRESS;
spin_unlock_irq(&phba->hbalock);
- /* Reset FCF round robin index bmask for new scan */
- if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) {
- memset(phba->fcf.fcf_rr_bmask, 0,
- sizeof(*phba->fcf.fcf_rr_bmask));
+ /* Reset eligible FCF count for new scan */
+ if (fcf_index == LPFC_FCOE_FCF_GET_FIRST)
phba->fcf.eligible_fcf_cnt = 0;
- }
error = 0;
}
fail_fcf_scan:
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index d28830af71d..61afb3420a9 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.15"
+#define LPFC_DRIVER_VERSION "8.3.16"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"