aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-05-24 11:42:45 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-26 23:49:37 -0400
commit52d5244096017bbd11164479116baceaede342b0 (patch)
tree1e61c05ab7f1babd2ed44f6136bc6f9384d9f786 /drivers/scsi/lpfc/lpfc_init.c
parent912e3acde60b3b9ebf46c5ec5ae6bd01b80132c8 (diff)
[SCSI] lpfc 8.3.24: Add request-firmware support
Add request-firmware support: - Add support for request_firmware interface for INTF2 SLI4 ports. - Add ability to reset SLI4 INTF2 ports. Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> 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.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e81912cd257e..2b535cff4b2a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -30,6 +30,7 @@
30#include <linux/ctype.h> 30#include <linux/ctype.h>
31#include <linux/aer.h> 31#include <linux/aer.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/firmware.h>
33 34
34#include <scsi/scsi.h> 35#include <scsi/scsi.h>
35#include <scsi/scsi_device.h> 36#include <scsi/scsi_device.h>
@@ -8775,6 +8776,97 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
8775} 8776}
8776 8777
8777/** 8778/**
8779 * lpfc_write_firmware - attempt to write a firmware image to the port
8780 * @phba: pointer to lpfc hba data structure.
8781 * @fw: pointer to firmware image returned from request_firmware.
8782 *
8783 * returns the number of bytes written if write is successful.
8784 * returns a negative error value if there were errors.
8785 * returns 0 if firmware matches currently active firmware on port.
8786 **/
8787int
8788lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
8789{
8790 char fwrev[32];
8791 struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data;
8792 struct list_head dma_buffer_list;
8793 int i, rc = 0;
8794 struct lpfc_dmabuf *dmabuf, *next;
8795 uint32_t offset = 0, temp_offset = 0;
8796
8797 INIT_LIST_HEAD(&dma_buffer_list);
8798 if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) ||
8799 (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) ||
8800 (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
8801 (image->size != fw->size)) {
8802 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8803 "3022 Invalid FW image found. "
8804 "Magic:%d Type:%x ID:%x\n",
8805 image->magic_number,
8806 bf_get(lpfc_grp_hdr_file_type, image),
8807 bf_get(lpfc_grp_hdr_id, image));
8808 return -EINVAL;
8809 }
8810 lpfc_decode_firmware_rev(phba, fwrev, 1);
8811 if (strncmp(fwrev, image->rev_name, strnlen(fwrev, 16))) {
8812 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8813 "3023 Updating Firmware. Current Version:%s "
8814 "New Version:%s\n",
8815 fwrev, image->rev_name);
8816 for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) {
8817 dmabuf = kzalloc(sizeof(struct lpfc_dmabuf),
8818 GFP_KERNEL);
8819 if (!dmabuf) {
8820 rc = -ENOMEM;
8821 goto out;
8822 }
8823 dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
8824 SLI4_PAGE_SIZE,
8825 &dmabuf->phys,
8826 GFP_KERNEL);
8827 if (!dmabuf->virt) {
8828 kfree(dmabuf);
8829 rc = -ENOMEM;
8830 goto out;
8831 }
8832 list_add_tail(&dmabuf->list, &dma_buffer_list);
8833 }
8834 while (offset < fw->size) {
8835 temp_offset = offset;
8836 list_for_each_entry(dmabuf, &dma_buffer_list, list) {
8837 if (offset + SLI4_PAGE_SIZE > fw->size) {
8838 temp_offset += fw->size - offset;
8839 memcpy(dmabuf->virt,
8840 fw->data + temp_offset,
8841 fw->size - offset);
8842 break;
8843 }
8844 temp_offset += SLI4_PAGE_SIZE;
8845 memcpy(dmabuf->virt, fw->data + temp_offset,
8846 SLI4_PAGE_SIZE);
8847 }
8848 rc = lpfc_wr_object(phba, &dma_buffer_list,
8849 (fw->size - offset), &offset);
8850 if (rc) {
8851 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8852 "3024 Firmware update failed. "
8853 "%d\n", rc);
8854 goto out;
8855 }
8856 }
8857 rc = offset;
8858 }
8859out:
8860 list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) {
8861 list_del(&dmabuf->list);
8862 dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE,
8863 dmabuf->virt, dmabuf->phys);
8864 kfree(dmabuf);
8865 }
8866 return rc;
8867}
8868
8869/**
8778 * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys 8870 * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys
8779 * @pdev: pointer to PCI device 8871 * @pdev: pointer to PCI device
8780 * @pid: pointer to PCI device identifier 8872 * @pid: pointer to PCI device identifier
@@ -8803,6 +8895,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
8803 int mcnt; 8895 int mcnt;
8804 int adjusted_fcp_eq_count; 8896 int adjusted_fcp_eq_count;
8805 int fcp_qidx; 8897 int fcp_qidx;
8898 const struct firmware *fw;
8899 uint8_t file_name[16];
8806 8900
8807 /* Allocate memory for HBA structure */ 8901 /* Allocate memory for HBA structure */
8808 phba = lpfc_hba_alloc(pdev); 8902 phba = lpfc_hba_alloc(pdev);
@@ -8957,6 +9051,14 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
8957 /* Perform post initialization setup */ 9051 /* Perform post initialization setup */
8958 lpfc_post_init_setup(phba); 9052 lpfc_post_init_setup(phba);
8959 9053
9054 /* check for firmware upgrade or downgrade */
9055 snprintf(file_name, 16, "%s.grp", phba->ModelName);
9056 error = request_firmware(&fw, file_name, &phba->pcidev->dev);
9057 if (!error) {
9058 lpfc_write_firmware(phba, fw);
9059 release_firmware(fw);
9060 }
9061
8960 /* Check if there are static vports to be created. */ 9062 /* Check if there are static vports to be created. */
8961 lpfc_create_static_vport(phba); 9063 lpfc_create_static_vport(phba);
8962 9064