Messages in this thread | | | Date | Wed, 11 Sep 2002 14:20:48 +0200 | From | Gerd Knorr <> | Subject | Re: ignore pci devices? |
| |
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/
| |