|
@@ -351,10 +351,23 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
|
|
|
struct Scsi_Host *shost = class_to_shost(dev);
|
|
|
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
|
|
struct lpfc_hba *phba = vport->phba;
|
|
|
+ uint32_t if_type;
|
|
|
+ uint8_t sli_family;
|
|
|
char fwrev[32];
|
|
|
+ int len;
|
|
|
|
|
|
lpfc_decode_firmware_rev(phba, fwrev, 1);
|
|
|
- return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
|
|
|
+ if_type = phba->sli4_hba.pc_sli4_params.if_type;
|
|
|
+ sli_family = phba->sli4_hba.pc_sli4_params.sli_family;
|
|
|
+
|
|
|
+ if (phba->sli_rev < LPFC_SLI_REV4)
|
|
|
+ len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n",
|
|
|
+ fwrev, phba->sli_rev);
|
|
|
+ else
|
|
|
+ len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n",
|
|
|
+ fwrev, phba->sli_rev, if_type, sli_family);
|
|
|
+
|
|
|
+ return len;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -487,6 +500,34 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
|
|
|
return len;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * lpfc_sli4_protocol_show - Return the fip mode of 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_sli4_protocol_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;
|
|
|
+
|
|
|
+ if (phba->sli_rev < LPFC_SLI_REV4)
|
|
|
+ return snprintf(buf, PAGE_SIZE, "fc\n");
|
|
|
+
|
|
|
+ if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) {
|
|
|
+ if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE)
|
|
|
+ return snprintf(buf, PAGE_SIZE, "fcoe\n");
|
|
|
+ if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)
|
|
|
+ return snprintf(buf, PAGE_SIZE, "fc\n");
|
|
|
+ }
|
|
|
+ return snprintf(buf, PAGE_SIZE, "unknown\n");
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lpfc_link_state_store - Transition the link_state on an HBA port
|
|
|
* @dev: class device that is converted into a Scsi_host.
|
|
@@ -773,7 +814,12 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
|
|
|
* the readyness after performing a firmware reset.
|
|
|
*
|
|
|
* Returns:
|
|
|
- * zero for success
|
|
|
+ * zero for success, -EPERM when port does not have privilage to perform the
|
|
|
+ * reset, -EIO when port timeout from recovering from the reset.
|
|
|
+ *
|
|
|
+ * Note:
|
|
|
+ * As the caller will interpret the return code by value, be careful in making
|
|
|
+ * change or addition to return codes.
|
|
|
**/
|
|
|
int
|
|
|
lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
|
|
@@ -826,9 +872,11 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
|
|
|
{
|
|
|
struct completion online_compl;
|
|
|
struct pci_dev *pdev = phba->pcidev;
|
|
|
+ uint32_t before_fc_flag;
|
|
|
+ uint32_t sriov_nr_virtfn;
|
|
|
uint32_t reg_val;
|
|
|
- int status = 0;
|
|
|
- int rc;
|
|
|
+ int status = 0, rc = 0;
|
|
|
+ int job_posted = 1, sriov_err;
|
|
|
|
|
|
if (!phba->cfg_enable_hba_reset)
|
|
|
return -EACCES;
|
|
@@ -838,6 +886,10 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
|
|
|
LPFC_SLI_INTF_IF_TYPE_2))
|
|
|
return -EPERM;
|
|
|
|
|
|
+ /* Keep state if we need to restore back */
|
|
|
+ before_fc_flag = phba->pport->fc_flag;
|
|
|
+ sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
|
|
|
+
|
|
|
/* Disable SR-IOV virtual functions if enabled */
|
|
|
if (phba->cfg_sriov_nr_virtfn) {
|
|
|
pci_disable_sriov(pdev);
|
|
@@ -869,21 +921,44 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
|
|
|
/* delay driver action following IF_TYPE_2 reset */
|
|
|
rc = lpfc_sli4_pdev_status_reg_wait(phba);
|
|
|
|
|
|
- if (rc)
|
|
|
+ if (rc == -EPERM) {
|
|
|
+ /* no privilage for reset, restore if needed */
|
|
|
+ if (before_fc_flag & FC_OFFLINE_MODE)
|
|
|
+ goto out;
|
|
|
+ } else if (rc == -EIO) {
|
|
|
+ /* reset failed, there is nothing more we can do */
|
|
|
return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* keep the original port state */
|
|
|
+ if (before_fc_flag & FC_OFFLINE_MODE)
|
|
|
+ goto out;
|
|
|
|
|
|
init_completion(&online_compl);
|
|
|
- rc = lpfc_workq_post_event(phba, &status, &online_compl,
|
|
|
- LPFC_EVT_ONLINE);
|
|
|
- if (rc == 0)
|
|
|
- return -ENOMEM;
|
|
|
+ job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
|
|
|
+ LPFC_EVT_ONLINE);
|
|
|
+ if (!job_posted)
|
|
|
+ goto out;
|
|
|
|
|
|
wait_for_completion(&online_compl);
|
|
|
|
|
|
- if (status != 0)
|
|
|
- return -EIO;
|
|
|
+out:
|
|
|
+ /* in any case, restore the virtual functions enabled as before */
|
|
|
+ if (sriov_nr_virtfn) {
|
|
|
+ sriov_err =
|
|
|
+ lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn);
|
|
|
+ if (!sriov_err)
|
|
|
+ phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn;
|
|
|
+ }
|
|
|
|
|
|
- return 0;
|
|
|
+ /* return proper error code */
|
|
|
+ if (!rc) {
|
|
|
+ if (!job_posted)
|
|
|
+ rc = -ENOMEM;
|
|
|
+ else if (status)
|
|
|
+ rc = -EIO;
|
|
|
+ }
|
|
|
+ return rc;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -955,33 +1030,38 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
|
|
|
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
|
|
struct lpfc_hba *phba = vport->phba;
|
|
|
struct completion online_compl;
|
|
|
- int status=0;
|
|
|
+ char *board_mode_str = NULL;
|
|
|
+ int status = 0;
|
|
|
int rc;
|
|
|
|
|
|
- if (!phba->cfg_enable_hba_reset)
|
|
|
- return -EACCES;
|
|
|
+ if (!phba->cfg_enable_hba_reset) {
|
|
|
+ status = -EACCES;
|
|
|
+ goto board_mode_out;
|
|
|
+ }
|
|
|
|
|
|
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
|
|
- "3050 lpfc_board_mode set to %s\n", buf);
|
|
|
+ "3050 lpfc_board_mode set to %s\n", buf);
|
|
|
|
|
|
init_completion(&online_compl);
|
|
|
|
|
|
if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
|
|
|
rc = lpfc_workq_post_event(phba, &status, &online_compl,
|
|
|
LPFC_EVT_ONLINE);
|
|
|
- if (rc == 0)
|
|
|
- return -ENOMEM;
|
|
|
+ if (rc == 0) {
|
|
|
+ status = -ENOMEM;
|
|
|
+ goto board_mode_out;
|
|
|
+ }
|
|
|
wait_for_completion(&online_compl);
|
|
|
} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
|
|
|
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
|
|
|
else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
- return -EINVAL;
|
|
|
+ status = -EINVAL;
|
|
|
else
|
|
|
status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
|
|
|
else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
|
|
|
if (phba->sli_rev == LPFC_SLI_REV4)
|
|
|
- return -EINVAL;
|
|
|
+ status = -EINVAL;
|
|
|
else
|
|
|
status = lpfc_do_offline(phba, LPFC_EVT_KILL);
|
|
|
else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0)
|
|
@@ -991,12 +1071,21 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
|
|
|
else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0)
|
|
|
status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET);
|
|
|
else
|
|
|
- return -EINVAL;
|
|
|
+ status = -EINVAL;
|
|
|
|
|
|
+board_mode_out:
|
|
|
if (!status)
|
|
|
return strlen(buf);
|
|
|
- else
|
|
|
+ else {
|
|
|
+ board_mode_str = strchr(buf, '\n');
|
|
|
+ if (board_mode_str)
|
|
|
+ *board_mode_str = '\0';
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
|
|
|
+ "3097 Failed \"%s\", status(%d), "
|
|
|
+ "fc_flag(x%x)\n",
|
|
|
+ buf, status, phba->pport->fc_flag);
|
|
|
return status;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1942,6 +2031,7 @@ static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL);
|
|
|
static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL);
|
|
|
static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO,
|
|
|
lpfc_sriov_hw_max_virtfn_show, NULL);
|
|
|
+static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
|
|
|
|
|
|
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
|
|
|
|
|
@@ -3830,6 +3920,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|
|
&dev_attr_lpfc_fips_rev,
|
|
|
&dev_attr_lpfc_dss,
|
|
|
&dev_attr_lpfc_sriov_hw_max_virtfn,
|
|
|
+ &dev_attr_protocol,
|
|
|
NULL,
|
|
|
};
|
|
|
|
|
@@ -3987,23 +4078,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {
|
|
|
.write = sysfs_ctlreg_write,
|
|
|
};
|
|
|
|
|
|
-/**
|
|
|
- * sysfs_mbox_idle - frees the sysfs mailbox
|
|
|
- * @phba: lpfc_hba pointer
|
|
|
- **/
|
|
|
-static void
|
|
|
-sysfs_mbox_idle(struct lpfc_hba *phba)
|
|
|
-{
|
|
|
- phba->sysfs_mbox.state = SMBOX_IDLE;
|
|
|
- phba->sysfs_mbox.offset = 0;
|
|
|
-
|
|
|
- if (phba->sysfs_mbox.mbox) {
|
|
|
- mempool_free(phba->sysfs_mbox.mbox,
|
|
|
- phba->mbox_mem_pool);
|
|
|
- phba->sysfs_mbox.mbox = NULL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* sysfs_mbox_write - Write method for writing information via mbox
|
|
|
* @filp: open sysfs file
|
|
@@ -4014,71 +4088,18 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
|
|
|
* @count: bytes to transfer.
|
|
|
*
|
|
|
* Description:
|
|
|
- * Accessed via /sys/class/scsi_host/hostxxx/mbox.
|
|
|
- * Uses the sysfs mbox to send buf contents to the adapter.
|
|
|
+ * Deprecated function. All mailbox access from user space is performed via the
|
|
|
+ * bsg interface.
|
|
|
*
|
|
|
* Returns:
|
|
|
- * -ERANGE off and count combo out of range
|
|
|
- * -EINVAL off, count or buff address invalid
|
|
|
- * zero if count is zero
|
|
|
- * -EPERM adapter is offline
|
|
|
- * -ENOMEM failed to allocate memory for the mail box
|
|
|
- * -EAGAIN offset, state or mbox is NULL
|
|
|
- * count number of bytes transferred
|
|
|
+ * -EPERM operation not permitted
|
|
|
**/
|
|
|
static ssize_t
|
|
|
sysfs_mbox_write(struct file *filp, struct kobject *kobj,
|
|
|
struct bin_attribute *bin_attr,
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
{
|
|
|
- struct device *dev = container_of(kobj, struct device, kobj);
|
|
|
- struct Scsi_Host *shost = class_to_shost(dev);
|
|
|
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
|
|
- struct lpfc_hba *phba = vport->phba;
|
|
|
- struct lpfcMboxq *mbox = NULL;
|
|
|
-
|
|
|
- if ((count + off) > MAILBOX_CMD_SIZE)
|
|
|
- return -ERANGE;
|
|
|
-
|
|
|
- if (off % 4 || count % 4 || (unsigned long)buf % 4)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (count == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (off == 0) {
|
|
|
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
|
|
- if (!mbox)
|
|
|
- return -ENOMEM;
|
|
|
- memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
|
|
|
- }
|
|
|
-
|
|
|
- spin_lock_irq(&phba->hbalock);
|
|
|
-
|
|
|
- if (off == 0) {
|
|
|
- if (phba->sysfs_mbox.mbox)
|
|
|
- mempool_free(mbox, phba->mbox_mem_pool);
|
|
|
- else
|
|
|
- phba->sysfs_mbox.mbox = mbox;
|
|
|
- phba->sysfs_mbox.state = SMBOX_WRITING;
|
|
|
- } else {
|
|
|
- if (phba->sysfs_mbox.state != SMBOX_WRITING ||
|
|
|
- phba->sysfs_mbox.offset != off ||
|
|
|
- phba->sysfs_mbox.mbox == NULL) {
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EAGAIN;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- memcpy((uint8_t *) &phba->sysfs_mbox.mbox->u.mb + off,
|
|
|
- buf, count);
|
|
|
-
|
|
|
- phba->sysfs_mbox.offset = off + count;
|
|
|
-
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
-
|
|
|
- return count;
|
|
|
+ return -EPERM;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -4091,201 +4112,18 @@ sysfs_mbox_write(struct file *filp, struct kobject *kobj,
|
|
|
* @count: bytes to transfer.
|
|
|
*
|
|
|
* Description:
|
|
|
- * Accessed via /sys/class/scsi_host/hostxxx/mbox.
|
|
|
- * Uses the sysfs mbox to receive data from to the adapter.
|
|
|
+ * Deprecated function. All mailbox access from user space is performed via the
|
|
|
+ * bsg interface.
|
|
|
*
|
|
|
* Returns:
|
|
|
- * -ERANGE off greater than mailbox command size
|
|
|
- * -EINVAL off, count or buff address invalid
|
|
|
- * zero if off and count are zero
|
|
|
- * -EACCES adapter over temp
|
|
|
- * -EPERM garbage can value to catch a multitude of errors
|
|
|
- * -EAGAIN management IO not permitted, state or off error
|
|
|
- * -ETIME mailbox timeout
|
|
|
- * -ENODEV mailbox error
|
|
|
- * count number of bytes transferred
|
|
|
+ * -EPERM operation not permitted
|
|
|
**/
|
|
|
static ssize_t
|
|
|
sysfs_mbox_read(struct file *filp, struct kobject *kobj,
|
|
|
struct bin_attribute *bin_attr,
|
|
|
char *buf, loff_t off, size_t count)
|
|
|
{
|
|
|
- struct device *dev = container_of(kobj, struct device, kobj);
|
|
|
- struct Scsi_Host *shost = class_to_shost(dev);
|
|
|
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
|
|
- struct lpfc_hba *phba = vport->phba;
|
|
|
- LPFC_MBOXQ_t *mboxq;
|
|
|
- MAILBOX_t *pmb;
|
|
|
- uint32_t mbox_tmo;
|
|
|
- int rc;
|
|
|
-
|
|
|
- if (off > MAILBOX_CMD_SIZE)
|
|
|
- return -ERANGE;
|
|
|
-
|
|
|
- if ((count + off) > MAILBOX_CMD_SIZE)
|
|
|
- count = MAILBOX_CMD_SIZE - off;
|
|
|
-
|
|
|
- if (off % 4 || count % 4 || (unsigned long)buf % 4)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (off && count == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- spin_lock_irq(&phba->hbalock);
|
|
|
-
|
|
|
- if (phba->over_temp_state == HBA_OVER_TEMP) {
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EACCES;
|
|
|
- }
|
|
|
-
|
|
|
- if (off == 0 &&
|
|
|
- phba->sysfs_mbox.state == SMBOX_WRITING &&
|
|
|
- phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) {
|
|
|
- mboxq = (LPFC_MBOXQ_t *)&phba->sysfs_mbox.mbox;
|
|
|
- pmb = &mboxq->u.mb;
|
|
|
- switch (pmb->mbxCommand) {
|
|
|
- /* Offline only */
|
|
|
- case MBX_INIT_LINK:
|
|
|
- case MBX_DOWN_LINK:
|
|
|
- case MBX_CONFIG_LINK:
|
|
|
- case MBX_CONFIG_RING:
|
|
|
- case MBX_RESET_RING:
|
|
|
- case MBX_UNREG_LOGIN:
|
|
|
- case MBX_CLEAR_LA:
|
|
|
- case MBX_DUMP_CONTEXT:
|
|
|
- case MBX_RUN_DIAGS:
|
|
|
- case MBX_RESTART:
|
|
|
- case MBX_SET_MASK:
|
|
|
- case MBX_SET_DEBUG:
|
|
|
- if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
|
|
|
- printk(KERN_WARNING "mbox_read:Command 0x%x "
|
|
|
- "is illegal in on-line state\n",
|
|
|
- pmb->mbxCommand);
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EPERM;
|
|
|
- }
|
|
|
- case MBX_WRITE_NV:
|
|
|
- case MBX_WRITE_VPARMS:
|
|
|
- case MBX_LOAD_SM:
|
|
|
- case MBX_READ_NV:
|
|
|
- case MBX_READ_CONFIG:
|
|
|
- case MBX_READ_RCONFIG:
|
|
|
- case MBX_READ_STATUS:
|
|
|
- case MBX_READ_XRI:
|
|
|
- case MBX_READ_REV:
|
|
|
- case MBX_READ_LNK_STAT:
|
|
|
- case MBX_DUMP_MEMORY:
|
|
|
- case MBX_DOWN_LOAD:
|
|
|
- case MBX_UPDATE_CFG:
|
|
|
- case MBX_KILL_BOARD:
|
|
|
- case MBX_LOAD_AREA:
|
|
|
- case MBX_LOAD_EXP_ROM:
|
|
|
- case MBX_BEACON:
|
|
|
- case MBX_DEL_LD_ENTRY:
|
|
|
- case MBX_SET_VARIABLE:
|
|
|
- case MBX_WRITE_WWN:
|
|
|
- case MBX_PORT_CAPABILITIES:
|
|
|
- case MBX_PORT_IOV_CONTROL:
|
|
|
- break;
|
|
|
- case MBX_SECURITY_MGMT:
|
|
|
- case MBX_AUTH_PORT:
|
|
|
- if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
|
|
|
- printk(KERN_WARNING "mbox_read:Command 0x%x "
|
|
|
- "is not permitted\n", pmb->mbxCommand);
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EPERM;
|
|
|
- }
|
|
|
- break;
|
|
|
- case MBX_READ_SPARM64:
|
|
|
- case MBX_READ_TOPOLOGY:
|
|
|
- case MBX_REG_LOGIN:
|
|
|
- case MBX_REG_LOGIN64:
|
|
|
- case MBX_CONFIG_PORT:
|
|
|
- case MBX_RUN_BIU_DIAG:
|
|
|
- printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
|
|
|
- pmb->mbxCommand);
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EPERM;
|
|
|
- default:
|
|
|
- printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
|
|
|
- pmb->mbxCommand);
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EPERM;
|
|
|
- }
|
|
|
-
|
|
|
- /* If HBA encountered an error attention, allow only DUMP
|
|
|
- * or RESTART mailbox commands until the HBA is restarted.
|
|
|
- */
|
|
|
- if (phba->pport->stopped &&
|
|
|
- pmb->mbxCommand != MBX_DUMP_MEMORY &&
|
|
|
- pmb->mbxCommand != MBX_RESTART &&
|
|
|
- pmb->mbxCommand != MBX_WRITE_VPARMS &&
|
|
|
- pmb->mbxCommand != MBX_WRITE_WWN)
|
|
|
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
|
|
|
- "1259 mbox: Issued mailbox cmd "
|
|
|
- "0x%x while in stopped state.\n",
|
|
|
- pmb->mbxCommand);
|
|
|
-
|
|
|
- phba->sysfs_mbox.mbox->vport = vport;
|
|
|
-
|
|
|
- /* Don't allow mailbox commands to be sent when blocked
|
|
|
- * or when in the middle of discovery
|
|
|
- */
|
|
|
- if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EAGAIN;
|
|
|
- }
|
|
|
-
|
|
|
- if ((vport->fc_flag & FC_OFFLINE_MODE) ||
|
|
|
- (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) {
|
|
|
-
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- rc = lpfc_sli_issue_mbox (phba,
|
|
|
- phba->sysfs_mbox.mbox,
|
|
|
- MBX_POLL);
|
|
|
- spin_lock_irq(&phba->hbalock);
|
|
|
-
|
|
|
- } else {
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
|
|
|
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
|
|
|
- spin_lock_irq(&phba->hbalock);
|
|
|
- }
|
|
|
-
|
|
|
- if (rc != MBX_SUCCESS) {
|
|
|
- if (rc == MBX_TIMEOUT) {
|
|
|
- phba->sysfs_mbox.mbox = NULL;
|
|
|
- }
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
|
|
|
- }
|
|
|
- phba->sysfs_mbox.state = SMBOX_READING;
|
|
|
- }
|
|
|
- else if (phba->sysfs_mbox.offset != off ||
|
|
|
- phba->sysfs_mbox.state != SMBOX_READING) {
|
|
|
- printk(KERN_WARNING "mbox_read: Bad State\n");
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
- return -EAGAIN;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy(buf, (uint8_t *) &pmb + off, count);
|
|
|
-
|
|
|
- phba->sysfs_mbox.offset = off + count;
|
|
|
-
|
|
|
- if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
|
|
|
- sysfs_mbox_idle(phba);
|
|
|
-
|
|
|
- spin_unlock_irq(&phba->hbalock);
|
|
|
-
|
|
|
- return count;
|
|
|
+ return -EPERM;
|
|
|
}
|
|
|
|
|
|
static struct bin_attribute sysfs_mbox_attr = {
|
|
@@ -4429,8 +4267,13 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
|
|
|
case LPFC_LINK_UP:
|
|
|
case LPFC_CLEAR_LA:
|
|
|
case LPFC_HBA_READY:
|
|
|
- /* Links up, beyond this port_type reports state */
|
|
|
- fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
|
|
|
+ /* Links up, reports port state accordingly */
|
|
|
+ if (vport->port_state < LPFC_VPORT_READY)
|
|
|
+ fc_host_port_state(shost) =
|
|
|
+ FC_PORTSTATE_BYPASSED;
|
|
|
+ else
|
|
|
+ fc_host_port_state(shost) =
|
|
|
+ FC_PORTSTATE_ONLINE;
|
|
|
break;
|
|
|
case LPFC_HBA_ERROR:
|
|
|
fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
|