aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/init.c
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2011-02-22 04:27:03 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:27 -0400
commit858d4aa741c80fb7579cda3517853f0cffc73772 (patch)
treedb0bc07852d91c5817315d37a8e5923898192d52 /drivers/scsi/isci/init.c
parent92cd51153d5c18af027ddf42547d59ba4167873c (diff)
isci: Move firmware loading to per PCI device
Moved the firmware loading from per adapter to per PCI device. This should prevent firmware from being loaded twice becuase of 2 SCU controller per PCI device. We do have to do it per PCI device because request_firmware() requires a struct device passed in. Signed-off-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/init.c')
-rw-r--r--drivers/scsi/isci/init.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index fda26292ba2b..6ca623aff051 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -82,6 +82,8 @@ static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
82 {} 82 {}
83}; 83};
84 84
85struct isci_firmware *isci_firmware;
86
85static int __devinit isci_pci_probe( 87static int __devinit isci_pci_probe(
86 struct pci_dev *pdev, 88 struct pci_dev *pdev,
87 const struct pci_device_id *device_id_p); 89 const struct pci_device_id *device_id_p);
@@ -519,11 +521,73 @@ static void check_si_rev(struct pci_dev *pdev)
519 521
520} 522}
521 523
524static int isci_verify_firmware(const struct firmware *fw,
525 struct isci_firmware *isci_fw)
526{
527 const u8 *tmp;
528
529 if (fw->size < ISCI_FIRMWARE_MIN_SIZE)
530 return -EINVAL;
531
532 tmp = fw->data;
533
534 /* 12th char should be the NULL terminate for the ID string */
535 if (tmp[11] != '\0')
536 return -EINVAL;
537
538 if (strncmp("#SCU MAGIC#", tmp, 11) != 0)
539 return -EINVAL;
540
541 isci_fw->id = tmp;
542 isci_fw->version = fw->data[ISCI_FW_VER_OFS];
543 isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS];
544
545 tmp = fw->data + ISCI_FW_DATA_OFS;
546
547 while (*tmp != ISCI_FW_HDR_EOF) {
548 switch (*tmp) {
549 case ISCI_FW_HDR_PHYMASK:
550 tmp++;
551 isci_fw->phy_masks_size = *tmp;
552 tmp++;
553 isci_fw->phy_masks = (const u32 *)tmp;
554 tmp += sizeof(u32) * isci_fw->phy_masks_size;
555 break;
556
557 case ISCI_FW_HDR_PHYGEN:
558 tmp++;
559 isci_fw->phy_gens_size = *tmp;
560 tmp++;
561 isci_fw->phy_gens = (const u32 *)tmp;
562 tmp += sizeof(u32) * isci_fw->phy_gens_size;
563 break;
564
565 case ISCI_FW_HDR_SASADDR:
566 tmp++;
567 isci_fw->sas_addrs_size = *tmp;
568 tmp++;
569 isci_fw->sas_addrs = (const u64 *)tmp;
570 tmp += sizeof(u64) * isci_fw->sas_addrs_size;
571 break;
572
573 default:
574 pr_err("bad field in firmware binary blob\n");
575 return -EINVAL;
576 }
577 }
578
579 pr_info("isci firmware v%u.%u loaded.\n",
580 isci_fw->version, isci_fw->subversion);
581
582 return SCI_SUCCESS;
583}
584
522static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 585static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
523{ 586{
524 struct isci_pci_info *pci_info; 587 struct isci_pci_info *pci_info;
525 int err, i; 588 int err, i;
526 struct isci_host *isci_host; 589 struct isci_host *isci_host;
590 const struct firmware *fw = NULL;
527 591
528 check_si_rev(pdev); 592 check_si_rev(pdev);
529 593
@@ -532,6 +596,33 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
532 return -ENOMEM; 596 return -ENOMEM;
533 pci_set_drvdata(pdev, pci_info); 597 pci_set_drvdata(pdev, pci_info);
534 598
599 err = request_firmware(&fw, ISCI_FW_NAME, &pdev->dev);
600 if (err) {
601 dev_warn(&pdev->dev,
602 "Loading firmware failed, using default values\n");
603 dev_warn(&pdev->dev,
604 "Default OEM configuration being used:"
605 " 4 narrow ports, and default SAS Addresses\n");
606 } else {
607 isci_firmware = devm_kzalloc(&pdev->dev,
608 sizeof(struct isci_firmware),
609 GFP_KERNEL);
610 if (isci_firmware) {
611 err = isci_verify_firmware(fw, isci_firmware);
612 if (err != SCI_SUCCESS) {
613 dev_warn(&pdev->dev,
614 "firmware verification failed\n");
615 dev_warn(&pdev->dev,
616 "Default OEM configuration being used:"
617 " 4 narrow ports, and default SAS "
618 "Addresses\n");
619 devm_kfree(&pdev->dev, isci_firmware);
620 isci_firmware = NULL;
621 }
622 }
623 release_firmware(fw);
624 }
625
535 err = isci_pci_init(pdev); 626 err = isci_pci_init(pdev);
536 if (err) 627 if (err)
537 return err; 628 return err;