From: Andrew Morton <andrewm@uow.edu.au>
To: linux-hotplug@vger.kernel.org
Subject: Re: OOPS in 2.4.0-pre9 -- NULL pointer dereference in pci_insert_device
Date: Thu, 08 Feb 2001 13:45:04 +0000 [thread overview]
Message-ID: <marc-linux-hotplug-98163938203585@msgid-missing> (raw)
In-Reply-To: <marc-linux-hotplug-98055210521029@msgid-missing>
Miles Lane wrote:
>
> Andrew Morton wrote:
>
> > Miles Lane wrote:
> >
> >> This highly reproducible OOPS gets triggered when I insert my
> >> Belkin BusPort Mobile after booting the machine with no other
> >> PC Cards inserted.
> >>
> >
> >
> > I really can't work that trace out. Are you sure it's
> > correct? System.map kosher, etc?
>
> Hi Andrew,
>
> I am adding Linus to the TO:, since this problem may be in his
> yenta code.
I took him off again :) Let's suprise him when we have a fix.
I suspect it's a broken driver and not yenta.
> I'm really not sure what why the OOPS I sent was bogus.
> Perhaps these new OOPS traces will be more useful. I hope so!
Yep. The PCI driver list has become corrupted. The bug
probably happened waaay before the oops, so we need to
find out who did this. It can happen if a driver fails
to unregister itself and then gets unloaded. Ten seconds
later, boom.
Please try this patch. It just checks the sanity of
the PCI driver list where ever it's touched, and also
immediately prior to module unload.
It's against 2.4.2-pre1. Hopefully it'll apply to
Alan's kernel. If the patch finds something, please
feed through ksymooops.
--- linux-2.4.2-pre1/kernel/module.c Tue Nov 28 12:38:07 2000
+++ lk/kernel/module.c Fri Feb 9 00:29:00 2001
@@ -1052,6 +1052,9 @@
/* And free the memory. */
+ memset(mod, 0, mod->size);
+#define CHECK_PCI_DRIVERS() check_pci_drivers(__FUNCTION__, __LINE__)
+ CHECK_PCI_DRIVERS();
module_unmap(mod);
}
--- linux-2.4.2-pre1/drivers/pci/pci.c Tue Dec 12 08:46:26 2000
+++ lk/drivers/pci/pci.c Fri Feb 9 00:18:02 2001
@@ -36,6 +36,21 @@
LIST_HEAD(pci_root_buses);
LIST_HEAD(pci_devices);
+static LIST_HEAD(pci_drivers);
+
+#define CHECK_PCI_DRIVERS() check_pci_drivers(__FUNCTION__, __LINE__)
+
+void check_pci_drivers(const char *who, int where)
+{
+ struct list_head *ln;
+ for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) {
+ struct pci_driver *drv = list_entry(ln, struct pci_driver, node);
+ if (drv = 0) {
+ printk("PCI driver list corrupted in %s:%d\n", who, where);
+ show_trace(0);
+ }
+ }
+}
/**
* pci_find_slot - locate PCI device from a given PCI slot
@@ -52,6 +67,7 @@
{
struct pci_dev *dev;
+ CHECK_PCI_DRIVERS();
pci_for_each_dev(dev) {
if (dev->bus->number = bus && dev->devfn = devfn)
return dev;
@@ -67,6 +83,7 @@
{
struct list_head *n = from ? from->global_list.next : pci_devices.next;
+ CHECK_PCI_DRIVERS();
while (n != &pci_devices) {
struct pci_dev *dev = pci_dev_g(n);
if ((vendor = PCI_ANY_ID || dev->vendor = vendor) &&
@@ -117,6 +134,7 @@
{
struct list_head *n = from ? from->global_list.next : pci_devices.next;
+ CHECK_PCI_DRIVERS();
while (n != &pci_devices) {
struct pci_dev *dev = pci_dev_g(n);
if (dev->class = class)
@@ -134,6 +152,7 @@
u8 pos, id;
int ttl = 48;
+ CHECK_PCI_DRIVERS();
pci_read_config_word(dev, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
@@ -177,6 +196,7 @@
int i;
struct resource *best = NULL;
+ CHECK_PCI_DRIVERS();
for(i=0; i<4; i++) {
struct resource *r = bus->resource[i];
if (!r)
@@ -252,6 +272,7 @@
{
int err;
+ CHECK_PCI_DRIVERS();
if ((err = pcibios_enable_device(dev)) < 0)
return err;
pci_set_power_state(dev, 0);
@@ -263,6 +284,7 @@
{
u8 pin;
+ CHECK_PCI_DRIVERS();
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin)
return -1;
@@ -279,8 +301,6 @@
* Registration of PCI drivers and handling of hot-pluggable devices.
*/
-static LIST_HEAD(pci_drivers);
-
const struct pci_device_id *
pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev)
{
@@ -302,6 +322,7 @@
const struct pci_device_id *id;
int ret = 0;
+ CHECK_PCI_DRIVERS();
if (drv->id_table) {
id = pci_match_device(drv->id_table, dev);
if (!id) {
@@ -312,10 +333,12 @@
id = NULL;
dev_probe_lock();
+ CHECK_PCI_DRIVERS();
if (drv->probe(dev, id) >= 0) {
dev->driver = drv;
ret = 1;
}
+ CHECK_PCI_DRIVERS();
dev_probe_unlock();
out:
return ret;
@@ -327,11 +350,13 @@
struct pci_dev *dev;
int count = 0;
+ CHECK_PCI_DRIVERS();
list_add_tail(&drv->node, &pci_drivers);
pci_for_each_dev(dev) {
if (!pci_dev_driver(dev))
count += pci_announce_device(drv, dev);
}
+ CHECK_PCI_DRIVERS();
return count;
}
@@ -340,14 +365,19 @@
{
struct pci_dev *dev;
+ CHECK_PCI_DRIVERS();
list_del(&drv->node);
pci_for_each_dev(dev) {
if (dev->driver = drv) {
- if (drv->remove)
+ if (drv->remove) {
+ CHECK_PCI_DRIVERS();
drv->remove(dev);
+ CHECK_PCI_DRIVERS();
+ }
dev->driver = NULL;
}
}
+ CHECK_PCI_DRIVERS();
}
#ifdef CONFIG_HOTPLUG
@@ -393,7 +423,9 @@
envp[i++] = "ACTION=remove";
envp[i] = 0;
+ CHECK_PCI_DRIVERS();
call_usermodehelper (argv [0], argv, envp);
+ CHECK_PCI_DRIVERS();
}
void
@@ -401,6 +433,7 @@
{
struct list_head *ln;
+ CHECK_PCI_DRIVERS();
list_add_tail(&dev->bus_list, &bus->devices);
list_add_tail(&dev->global_list, &pci_devices);
#ifdef CONFIG_PROC_FS
@@ -408,6 +441,10 @@
#endif
for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) {
struct pci_driver *drv = list_entry(ln, struct pci_driver, node);
+ if (drv = 0) {
+ printk("oops avoided\n");
+ return;
+ }
if (drv->remove && pci_announce_device(drv, dev))
break;
}
@@ -421,21 +458,25 @@
{
int i;
+ CHECK_PCI_DRIVERS();
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = dev->resource + i;
if (res->parent)
release_resource(res);
}
+ CHECK_PCI_DRIVERS();
}
void
pci_remove_device(struct pci_dev *dev)
{
+ CHECK_PCI_DRIVERS();
if (dev->driver) {
if (dev->driver->remove)
dev->driver->remove(dev);
dev->driver = NULL;
}
+ CHECK_PCI_DRIVERS();
list_del(&dev->bus_list);
list_del(&dev->global_list);
pci_free_resources(dev);
@@ -1072,21 +1113,25 @@
*/
static int pci_pm_suspend_device(struct pci_dev *dev)
{
+ CHECK_PCI_DRIVERS();
if (dev) {
struct pci_driver *driver = dev->driver;
if (driver && driver->suspend)
driver->suspend(dev);
}
+ CHECK_PCI_DRIVERS();
return 0;
}
static int pci_pm_resume_device(struct pci_dev *dev)
{
+ CHECK_PCI_DRIVERS();
if (dev) {
struct pci_driver *driver = dev->driver;
if (driver && driver->resume)
driver->resume(dev);
}
+ CHECK_PCI_DRIVERS();
return 0;
}
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
prev parent reply other threads:[~2001-02-08 13:45 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-01-26 23:37 OOPS in 2.4.0-pre9 -- NULL pointer dereference in pci_insert_device Miles Lane
2001-01-27 12:33 ` Andrew Morton
2001-02-08 13:45 ` Andrew Morton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-hotplug-98163938203585@msgid-missing \
--to=andrewm@uow.edu.au \
--cc=linux-hotplug@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).