diff options
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r-- | drivers/scsi/isci/init.c | 191 |
1 files changed, 27 insertions, 164 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 3f2bb137bcb1..65519321e1cc 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -56,12 +56,15 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/firmware.h> +#include <linux/efi.h> #include <asm/string.h> #include "isci.h" #include "task.h" #include "sci_controller_constants.h" #include "scic_remote_device.h" #include "sci_environment.h" +#include "probe_roms.h" static struct scsi_transport_template *isci_transport_template; @@ -373,85 +376,6 @@ static int isci_setup_interrupts(struct pci_dev *pdev) return err; } -/** - * isci_parse_oem_parameters() - This method will take OEM parameters - * from the module init parameters and copy them to oem_params. This will - * only copy values that are not set to the module parameter default values - * @oem_parameters: This parameter specifies the controller default OEM - * parameters. It is expected that this has been initialized to the default - * parameters for the controller - * - * - */ -enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, - int scu_index, - struct isci_firmware *fw) -{ - int i; - - /* check for valid inputs */ - if (!(scu_index >= 0 - && scu_index < SCI_MAX_CONTROLLERS - && oem_params != NULL)) { - return SCI_FAILURE; - } - - for (i = 0; i < SCI_MAX_PHYS; i++) { - int array_idx = i + (SCI_MAX_PHYS * scu_index); - u64 sas_addr = fw->sas_addrs[array_idx]; - - if (sas_addr != 0) { - oem_params->sds1.phys[i].sas_address.low = - (u32)(sas_addr & 0xffffffff); - oem_params->sds1.phys[i].sas_address.high = - (u32)((sas_addr >> 32) & 0xffffffff); - } - } - - for (i = 0; i < SCI_MAX_PORTS; i++) { - int array_idx = i + (SCI_MAX_PORTS * scu_index); - u32 pmask = fw->phy_masks[array_idx]; - - oem_params->sds1.ports[i].phy_mask = pmask; - } - - return SCI_SUCCESS; -} - -/** - * isci_parse_user_parameters() - This method will take user parameters - * from the module init parameters and copy them to user_params. This will - * only copy values that are not set to the module parameter default values - * @user_parameters: This parameter specifies the controller default user - * parameters. It is expected that this has been initialized to the default - * parameters for the controller - * - * - */ -enum sci_status isci_parse_user_parameters( - union scic_user_parameters *user_params, - int scu_index, - struct isci_firmware *fw) -{ - int i; - - if (!(scu_index >= 0 - && scu_index < SCI_MAX_CONTROLLERS - && user_params != NULL)) { - return SCI_FAILURE; - } - - for (i = 0; i < SCI_MAX_PORTS; i++) { - int array_idx = i + (SCI_MAX_PORTS * scu_index); - u32 gen = fw->phy_gens[array_idx]; - - user_params->sds1.phys[i].max_speed_generation = gen; - - } - - return SCI_SUCCESS; -} - static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) { struct isci_host *isci_host; @@ -535,73 +459,13 @@ static void check_si_rev(struct pci_dev *pdev) } -static int isci_verify_firmware(const struct firmware *fw, - struct isci_firmware *isci_fw) -{ - const u8 *tmp; - - if (fw->size < ISCI_FIRMWARE_MIN_SIZE) - return -EINVAL; - - tmp = fw->data; - - /* 12th char should be the NULL terminate for the ID string */ - if (tmp[11] != '\0') - return -EINVAL; - - if (strncmp("#SCU MAGIC#", tmp, 11) != 0) - return -EINVAL; - - isci_fw->id = tmp; - isci_fw->version = fw->data[ISCI_FW_VER_OFS]; - isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; - - tmp = fw->data + ISCI_FW_DATA_OFS; - - while (*tmp != ISCI_FW_HDR_EOF) { - switch (*tmp) { - case ISCI_FW_HDR_PHYMASK: - tmp++; - isci_fw->phy_masks_size = *tmp; - tmp++; - isci_fw->phy_masks = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_masks_size; - break; - - case ISCI_FW_HDR_PHYGEN: - tmp++; - isci_fw->phy_gens_size = *tmp; - tmp++; - isci_fw->phy_gens = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_gens_size; - break; - - case ISCI_FW_HDR_SASADDR: - tmp++; - isci_fw->sas_addrs_size = *tmp; - tmp++; - isci_fw->sas_addrs = (const u64 *)tmp; - tmp += sizeof(u64) * isci_fw->sas_addrs_size; - break; - - default: - pr_err("bad field in firmware binary blob\n"); - return -EINVAL; - } - } - - pr_info("isci firmware v%u.%u loaded.\n", - isci_fw->version, isci_fw->subversion); - - return SCI_SUCCESS; -} - static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct isci_pci_info *pci_info; int err, i; struct isci_host *isci_host; const struct firmware *fw = NULL; + struct isci_orom *orom; check_si_rev(pdev); @@ -610,33 +474,32 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); - err = request_firmware(&fw, ISCI_FW_NAME, &pdev->dev); - if (err) { - dev_warn(&pdev->dev, - "Loading firmware failed, using default values\n"); - dev_warn(&pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS Addresses\n"); - } else { - isci_firmware = devm_kzalloc(&pdev->dev, - sizeof(struct isci_firmware), - GFP_KERNEL); - if (isci_firmware) { - err = isci_verify_firmware(fw, isci_firmware); - if (err != SCI_SUCCESS) { - dev_warn(&pdev->dev, - "firmware verification failed\n"); - dev_warn(&pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS " - "Addresses\n"); - devm_kfree(&pdev->dev, isci_firmware); - isci_firmware = NULL; - } + if (efi_enabled) { + /* do EFI parsing here */ + orom = NULL; + } else + orom = isci_request_oprom(pdev); + + if (!orom) { + orom = isci_request_firmware(pdev, fw); + if (!orom) { + /* TODO convert this to WARN_TAINT_ONCE once the + * orom/efi parameter support is widely available + */ + dev_warn(&pdev->dev, + "Loading user firmware failed, using default " + "values\n"); + dev_warn(&pdev->dev, + "Default OEM configuration being used: 4 " + "narrow ports, and default SAS Addresses\n"); } - release_firmware(fw); } + if (orom) + dev_info(&pdev->dev, "sas parameters (version: %#x) loaded\n", + orom->hdr.version); + pci_info->orom = orom; + err = isci_pci_init(pdev); if (err) return err; |