aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/gdth.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2008-02-15 22:20:09 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:15:36 -0400
commitcff2680643f9288a1cd4e27c241e1da51f476d66 (patch)
tree622d5a8c98abc9adcd2c75ff2496ea904cd1c06a /drivers/scsi/gdth.c
parent4c9c8d782c8dddc5e97d33210e8a993cec6bc168 (diff)
[SCSI] gdth: convert to PCI hotplug API
- remove PCI device sort, which greatly simplifies PCI probe, permitting direct, per-HBA function calls rather than an indirect route to the same end result. - remove need for pcistr[] Signed-off-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/gdth.c')
-rw-r--r--drivers/scsi/gdth.c196
1 files changed, 94 insertions, 102 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 12be6729898a..4941997c484e 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -591,123 +591,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
591#endif /* CONFIG_ISA */ 591#endif /* CONFIG_ISA */
592 592
593#ifdef CONFIG_PCI 593#ifdef CONFIG_PCI
594static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, 594static bool gdth_pci_registered;
595 ushort vendor, ushort dev);
596 595
597static int __init gdth_search_pci(gdth_pci_str *pcistr) 596static bool gdth_search_vortex(ushort device)
598{ 597{
599 ushort device, cnt; 598 if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
600 599 return true;
601 TRACE(("gdth_search_pci()\n")); 600 if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
602 601 device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
603 cnt = 0; 602 return true;
604 for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device) 603 if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
605 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); 604 device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
606 for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; 605 return true;
607 device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device) 606 return false;
608 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
609 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
610 PCI_DEVICE_ID_VORTEX_GDTNEWRX);
611 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
612 PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
613 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
614 PCI_DEVICE_ID_INTEL_SRC);
615 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
616 PCI_DEVICE_ID_INTEL_SRC_XSCALE);
617 return cnt;
618} 607}
619 608
609static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
610static int gdth_pci_init_one(struct pci_dev *pdev,
611 const struct pci_device_id *ent);
612static void gdth_pci_remove_one(struct pci_dev *pdev);
613static void gdth_remove_one(gdth_ha_str *ha);
614
620/* Vortex only makes RAID controllers. 615/* Vortex only makes RAID controllers.
621 * We do not really want to specify all 550 ids here, so wildcard match. 616 * We do not really want to specify all 550 ids here, so wildcard match.
622 */ 617 */
623static struct pci_device_id gdthtable[] __maybe_unused = { 618static const struct pci_device_id gdthtable[] = {
624 {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, 619 { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
625 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 620 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
626 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 621 { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
627 {0} 622 { } /* terminate list */
628}; 623};
629MODULE_DEVICE_TABLE(pci,gdthtable); 624MODULE_DEVICE_TABLE(pci, gdthtable);
630 625
631static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, 626static struct pci_driver gdth_pci_driver = {
632 ushort vendor, ushort device) 627 .name = "gdth",
628 .id_table = gdthtable,
629 .probe = gdth_pci_init_one,
630 .remove = gdth_pci_remove_one,
631};
632
633static void gdth_pci_remove_one(struct pci_dev *pdev)
633{ 634{
634 ulong base0, base1, base2; 635 gdth_ha_str *ha = pci_get_drvdata(pdev);
635 struct pci_dev *pdev; 636
637 pci_set_drvdata(pdev, NULL);
638
639 list_del(&ha->list);
640 gdth_remove_one(ha);
641
642 pci_disable_device(pdev);
643}
644
645static int gdth_pci_init_one(struct pci_dev *pdev,
646 const struct pci_device_id *ent)
647{
648 ushort vendor = pdev->vendor;
649 ushort device = pdev->device;
650 ulong base0, base1, base2;
651 int rc;
652 gdth_pci_str gdth_pcistr;
653 gdth_ha_str *ha = NULL;
636 654
637 TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", 655 TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
638 *cnt, vendor, device)); 656 gdth_ctr_count, vendor, device));
639 657
640 pdev = NULL; 658 memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
641 while ((pdev = pci_get_device(vendor, device, pdev)) 659
642 != NULL) { 660 if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
643 if (pci_enable_device(pdev)) 661 return -ENODEV;
644 continue; 662
645 if (*cnt >= MAXHA) { 663 rc = pci_enable_device(pdev);
646 pci_dev_put(pdev); 664 if (rc)
647 return; 665 return rc;
648 } 666
667 if (gdth_ctr_count >= MAXHA)
668 return -EBUSY;
649 669
650 /* GDT PCI controller found, resources are already in pdev */ 670 /* GDT PCI controller found, resources are already in pdev */
651 pcistr[*cnt].pdev = pdev; 671 gdth_pcistr.pdev = pdev;
652 base0 = pci_resource_flags(pdev, 0); 672 base0 = pci_resource_flags(pdev, 0);
653 base1 = pci_resource_flags(pdev, 1); 673 base1 = pci_resource_flags(pdev, 1);
654 base2 = pci_resource_flags(pdev, 2); 674 base2 = pci_resource_flags(pdev, 2);
655 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ 675 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
656 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ 676 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
657 if (!(base0 & IORESOURCE_MEM)) 677 if (!(base0 & IORESOURCE_MEM))
658 continue; 678 return -ENODEV;
659 pcistr[*cnt].dpmem = pci_resource_start(pdev, 0); 679 gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
660 } else { /* GDT6110, GDT6120, .. */ 680 } else { /* GDT6110, GDT6120, .. */
661 if (!(base0 & IORESOURCE_MEM) || 681 if (!(base0 & IORESOURCE_MEM) ||
662 !(base2 & IORESOURCE_MEM) || 682 !(base2 & IORESOURCE_MEM) ||
663 !(base1 & IORESOURCE_IO)) 683 !(base1 & IORESOURCE_IO))
664 continue; 684 return -ENODEV;
665 pcistr[*cnt].dpmem = pci_resource_start(pdev, 2); 685 gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
666 pcistr[*cnt].io = pci_resource_start(pdev, 1); 686 gdth_pcistr.io = pci_resource_start(pdev, 1);
667 } 687 }
668 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", 688 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
669 pcistr[*cnt].pdev->bus->number, 689 gdth_pcistr.pdev->bus->number,
670 PCI_SLOT(pcistr[*cnt].pdev->devfn), 690 PCI_SLOT(gdth_pcistr.pdev->devfn),
671 pcistr[*cnt].irq, pcistr[*cnt].dpmem)); 691 gdth_pcistr.irq,
672 (*cnt)++; 692 gdth_pcistr.dpmem));
673 }
674}
675 693
676static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) 694 rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
677{ 695 if (rc)
678 gdth_pci_str temp; 696 return rc;
679 int i, changed;
680
681 TRACE(("gdth_sort_pci() cnt %d\n",cnt));
682 if (cnt == 0)
683 return;
684 697
685 do { 698 return 0;
686 changed = FALSE;
687 for (i = 0; i < cnt-1; ++i) {
688 if (!reverse_scan) {
689 if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
690 (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
691 PCI_SLOT(pcistr[i].pdev->devfn) >
692 PCI_SLOT(pcistr[i+1].pdev->devfn))) {
693 temp = pcistr[i];
694 pcistr[i] = pcistr[i+1];
695 pcistr[i+1] = temp;
696 changed = TRUE;
697 }
698 } else {
699 if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
700 (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
701 PCI_SLOT(pcistr[i].pdev->devfn) <
702 PCI_SLOT(pcistr[i+1].pdev->devfn))) {
703 temp = pcistr[i];
704 pcistr[i] = pcistr[i+1];
705 pcistr[i+1] = temp;
706 changed = TRUE;
707 }
708 }
709 }
710 } while (changed);
711} 699}
712#endif /* CONFIG_PCI */ 700#endif /* CONFIG_PCI */
713 701
@@ -907,8 +895,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
907#endif /* CONFIG_ISA */ 895#endif /* CONFIG_ISA */
908 896
909#ifdef CONFIG_PCI 897#ifdef CONFIG_PCI
910static int __init gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, 898static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
911 gdth_ha_str *ha) 899 gdth_ha_str *ha)
912{ 900{
913 register gdt6_dpram_str __iomem *dp6_ptr; 901 register gdt6_dpram_str __iomem *dp6_ptr;
914 register gdt6c_dpram_str __iomem *dp6c_ptr; 902 register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -4951,7 +4939,8 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
4951#endif /* CONFIG_EISA */ 4939#endif /* CONFIG_EISA */
4952 4940
4953#ifdef CONFIG_PCI 4941#ifdef CONFIG_PCI
4954static int __init gdth_pci_probe_one(gdth_pci_str *pcistr) 4942static int gdth_pci_probe_one(gdth_pci_str *pcistr,
4943 gdth_ha_str **ha_out)
4955{ 4944{
4956 struct Scsi_Host *shp; 4945 struct Scsi_Host *shp;
4957 gdth_ha_str *ha; 4946 gdth_ha_str *ha;
@@ -4959,6 +4948,8 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr)
4959 int error, i; 4948 int error, i;
4960 struct pci_dev *pdev = pcistr->pdev; 4949 struct pci_dev *pdev = pcistr->pdev;
4961 4950
4951 *ha_out = NULL;
4952
4962 shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str)); 4953 shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
4963 if (!shp) 4954 if (!shp)
4964 return -ENOMEM; 4955 return -ENOMEM;
@@ -5064,8 +5055,12 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr)
5064 goto out_free_coal_stat; 5055 goto out_free_coal_stat;
5065 list_add_tail(&ha->list, &gdth_instances); 5056 list_add_tail(&ha->list, &gdth_instances);
5066 5057
5058 pci_set_drvdata(ha->pdev, ha);
5059
5067 scsi_scan_host(shp); 5060 scsi_scan_host(shp);
5068 5061
5062 *ha_out = ha;
5063
5069 return 0; 5064 return 0;
5070 5065
5071 out_free_coal_stat: 5066 out_free_coal_stat:
@@ -5182,16 +5177,8 @@ static int __init gdth_init(void)
5182 5177
5183#ifdef CONFIG_PCI 5178#ifdef CONFIG_PCI
5184 /* scanning for PCI controllers */ 5179 /* scanning for PCI controllers */
5185 { 5180 if (pci_register_driver(&gdth_pci_driver) == 0)
5186 gdth_pci_str pcistr[MAXHA]; 5181 gdth_pci_registered = true;
5187 int cnt,ctr;
5188
5189 cnt = gdth_search_pci(pcistr);
5190 printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
5191 gdth_sort_pci(pcistr,cnt);
5192 for (ctr = 0; ctr < cnt; ++ctr)
5193 gdth_pci_probe_one(&pcistr[ctr]);
5194 }
5195#endif /* CONFIG_PCI */ 5182#endif /* CONFIG_PCI */
5196 5183
5197 TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); 5184 TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
@@ -5224,6 +5211,11 @@ static void __exit gdth_exit(void)
5224 del_timer_sync(&gdth_timer); 5211 del_timer_sync(&gdth_timer);
5225#endif 5212#endif
5226 5213
5214#ifdef CONFIG_PCI
5215 if (gdth_pci_registered)
5216 pci_unregister_driver(&gdth_pci_driver);
5217#endif
5218
5227 list_for_each_entry(ha, &gdth_instances, list) 5219 list_for_each_entry(ha, &gdth_instances, list)
5228 gdth_remove_one(ha); 5220 gdth_remove_one(ha);
5229} 5221}