Re: ignore pci devices?

From: Gerd Knorr (kraxel@bytesex.org)
Date: Wed Sep 11 2002 - 07:20:48 EST


On Tue, Sep 10, 2002 at 09:15:12PM +0100, Alan Cox wrote:
> On Tue, 2002-09-10 at 19:41, Martin Mares wrote:
> > > pci_driver has no implicit ordering.
> >
> > Agreed, but I meant inserting it as a module before the other
> > modules.
>
> Which breaks the moment it meets a hotplug system

Neverless this works fine in the non-hotplugging modular driver case,
i.e. it can be used to fix that particular bt878 card issue. Might also
be useful for testing ressource allocation error paths of PCI drivers.

  Gerd

==============================[ cut here ]==============================
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/kernel.h>

MODULE_DESCRIPTION("reserve pci card ressources to make device drivers *not* touch the card");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");

static char *ignore = "none";
MODULE_PARM(ignore,"s");
static int bus = -1, slot = -1,function = -1;

static void remove(struct pci_dev *dev)
{
        int i;
        
        printk("reserve: remove device %02x:%02x.%x\n",
               dev->bus->number,PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn));
        for (i = 0;; i++) {
                if (0 == pci_resource_start(dev,i))
                        break;
                if (pci_resource_start(dev,i) < 0x10000) {
                        release_region(pci_resource_start(dev,i),
                                       pci_resource_len(dev,i));
                } else {
                        release_mem_region(pci_resource_start(dev,i),
                                           pci_resource_len(dev,i));
                }
        }
        return;
}

static int __devinit probe(struct pci_dev *dev,
                           const struct pci_device_id *id)
{
        struct resource *res;
        int i;

        if (bus != dev->bus->number ||
            slot != PCI_SLOT(dev->devfn) ||
            function != PCI_FUNC(dev->devfn))
                return -EBUSY;

        printk("reserve: probe device %02x:%02x.%x\n",
               dev->bus->number,PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn));
        for (i = 0;; i++) {
                if (0 == pci_resource_start(dev,i))
                        break;
                if (pci_resource_start(dev,i) < 0x10000) {
                        res = request_region(pci_resource_start(dev,i),
                                             pci_resource_len(dev,i),
                                             "reserve");
                        printk("reserve: ... io at %lx size %lx [%s]\n",
                               pci_resource_start(dev,i),
                               pci_resource_len(dev,i),
                               res ? "ok" : "failed");
                        if (!res)
                                goto busy;
                } else {
                        res = request_mem_region(pci_resource_start(dev,i),
                                                 pci_resource_len(dev,i),
                                                 "reserve");
                        printk("reserve: ... mem at %lx size %lx [%s]\n",
                               pci_resource_start(dev,i),
                               pci_resource_len(dev,i),
                               res ? "ok" : "failed");
                        if (!res)
                                goto busy;
                }
        }
        return 0;

 busy:
        i--;
        while (i >= 0) {
                if (pci_resource_start(dev,i) < 0x10000) {
                        release_region(pci_resource_start(dev,i),
                                       pci_resource_len(dev,i));
                } else {
                        release_mem_region(pci_resource_start(dev,i),
                                           pci_resource_len(dev,i));
                }
        }
        return -EBUSY;
}

static struct pci_device_id pci_tbl[] __devinitdata = {
        {
                .vendor = PCI_ANY_ID,
                .device = PCI_ANY_ID,
                .subvendor = PCI_ANY_ID,
                .subdevice = PCI_ANY_ID,
        },
        { /* end of list */}
};

MODULE_DEVICE_TABLE(pci, pci_tbl);

static struct pci_driver pci_driver = {
        name: "reserve",
        id_table: pci_tbl,
        probe: probe,
        remove: remove,
};

static int do_init(void)
{
        if (3 == sscanf(ignore,"%x:%x.%x",&bus,&slot,&function)) {
                /* nothing */;
        } else if (2 == sscanf(ignore,"%x.%x",&slot,&function)) {
                bus = 0;
        } else if (2 == sscanf(ignore,"%x:%x",&bus,&slot)) {
                function = 0;
        } else if (1 == sscanf(ignore,"%x",&slot)) {
                bus = 0;
                function = 0;
        } else {
                printk("reserve: can't parse ignore=<device> insmod option\n");
                return -EINVAL;
        }
        printk("reserve: ignore=\"%s\" -> using device %02x:%02x.%x\n",
               ignore,bus,slot,function);
        return pci_module_init(&pci_driver);
}

static void do_fini(void)
{
        pci_unregister_driver(&pci_driver);
}

module_init(do_init);
module_exit(do_fini);

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Sep 15 2002 - 22:00:25 EST