88 lines
3.6 KiB
Diff
88 lines
3.6 KiB
Diff
commit 3ff0e97a1bc3059bfbcc1d864c5d4ff5f8d3c2b9
|
|
Author: Neil Horman <nhorman@tuxdriver.com>
|
|
Date: Tue Jan 3 10:17:21 2012 -0500
|
|
|
|
msi: fix imbalanced refcount of msi irq sysfs objects
|
|
|
|
This warning was recently reported to me:
|
|
|
|
------------[ cut here ]------------
|
|
WARNING: at lib/kobject.c:595 kobject_put+0x50/0x60()
|
|
Hardware name: VMware Virtual Platform
|
|
kobject: '(null)' (ffff880027b0df40): is not initialized, yet kobject_put() is
|
|
being called.
|
|
Modules linked in: vmxnet3(+) vmw_balloon i2c_piix4 i2c_core shpchp raid10
|
|
vmw_pvscsi
|
|
Pid: 630, comm: modprobe Tainted: G W 3.1.6-1.fc16.x86_64 #1
|
|
Call Trace:
|
|
[<ffffffff8106b73f>] warn_slowpath_common+0x7f/0xc0
|
|
[<ffffffff8106b836>] warn_slowpath_fmt+0x46/0x50
|
|
[<ffffffff810da293>] ? free_desc+0x63/0x70
|
|
[<ffffffff812a9aa0>] kobject_put+0x50/0x60
|
|
[<ffffffff812e4c25>] free_msi_irqs+0xd5/0x120
|
|
[<ffffffff812e524c>] pci_enable_msi_block+0x24c/0x2c0
|
|
[<ffffffffa017c273>] vmxnet3_alloc_intr_resources+0x173/0x240 [vmxnet3]
|
|
[<ffffffffa0182e94>] vmxnet3_probe_device+0x615/0x834 [vmxnet3]
|
|
[<ffffffff812d141c>] local_pci_probe+0x5c/0xd0
|
|
[<ffffffff812d2cb9>] pci_device_probe+0x109/0x130
|
|
[<ffffffff8138ba2c>] driver_probe_device+0x9c/0x2b0
|
|
[<ffffffff8138bceb>] __driver_attach+0xab/0xb0
|
|
[<ffffffff8138bc40>] ? driver_probe_device+0x2b0/0x2b0
|
|
[<ffffffff8138bc40>] ? driver_probe_device+0x2b0/0x2b0
|
|
[<ffffffff8138a8ac>] bus_for_each_dev+0x5c/0x90
|
|
[<ffffffff8138b63e>] driver_attach+0x1e/0x20
|
|
[<ffffffff8138b240>] bus_add_driver+0x1b0/0x2a0
|
|
[<ffffffffa0188000>] ? 0xffffffffa0187fff
|
|
[<ffffffff8138c246>] driver_register+0x76/0x140
|
|
[<ffffffff815ca414>] ? printk+0x51/0x53
|
|
[<ffffffffa0188000>] ? 0xffffffffa0187fff
|
|
[<ffffffff812d2996>] __pci_register_driver+0x56/0xd0
|
|
[<ffffffffa018803a>] vmxnet3_init_module+0x3a/0x3c [vmxnet3]
|
|
[<ffffffff81002042>] do_one_initcall+0x42/0x180
|
|
[<ffffffff810aad71>] sys_init_module+0x91/0x200
|
|
[<ffffffff815dccc2>] system_call_fastpath+0x16/0x1b
|
|
---[ end trace 44593438a59a9558 ]---
|
|
Using INTx interrupt, #Rx queues: 1.
|
|
|
|
It occurs when populate_msi_sysfs fails, which in turn causes free_msi_irqs to
|
|
be called. Because populate_msi_sysfs fails, we never registered any of the
|
|
msi irq sysfs objects, but free_msi_irqs still calls kobject_del and kobject_put
|
|
on each of them, which gets flagged in the above stack trace.
|
|
|
|
The fix is pretty straightforward. We can key of the parent pointer in the
|
|
kobject. It is only set if the kobject_init_and_add succededs in
|
|
populate_msi_sysfs. If anything fails there, each kobject has its parent reset
|
|
to NULL
|
|
|
|
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
|
CC: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
CC: Bjorn Helgaas <bhelgaas@google.com>
|
|
CC: Greg Kroah-Hartman <gregkh@suse.de>
|
|
CC: linux-pci@vger.kernel.org
|
|
|
|
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
|
|
index 337e16a..82de95e 100644
|
|
--- a/drivers/pci/msi.c
|
|
+++ b/drivers/pci/msi.c
|
|
@@ -323,8 +323,18 @@ static void free_msi_irqs(struct pci_dev *dev)
|
|
if (list_is_last(&entry->list, &dev->msi_list))
|
|
iounmap(entry->mask_base);
|
|
}
|
|
- kobject_del(&entry->kobj);
|
|
- kobject_put(&entry->kobj);
|
|
+
|
|
+ /*
|
|
+ * Its possible that we get into this path
|
|
+ * When populate_msi_sysfs fails, which means the entries
|
|
+ * were not registered with sysfs. In that case don't
|
|
+ * unregister them.
|
|
+ */
|
|
+ if (entry->kobj.parent) {
|
|
+ kobject_del(&entry->kobj);
|
|
+ kobject_put(&entry->kobj);
|
|
+ }
|
|
+
|
|
list_del(&entry->list);
|
|
kfree(entry);
|
|
}
|