diff options
author | Jeff Garzik <jeff@garzik.org> | 2008-02-15 22:20:09 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-07 13:15:36 -0400 |
commit | cff2680643f9288a1cd4e27c241e1da51f476d66 (patch) | |
tree | 622d5a8c98abc9adcd2c75ff2496ea904cd1c06a /drivers | |
parent | 4c9c8d782c8dddc5e97d33210e8a993cec6bc168 (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')
-rw-r--r-- | drivers/scsi/gdth.c | 196 |
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 |
594 | static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, | 594 | static bool gdth_pci_registered; |
595 | ushort vendor, ushort dev); | ||
596 | 595 | ||
597 | static int __init gdth_search_pci(gdth_pci_str *pcistr) | 596 | static 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 | ||
609 | static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out); | ||
610 | static int gdth_pci_init_one(struct pci_dev *pdev, | ||
611 | const struct pci_device_id *ent); | ||
612 | static void gdth_pci_remove_one(struct pci_dev *pdev); | ||
613 | static 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 | */ |
623 | static struct pci_device_id gdthtable[] __maybe_unused = { | 618 | static 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 | }; |
629 | MODULE_DEVICE_TABLE(pci,gdthtable); | 624 | MODULE_DEVICE_TABLE(pci, gdthtable); |
630 | 625 | ||
631 | static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, | 626 | static 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 | |||
633 | static 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 | |||
645 | static 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 | ||
676 | static 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 |
910 | static int __init gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, | 898 | static 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 |
4954 | static int __init gdth_pci_probe_one(gdth_pci_str *pcistr) | 4942 | static 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 | } |