aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/init.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-03-03 20:59:32 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:29 -0400
commitd9c37390c4f02153188a64a7a89fa6798dc3ffc2 (patch)
tree508f28b5b88348b2d989f479442cbd6813bd2b42 /drivers/scsi/isci/init.c
parent6ad31fec306d532031b2f778f8656385df1b9d8f (diff)
isci: preallocate remote devices
Until we synchronize against device removal this limits the damage of use after free bugs to the driver's own objects. Unless we implement reference counting we need to ensure at least a subset of a remote device is valid at all times. We follow the lead of other libsas drivers that also preallocate devices. This also enforces maximum remote device accounting at the lldd layer, but the core may still run out of RNC's before we hit this limit. 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.c27
1 files changed, 7 insertions, 20 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index f1b8a51dd49f..2838beff43b8 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -64,7 +64,6 @@
64#include "sci_environment.h" 64#include "sci_environment.h"
65 65
66static struct scsi_transport_template *isci_transport_template; 66static struct scsi_transport_template *isci_transport_template;
67struct kmem_cache *isci_kmem_cache;
68 67
69static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { 68static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
70 { PCI_VDEVICE(INTEL, 0x1D61),}, 69 { PCI_VDEVICE(INTEL, 0x1D61),},
@@ -443,7 +442,10 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
443 struct Scsi_Host *shost; 442 struct Scsi_Host *shost;
444 int err; 443 int err;
445 444
446 isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); 445 isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) +
446 SCI_MAX_REMOTE_DEVICES *
447 (sizeof(struct isci_remote_device) +
448 scic_remote_device_get_object_size()), GFP_KERNEL);
447 if (!isci_host) 449 if (!isci_host)
448 return NULL; 450 return NULL;
449 451
@@ -656,31 +658,17 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev)
656 658
657static __init int isci_init(void) 659static __init int isci_init(void)
658{ 660{
659 int err = -ENOMEM; 661 int err;
660 662
661 pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); 663 pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
662 664
663 isci_kmem_cache = kmem_cache_create(DRV_NAME,
664 sizeof(struct isci_remote_device) +
665 scic_remote_device_get_object_size(),
666 0, 0, NULL);
667 if (!isci_kmem_cache)
668 return err;
669
670 isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); 665 isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
671 if (!isci_transport_template) 666 if (!isci_transport_template)
672 goto err_kmem; 667 return -ENOMEM;
673 668
674 err = pci_register_driver(&isci_pci_driver); 669 err = pci_register_driver(&isci_pci_driver);
675 if (err) 670 if (err)
676 goto err_sas; 671 sas_release_transport(isci_transport_template);
677
678 return 0;
679
680 err_sas:
681 sas_release_transport(isci_transport_template);
682 err_kmem:
683 kmem_cache_destroy(isci_kmem_cache);
684 672
685 return err; 673 return err;
686} 674}
@@ -689,7 +677,6 @@ static __exit void isci_exit(void)
689{ 677{
690 pci_unregister_driver(&isci_pci_driver); 678 pci_unregister_driver(&isci_pci_driver);
691 sas_release_transport(isci_transport_template); 679 sas_release_transport(isci_transport_template);
692 kmem_cache_destroy(isci_kmem_cache);
693} 680}
694 681
695MODULE_LICENSE("Dual BSD/GPL"); 682MODULE_LICENSE("Dual BSD/GPL");