Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cff26806 authored by Jeff Garzik's avatar Jeff Garzik Committed by James Bottomley
Browse files

[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: default avatarJeff Garzik <jgarzik@redhat.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 4c9c8d78
Loading
Loading
Loading
Loading
+94 −102
Original line number Diff line number Diff line
@@ -591,123 +591,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
#endif /* CONFIG_ISA */

#ifdef CONFIG_PCI
static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
                            ushort vendor, ushort dev);
static bool gdth_pci_registered;

static int __init gdth_search_pci(gdth_pci_str *pcistr)
static bool gdth_search_vortex(ushort device)
{
    ushort device, cnt;
    
    TRACE(("gdth_search_pci()\n"));

    cnt = 0;
    for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
    for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; 
         device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
                    PCI_DEVICE_ID_VORTEX_GDTNEWRX);
    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
                    PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
                    PCI_DEVICE_ID_INTEL_SRC);
    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
    return cnt;
}
	if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
		return true;
	if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
	    device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
		return true;
	if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
	    device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
		return true;
	return false;
}

static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
static int gdth_pci_init_one(struct pci_dev *pdev,
			     const struct pci_device_id *ent);
static void gdth_pci_remove_one(struct pci_dev *pdev);
static void gdth_remove_one(gdth_ha_str *ha);

/* Vortex only makes RAID controllers.
 * We do not really want to specify all 550 ids here, so wildcard match.
 */
static struct pci_device_id gdthtable[] __maybe_unused = {
    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
    {0}
static const struct pci_device_id gdthtable[] = {
	{ PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
	{ }	/* terminate list */
};
MODULE_DEVICE_TABLE(pci, gdthtable);

static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
                                   ushort vendor, ushort device)
static struct pci_driver gdth_pci_driver = {
	.name		= "gdth",
	.id_table	= gdthtable,
	.probe		= gdth_pci_init_one,
	.remove		= gdth_pci_remove_one,
};

static void gdth_pci_remove_one(struct pci_dev *pdev)
{
	gdth_ha_str *ha = pci_get_drvdata(pdev);

	pci_set_drvdata(pdev, NULL);

	list_del(&ha->list);
	gdth_remove_one(ha);

	pci_disable_device(pdev);
}

static int gdth_pci_init_one(struct pci_dev *pdev,
				       const struct pci_device_id *ent)
{
	ushort vendor = pdev->vendor;
	ushort device = pdev->device;
	ulong base0, base1, base2;
    struct pci_dev *pdev;
	int rc;
	gdth_pci_str gdth_pcistr;
	gdth_ha_str *ha = NULL;
    
	TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
          *cnt, vendor, device));
	       gdth_ctr_count, vendor, device));

    pdev = NULL;
    while ((pdev = pci_get_device(vendor, device, pdev))
           != NULL) {
        if (pci_enable_device(pdev))
            continue;
        if (*cnt >= MAXHA) {
            pci_dev_put(pdev);
            return;
        }
	memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));

	if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
		return -ENODEV;

	rc = pci_enable_device(pdev);
	if (rc)
		return rc;

	if (gdth_ctr_count >= MAXHA)
		return -EBUSY;

        /* GDT PCI controller found, resources are already in pdev */
        pcistr[*cnt].pdev = pdev;
	gdth_pcistr.pdev = pdev;
        base0 = pci_resource_flags(pdev, 0);
        base1 = pci_resource_flags(pdev, 1);
        base2 = pci_resource_flags(pdev, 2);
        if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
            device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
            if (!(base0 & IORESOURCE_MEM)) 
                continue;
            pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
		return -ENODEV;
	    gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
        } else {                                  /* GDT6110, GDT6120, .. */
            if (!(base0 & IORESOURCE_MEM) ||
                !(base2 & IORESOURCE_MEM) ||
                !(base1 & IORESOURCE_IO)) 
                continue;
            pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
            pcistr[*cnt].io    = pci_resource_start(pdev, 1);
		return -ENODEV;
	    gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
	    gdth_pcistr.io    = pci_resource_start(pdev, 1);
        }
        TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
                pcistr[*cnt].pdev->bus->number,
		PCI_SLOT(pcistr[*cnt].pdev->devfn),
                pcistr[*cnt].irq, pcistr[*cnt].dpmem));
        (*cnt)++;
    }       
}   

static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
{    
    gdth_pci_str temp;
    int i, changed;
		gdth_pcistr.pdev->bus->number,
		PCI_SLOT(gdth_pcistr.pdev->devfn),
		gdth_pcistr.irq,
		gdth_pcistr.dpmem));

    TRACE(("gdth_sort_pci() cnt %d\n",cnt));
    if (cnt == 0)
        return;
	rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
	if (rc)
		return rc;

    do {
        changed = FALSE;
        for (i = 0; i < cnt-1; ++i) {
            if (!reverse_scan) {
                if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
                     PCI_SLOT(pcistr[i].pdev->devfn) >
                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
                    temp = pcistr[i];
                    pcistr[i] = pcistr[i+1];
                    pcistr[i+1] = temp;
                    changed = TRUE;
                }
            } else {
                if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
                     PCI_SLOT(pcistr[i].pdev->devfn) <
                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
                    temp = pcistr[i];
                    pcistr[i] = pcistr[i+1];
                    pcistr[i+1] = temp;
                    changed = TRUE;
                }
            }
        }
    } while (changed);
	return 0;
}
#endif /* CONFIG_PCI */

@@ -907,7 +895,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
#endif /* CONFIG_ISA */

#ifdef CONFIG_PCI
static int __init gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
				   gdth_ha_str *ha)
{
    register gdt6_dpram_str __iomem *dp6_ptr;
@@ -4951,7 +4939,8 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
#endif /* CONFIG_EISA */

#ifdef CONFIG_PCI
static int __init gdth_pci_probe_one(gdth_pci_str *pcistr)
static int gdth_pci_probe_one(gdth_pci_str *pcistr,
			     gdth_ha_str **ha_out)
{
	struct Scsi_Host *shp;
	gdth_ha_str *ha;
@@ -4959,6 +4948,8 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr)
	int error, i;
	struct pci_dev *pdev = pcistr->pdev;

	*ha_out = NULL;

	shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
	if (!shp)
		return -ENOMEM;
@@ -5064,8 +5055,12 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr)
		goto out_free_coal_stat;
	list_add_tail(&ha->list, &gdth_instances);

	pci_set_drvdata(ha->pdev, ha);

	scsi_scan_host(shp);

	*ha_out = ha;

	return 0;

 out_free_coal_stat:
@@ -5182,16 +5177,8 @@ static int __init gdth_init(void)

#ifdef CONFIG_PCI
	/* scanning for PCI controllers */
	{
		gdth_pci_str pcistr[MAXHA];
		int cnt,ctr;

		cnt = gdth_search_pci(pcistr);
		printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
		gdth_sort_pci(pcistr,cnt);
		for (ctr = 0; ctr < cnt; ++ctr)
			gdth_pci_probe_one(&pcistr[ctr]);
	}
	if (pci_register_driver(&gdth_pci_driver) == 0)
		gdth_pci_registered = true;
#endif /* CONFIG_PCI */

	TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
@@ -5224,6 +5211,11 @@ static void __exit gdth_exit(void)
	del_timer_sync(&gdth_timer);
#endif

#ifdef CONFIG_PCI
	if (gdth_pci_registered)
		pci_unregister_driver(&gdth_pci_driver);
#endif

	list_for_each_entry(ha, &gdth_instances, list)
		gdth_remove_one(ha);
}