aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2012-10-31 14:44:33 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-11-26 23:59:43 -0500
commitc71ab8616d62d8d857c438f058839d9a0282e64c (patch)
tree1c5f1029704ad8c64c13d15e274a77760bd46dbb /drivers/scsi
parent286aa031664ba5223bcb3dfd49a9e2d89d6b3aec (diff)
[SCSI] lpfc 8.3.36: Fixed boot from san failure
Fixed boot from san failure when SLI4 FC device presented on the same PCI bus The request_firmware interface can induce delays while looking for firmware files, even if no fw file is present. In some situations the delays exceeded scan_wait timeouts, resulting in situations in which the boot device had not been discovered in time. Boot Device does not need to be on a lpfc device. Change request_firmware use to be module paramater driven. Default is to not attempt firmware download on boot. Add sysfs parameter to invoke firmware update. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c73
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c55
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h3
5 files changed, 120 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 69b59935b53f..d0ed6c19a9aa 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -714,6 +714,7 @@ struct lpfc_hba {
714 uint32_t cfg_log_verbose; 714 uint32_t cfg_log_verbose;
715 uint32_t cfg_aer_support; 715 uint32_t cfg_aer_support;
716 uint32_t cfg_sriov_nr_virtfn; 716 uint32_t cfg_sriov_nr_virtfn;
717 uint32_t cfg_request_firmware_upgrade;
717 uint32_t cfg_iocb_cnt; 718 uint32_t cfg_iocb_cnt;
718 uint32_t cfg_suppress_link_up; 719 uint32_t cfg_suppress_link_up;
719#define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ 720#define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index ad16e54ac383..a71c7ebe7b74 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3618,6 +3618,77 @@ static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR,
3618 lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); 3618 lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store);
3619 3619
3620/** 3620/**
3621 * lpfc_request_firmware_store - Request for Linux generic firmware upgrade
3622 *
3623 * @dev: class device that is converted into a Scsi_host.
3624 * @attr: device attribute, not used.
3625 * @buf: containing the string the number of vfs to be enabled.
3626 * @count: unused variable.
3627 *
3628 * Description:
3629 *
3630 * Returns:
3631 * length of the buf on success if val is in range the intended mode
3632 * is supported.
3633 * -EINVAL if val out of range or intended mode is not supported.
3634 **/
3635static ssize_t
3636lpfc_request_firmware_upgrade_store(struct device *dev,
3637 struct device_attribute *attr,
3638 const char *buf, size_t count)
3639{
3640 struct Scsi_Host *shost = class_to_shost(dev);
3641 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
3642 struct lpfc_hba *phba = vport->phba;
3643 int val = 0, rc = -EINVAL;
3644
3645 /* Sanity check on user data */
3646 if (!isdigit(buf[0]))
3647 return -EINVAL;
3648 if (sscanf(buf, "%i", &val) != 1)
3649 return -EINVAL;
3650 if (val != 1)
3651 return -EINVAL;
3652
3653 rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE);
3654 if (rc)
3655 rc = -EPERM;
3656 else
3657 rc = strlen(buf);
3658 return rc;
3659}
3660
3661static int lpfc_req_fw_upgrade;
3662module_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR);
3663MODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade");
3664lpfc_param_show(request_firmware_upgrade)
3665
3666/**
3667 * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade
3668 * @phba: lpfc_hba pointer.
3669 * @val: 0 or 1.
3670 *
3671 * Description:
3672 * Set the initial Linux generic firmware upgrade enable or disable flag.
3673 *
3674 * Returns:
3675 * zero if val saved.
3676 * -EINVAL val out of range
3677 **/
3678static int
3679lpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val)
3680{
3681 if (val >= 0 && val <= 1) {
3682 phba->cfg_request_firmware_upgrade = val;
3683 return 0;
3684 }
3685 return -EINVAL;
3686}
3687static DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR,
3688 lpfc_request_firmware_upgrade_show,
3689 lpfc_request_firmware_upgrade_store);
3690
3691/**
3621 * lpfc_fcp_imax_store 3692 * lpfc_fcp_imax_store
3622 * 3693 *
3623 * @dev: class device that is converted into a Scsi_host. 3694 * @dev: class device that is converted into a Scsi_host.
@@ -4069,6 +4140,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
4069 &dev_attr_lpfc_aer_support, 4140 &dev_attr_lpfc_aer_support,
4070 &dev_attr_lpfc_aer_state_cleanup, 4141 &dev_attr_lpfc_aer_state_cleanup,
4071 &dev_attr_lpfc_sriov_nr_virtfn, 4142 &dev_attr_lpfc_sriov_nr_virtfn,
4143 &dev_attr_lpfc_req_fw_upgrade,
4072 &dev_attr_lpfc_suppress_link_up, 4144 &dev_attr_lpfc_suppress_link_up,
4073 &dev_attr_lpfc_iocb_cnt, 4145 &dev_attr_lpfc_iocb_cnt,
4074 &dev_attr_iocb_hw, 4146 &dev_attr_iocb_hw,
@@ -5051,6 +5123,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
5051 lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); 5123 lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
5052 lpfc_aer_support_init(phba, lpfc_aer_support); 5124 lpfc_aer_support_init(phba, lpfc_aer_support);
5053 lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); 5125 lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
5126 lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
5054 lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); 5127 lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
5055 lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); 5128 lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
5056 phba->cfg_enable_dss = 1; 5129 phba->cfg_enable_dss = 1;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 4380a44000bc..69d66e3662cb 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -468,3 +468,4 @@ void lpfc_sli4_node_prep(struct lpfc_hba *);
468int lpfc_sli4_xri_sgl_update(struct lpfc_hba *); 468int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
469void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *); 469void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
470uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *); 470uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
471int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7dc4218d9c4c..d89569307416 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9450,7 +9450,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
9450 struct lpfc_dmabuf *dmabuf, *next; 9450 struct lpfc_dmabuf *dmabuf, *next;
9451 uint32_t offset = 0, temp_offset = 0; 9451 uint32_t offset = 0, temp_offset = 0;
9452 9452
9453 /* It can be null, sanity check */ 9453 /* It can be null in no-wait mode, sanity check */
9454 if (!fw) { 9454 if (!fw) {
9455 rc = -ENXIO; 9455 rc = -ENXIO;
9456 goto out; 9456 goto out;
@@ -9528,11 +9528,48 @@ release_out:
9528 release_firmware(fw); 9528 release_firmware(fw);
9529out: 9529out:
9530 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 9530 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
9531 "3024 Firmware update done: %d.", rc); 9531 "3024 Firmware update done: %d.\n", rc);
9532 return; 9532 return;
9533} 9533}
9534 9534
9535/** 9535/**
9536 * lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade
9537 * @phba: pointer to lpfc hba data structure.
9538 *
9539 * This routine is called to perform Linux generic firmware upgrade on device
9540 * that supports such feature.
9541 **/
9542int
9543lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
9544{
9545 uint8_t file_name[ELX_MODEL_NAME_SIZE];
9546 int ret;
9547 const struct firmware *fw;
9548
9549 /* Only supported on SLI4 interface type 2 for now */
9550 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
9551 LPFC_SLI_INTF_IF_TYPE_2)
9552 return -EPERM;
9553
9554 snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName);
9555
9556 if (fw_upgrade == INT_FW_UPGRADE) {
9557 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
9558 file_name, &phba->pcidev->dev,
9559 GFP_KERNEL, (void *)phba,
9560 lpfc_write_firmware);
9561 } else if (fw_upgrade == RUN_FW_UPGRADE) {
9562 ret = request_firmware(&fw, file_name, &phba->pcidev->dev);
9563 if (!ret)
9564 lpfc_write_firmware(fw, (void *)phba);
9565 } else {
9566 ret = -EINVAL;
9567 }
9568
9569 return ret;
9570}
9571
9572/**
9536 * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys 9573 * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys
9537 * @pdev: pointer to PCI device 9574 * @pdev: pointer to PCI device
9538 * @pid: pointer to PCI device identifier 9575 * @pid: pointer to PCI device identifier
@@ -9560,7 +9597,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
9560 uint32_t cfg_mode, intr_mode; 9597 uint32_t cfg_mode, intr_mode;
9561 int mcnt; 9598 int mcnt;
9562 int adjusted_fcp_io_channel; 9599 int adjusted_fcp_io_channel;
9563 uint8_t file_name[ELX_MODEL_NAME_SIZE];
9564 9600
9565 /* Allocate memory for HBA structure */ 9601 /* Allocate memory for HBA structure */
9566 phba = lpfc_hba_alloc(pdev); 9602 phba = lpfc_hba_alloc(pdev);
@@ -9703,16 +9739,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
9703 /* Perform post initialization setup */ 9739 /* Perform post initialization setup */
9704 lpfc_post_init_setup(phba); 9740 lpfc_post_init_setup(phba);
9705 9741
9706 /* check for firmware upgrade or downgrade (if_type 2 only) */ 9742 /* check for firmware upgrade or downgrade */
9707 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == 9743 if (phba->cfg_request_firmware_upgrade)
9708 LPFC_SLI_INTF_IF_TYPE_2) { 9744 ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
9709 snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp",
9710 phba->ModelName);
9711 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
9712 file_name, &phba->pcidev->dev,
9713 GFP_KERNEL, (void *)phba,
9714 lpfc_write_firmware);
9715 }
9716 9745
9717 /* Check if there are static vports to be created. */ 9746 /* Check if there are static vports to be created. */
9718 lpfc_create_static_vport(phba); 9747 lpfc_create_static_vport(phba);
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index f44a06a4c6e7..44c427a45d66 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -82,6 +82,9 @@
82 82
83#define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000 83#define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
84 84
85#define INT_FW_UPGRADE 0
86#define RUN_FW_UPGRADE 1
87
85enum lpfc_sli4_queue_type { 88enum lpfc_sli4_queue_type {
86 LPFC_EQ, 89 LPFC_EQ,
87 LPFC_GCQ, 90 LPFC_GCQ,