From 36e3989f2f2ee86c81a9d294879712bcbfed395e Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 7 Jul 2010 10:29:01 +0200 Subject: [PATCH] drivers/dca: Convert dca_lock to a raw spinlock commit 5805f5ac2a7b6ca1fb32e406523a00ac1eb45ffb in tip. drivers/dca: convert dca_lock to a raw spinlock [ 25.607517] igb 0000:01:00.0: DCA enabled [ 25.607524] BUG: sleeping function called from invalid context at kernel/rtmutex.c:684 [ 25.607528] pcnt: 1 0 in_atomic(): 1, irqs_disabled(): 0, pid: 1805, name: modprobe [ 25.607532] Pid: 1805, comm: modprobe Tainted: G M W N 2.6.33.5-rt23-rt_debug #2 [ 25.607536] Call Trace: [ 25.607557] [] try_stack_unwind+0x151/0x1a0 [ 25.607566] [] dump_trace+0x92/0x370 [ 25.607573] [] show_trace_log_lvl+0x5c/0x80 [ 25.607578] [] show_trace+0x15/0x20 [ 25.607587] [] dump_stack+0x77/0x8f [ 25.607595] [] __might_sleep+0x11a/0x130 [ 25.607602] [] rt_spin_lock+0x83/0x90 [ 25.607611] [] dca_common_get_tag+0x28/0x80 [dca] [ 25.607622] [] dca3_get_tag+0x18/0x20 [dca] [ 25.607634] [] igb_update_dca+0xb1/0x1d0 [igb] [ 25.607649] [] igb_setup_dca+0x65/0x80 [igb] [ 25.607663] [] igb_probe+0x946/0xe4d [igb] [ 25.607678] [] local_pci_probe+0x17/0x20 [ 25.607686] [] pci_device_probe+0x121/0x130 [ 25.607699] [] driver_probe_device+0xd2/0x2e0 [ 25.607707] [] __driver_attach+0x9b/0xa0 [ 25.607714] [] bus_for_each_dev+0x6b/0xa0 [ 25.607720] [] driver_attach+0x21/0x30 [ 25.607727] [] bus_add_driver+0x1e5/0x350 [ 25.607734] [] driver_register+0x81/0x160 [ 25.607742] [] __pci_register_driver+0x6f/0xf0 [ 25.607752] [] igb_init_module+0x5b/0x5d [igb] [ 25.607769] [] do_one_initcall+0x3d/0x1a0 [ 25.607778] [] sys_init_module+0xe6/0x270 [ 25.607786] [] system_call_fastpath+0x16/0x1b [ 25.607794] [<00007f84d6783f4a>] 0x7f84d6783f4a [ tglx: Fixed the domain allocation which was calling kzalloc from the irq disabled section ] Signed-off-by: Mike Galbraith LKML-Reference: <1278491341.7926.4.camel@marge.simson.net> Signed-off-by: Thomas Gleixner Signed-off-by: Paul Gortmaker --- drivers/dca/dca-core.c | 60 ++++++++++++++++++++++++++--------------------- 1 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 8661c84..4cb0e57 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -35,7 +35,7 @@ MODULE_VERSION(DCA_VERSION); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); -static DEFINE_SPINLOCK(dca_lock); +static DEFINE_RAW_SPINLOCK(dca_lock); static LIST_HEAD(dca_domains); @@ -88,13 +88,6 @@ static struct dca_domain *dca_get_domain(struct device *dev) rc = dca_pci_rc_from_dev(dev); domain = dca_find_domain(rc); - - if (!domain) { - domain = dca_allocate_domain(rc); - if (domain) - list_add(&domain->node, &dca_domains); - } - return domain; } @@ -140,19 +133,19 @@ int dca_add_requester(struct device *dev) if (!dev) return -EFAULT; - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); /* check if the requester has not been added already */ dca = dca_find_provider_by_dev(dev); if (dca) { - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return -EEXIST; } pci_rc = dca_pci_rc_from_dev(dev); domain = dca_find_domain(pci_rc); if (!domain) { - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } @@ -162,17 +155,17 @@ int dca_add_requester(struct device *dev) break; } - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); if (slot < 0) return slot; err = dca_sysfs_add_req(dca, dev, slot); if (err) { - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); if (dca == dca_find_provider_by_dev(dev)) dca->ops->remove_requester(dca, dev); - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return err; } @@ -193,14 +186,14 @@ int dca_remove_requester(struct device *dev) if (!dev) return -EFAULT; - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } slot = dca->ops->remove_requester(dca, dev); - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); if (slot < 0) return slot; @@ -222,16 +215,16 @@ u8 dca_common_get_tag(struct device *dev, int cpu) u8 tag; unsigned long flags; - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } tag = dca->ops->get_tag(dca, dev, cpu); - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); return tag; } @@ -304,23 +297,36 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev) { int err; unsigned long flags; - struct dca_domain *domain; + struct dca_domain *domain, *newdomain = NULL; err = dca_sysfs_add_provider(dca, dev); if (err) return err; - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); domain = dca_get_domain(dev); if (!domain) { - spin_unlock_irqrestore(&dca_lock, flags); - return -ENODEV; + raw_spin_unlock_irqrestore(&dca_lock, flags); + + newdomain = dca_allocate_domain(rc); + if (!newdomain) + return -ENODEV; + + raw_spin_lock_irqsave(&dca_lock, flags); + /* Recheck, we might have raced after dropping the lock */ + domain = dca_get_domain(dev); + if (!domain) { + domain = newdomain; + newdomain = NULL; + list_add(&domain->node, &dca_domains); + } } list_add(&dca->node, &domain->dca_providers); - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_ADD, NULL); + kfree(newdomain); return 0; } EXPORT_SYMBOL_GPL(register_dca_provider); @@ -338,7 +344,7 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev) blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_REMOVE, NULL); - spin_lock_irqsave(&dca_lock, flags); + raw_spin_lock_irqsave(&dca_lock, flags); list_del(&dca->node); @@ -347,7 +353,7 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev) if (list_empty(&domain->dca_providers)) dca_free_domain(domain); - spin_unlock_irqrestore(&dca_lock, flags); + raw_spin_unlock_irqrestore(&dca_lock, flags); dca_sysfs_remove_provider(dca); } -- 1.7.0.4