Resolves: bz 771058

This commit is contained in:
Neil Horman 2012-01-04 16:05:07 -05:00
parent c7ebc6df23
commit 114a35487e
2 changed files with 96 additions and 0 deletions

View File

@ -869,6 +869,9 @@ Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch
Patch22000: route-cache-garbage-collector.patch
#rhbz 771058
Patch22100: msi-irq-sysfs-warning.patch
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@ -1601,6 +1604,9 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch
#rhbz 771678
ApplyPatch KVM-fix-device-assignment-permissions.patch
#rhbz 771058
ApplyPatch msi-irq-sysfs-warning.patch
# END OF PATCH APPLICATIONS
%endif
@ -2376,6 +2382,9 @@ fi
# and build.
%changelog
* Wed Jan 04 2012 Neil Horman <nhorman@redhat.com>
- Fix warning about msi sysfs refcount (bz 771058)
* Wed Jan 04 2012 Dave Jones <davej@redhat.com>
- Add Dell Studio 1557 to pci=nocrs blacklist. (rhbz 769657)

View File

@ -0,0 +1,87 @@
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);
}