diff options
author | James Smart <james.smart@emulex.com> | 2012-10-31 14:44:33 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-11-27 08:59:43 +0400 |
commit | c71ab8616d62d8d857c438f058839d9a0282e64c (patch) | |
tree | 1c5f1029704ad8c64c13d15e274a77760bd46dbb /drivers/scsi/lpfc/lpfc_init.c | |
parent | 286aa031664ba5223bcb3dfd49a9e2d89d6b3aec (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/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 55 |
1 files changed, 42 insertions, 13 deletions
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) struct lpfc_dmabuf *dmabuf, *next; uint32_t offset = 0, temp_offset = 0; - /* It can be null, sanity check */ + /* It can be null in no-wait mode, sanity check */ if (!fw) { rc = -ENXIO; goto out; @@ -9528,11 +9528,48 @@ release_out: release_firmware(fw); out: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "3024 Firmware update done: %d.", rc); + "3024 Firmware update done: %d.\n", rc); return; } /** + * lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade + * @phba: pointer to lpfc hba data structure. + * + * This routine is called to perform Linux generic firmware upgrade on device + * that supports such feature. + **/ +int +lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade) +{ + uint8_t file_name[ELX_MODEL_NAME_SIZE]; + int ret; + const struct firmware *fw; + + /* Only supported on SLI4 interface type 2 for now */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + LPFC_SLI_INTF_IF_TYPE_2) + return -EPERM; + + snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName); + + if (fw_upgrade == INT_FW_UPGRADE) { + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + file_name, &phba->pcidev->dev, + GFP_KERNEL, (void *)phba, + lpfc_write_firmware); + } else if (fw_upgrade == RUN_FW_UPGRADE) { + ret = request_firmware(&fw, file_name, &phba->pcidev->dev); + if (!ret) + lpfc_write_firmware(fw, (void *)phba); + } else { + ret = -EINVAL; + } + + return ret; +} + +/** * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys * @pdev: pointer to PCI device * @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) uint32_t cfg_mode, intr_mode; int mcnt; int adjusted_fcp_io_channel; - uint8_t file_name[ELX_MODEL_NAME_SIZE]; /* Allocate memory for HBA structure */ phba = lpfc_hba_alloc(pdev); @@ -9703,16 +9739,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Perform post initialization setup */ lpfc_post_init_setup(phba); - /* check for firmware upgrade or downgrade (if_type 2 only) */ - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == - LPFC_SLI_INTF_IF_TYPE_2) { - snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", - phba->ModelName); - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - file_name, &phba->pcidev->dev, - GFP_KERNEL, (void *)phba, - lpfc_write_firmware); - } + /* check for firmware upgrade or downgrade */ + if (phba->cfg_request_firmware_upgrade) + ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE); /* Check if there are static vports to be created. */ lpfc_create_static_vport(phba); |