diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-10-26 17:21:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 19:52:04 -0400 |
commit | de5e2ddf9bb3ce7b643223b9b0718062254f302f (patch) | |
tree | cf19192bfa2fb914e0b070ba0d3ea2f7669e7053 | |
parent | 1f9fa5216eacf4fdf9d3e4ab57feb8b642f0e78b (diff) |
ipmi: proper spinlock initialization
Unloading ipmi module can trigger following error. (if
CONFIG_DEBUG_SPINLOCK=y)
[ 9633.779590] BUG: spinlock bad magic on CPU#1, rmmod/7170
[ 9633.779606] lock: f41f5414, .magic: 00000000, .owner:
<none>/-1, .owner_cpu: 0
[ 9633.779626] Pid: 7170, comm: rmmod Not tainted
2.6.36-rc7-11474-gb71eb1e-dirty #328
[ 9633.779644] Call Trace:
[ 9633.779657] [<c13921cc>] ? printk+0x18/0x1c
[ 9633.779672] [<c11a1f33>] spin_bug+0xa3/0xf0
[ 9633.779685] [<c11a1ffd>] do_raw_spin_lock+0x7d/0x160
[ 9633.779702] [<c1131537>] ? release_sysfs_dirent+0x47/0xb0
[ 9633.779718] [<c1131b78>] ? sysfs_addrm_finish+0xa8/0xd0
[ 9633.779734] [<c1394bac>] _raw_spin_lock_irqsave+0xc/0x20
[ 9633.779752] [<f99d93da>] cleanup_one_si+0x6a/0x200 [ipmi_si]
[ 9633.779768] [<c11305b2>] ? sysfs_hash_and_remove+0x72/0x80
[ 9633.779786] [<f99dcf26>] ipmi_pnp_remove+0xd/0xf [ipmi_si]
[ 9633.779802] [<c11f622b>] pnp_device_remove+0x1b/0x40
Fix this by initializing spinlocks in a smi_info_alloc() helper function,
right after memory allocation and clearing.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: David Miller <davem@davemloft.net>
Cc: Yinghai Lu <yinghai@kernel.org>
Acked-by: Corey Minyard <cminyard@mvista.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e537610d2f09..b293d57d30a7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1665,6 +1665,17 @@ static int check_hotmod_int_op(const char *curr, const char *option, | |||
1665 | return 0; | 1665 | return 0; |
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | static struct smi_info *smi_info_alloc(void) | ||
1669 | { | ||
1670 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1671 | |||
1672 | if (info) { | ||
1673 | spin_lock_init(&info->si_lock); | ||
1674 | spin_lock_init(&info->msg_lock); | ||
1675 | } | ||
1676 | return info; | ||
1677 | } | ||
1678 | |||
1668 | static int hotmod_handler(const char *val, struct kernel_param *kp) | 1679 | static int hotmod_handler(const char *val, struct kernel_param *kp) |
1669 | { | 1680 | { |
1670 | char *str = kstrdup(val, GFP_KERNEL); | 1681 | char *str = kstrdup(val, GFP_KERNEL); |
@@ -1779,7 +1790,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1779 | } | 1790 | } |
1780 | 1791 | ||
1781 | if (op == HM_ADD) { | 1792 | if (op == HM_ADD) { |
1782 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1793 | info = smi_info_alloc(); |
1783 | if (!info) { | 1794 | if (!info) { |
1784 | rv = -ENOMEM; | 1795 | rv = -ENOMEM; |
1785 | goto out; | 1796 | goto out; |
@@ -1844,7 +1855,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1844 | if (!ports[i] && !addrs[i]) | 1855 | if (!ports[i] && !addrs[i]) |
1845 | continue; | 1856 | continue; |
1846 | 1857 | ||
1847 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1858 | info = smi_info_alloc(); |
1848 | if (!info) | 1859 | if (!info) |
1849 | return; | 1860 | return; |
1850 | 1861 | ||
@@ -2027,7 +2038,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2027 | return -ENODEV; | 2038 | return -ENODEV; |
2028 | } | 2039 | } |
2029 | 2040 | ||
2030 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2041 | info = smi_info_alloc(); |
2031 | if (!info) { | 2042 | if (!info) { |
2032 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); | 2043 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
2033 | return -ENOMEM; | 2044 | return -ENOMEM; |
@@ -2137,7 +2148,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2137 | if (!acpi_dev) | 2148 | if (!acpi_dev) |
2138 | return -ENODEV; | 2149 | return -ENODEV; |
2139 | 2150 | ||
2140 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2151 | info = smi_info_alloc(); |
2141 | if (!info) | 2152 | if (!info) |
2142 | return -ENOMEM; | 2153 | return -ENOMEM; |
2143 | 2154 | ||
@@ -2318,7 +2329,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2318 | { | 2329 | { |
2319 | struct smi_info *info; | 2330 | struct smi_info *info; |
2320 | 2331 | ||
2321 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2332 | info = smi_info_alloc(); |
2322 | if (!info) { | 2333 | if (!info) { |
2323 | printk(KERN_ERR PFX "Could not allocate SI data\n"); | 2334 | printk(KERN_ERR PFX "Could not allocate SI data\n"); |
2324 | return; | 2335 | return; |
@@ -2425,7 +2436,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2425 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; | 2436 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; |
2426 | struct smi_info *info; | 2437 | struct smi_info *info; |
2427 | 2438 | ||
2428 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2439 | info = smi_info_alloc(); |
2429 | if (!info) | 2440 | if (!info) |
2430 | return -ENOMEM; | 2441 | return -ENOMEM; |
2431 | 2442 | ||
@@ -2566,7 +2577,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, | |||
2566 | return -EINVAL; | 2577 | return -EINVAL; |
2567 | } | 2578 | } |
2568 | 2579 | ||
2569 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2580 | info = smi_info_alloc(); |
2570 | 2581 | ||
2571 | if (!info) { | 2582 | if (!info) { |
2572 | dev_err(&dev->dev, | 2583 | dev_err(&dev->dev, |
@@ -3013,7 +3024,7 @@ static __devinit void default_find_bmc(void) | |||
3013 | if (check_legacy_ioport(ipmi_defaults[i].port)) | 3024 | if (check_legacy_ioport(ipmi_defaults[i].port)) |
3014 | continue; | 3025 | continue; |
3015 | #endif | 3026 | #endif |
3016 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 3027 | info = smi_info_alloc(); |
3017 | if (!info) | 3028 | if (!info) |
3018 | return; | 3029 | return; |
3019 | 3030 | ||
@@ -3138,9 +3149,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3138 | goto out_err; | 3149 | goto out_err; |
3139 | } | 3150 | } |
3140 | 3151 | ||
3141 | spin_lock_init(&(new_smi->si_lock)); | ||
3142 | spin_lock_init(&(new_smi->msg_lock)); | ||
3143 | |||
3144 | /* Do low-level detection first. */ | 3152 | /* Do low-level detection first. */ |
3145 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 3153 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
3146 | if (new_smi->addr_source) | 3154 | if (new_smi->addr_source) |