aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/isci/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r--drivers/scsi/isci/init.c191
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;