Re: [patch] drivers/dca: convert dca_lock to a raw spinlock V2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jul 23, 2010 at 12:18 PM, Mike Galbraith <efault@xxxxxx> wrote:
>
> Thanks for the hint+ Thomas.  V2 moves allocation outside the lock.
>
> 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]  [<ffffffff820078a1>] try_stack_unwind+0x151/0x1a0
> [   25.607566]  [<ffffffff820062c2>] dump_trace+0x92/0x370
> [   25.607573]  [<ffffffff8200731c>] show_trace_log_lvl+0x5c/0x80
> [   25.607578]  [<ffffffff82007355>] show_trace+0x15/0x20
> [   25.607587]  [<ffffffff823f4588>] dump_stack+0x77/0x8f
> [   25.607595]  [<ffffffff82043f2a>] __might_sleep+0x11a/0x130
> [   25.607602]  [<ffffffff823f7b93>] rt_spin_lock+0x83/0x90
> [   25.607611]  [<ffffffffa0209138>] dca_common_get_tag+0x28/0x80 [dca]
> [   25.607622]  [<ffffffffa02091c8>] dca3_get_tag+0x18/0x20 [dca]
> [   25.607634]  [<ffffffffa0244e71>] igb_update_dca+0xb1/0x1d0 [igb]
> [   25.607649]  [<ffffffffa0244ff5>] igb_setup_dca+0x65/0x80 [igb]
> [   25.607663]  [<ffffffffa02535a6>] igb_probe+0x946/0xe4d [igb]
> [   25.607678]  [<ffffffff82247517>] local_pci_probe+0x17/0x20
> [   25.607686]  [<ffffffff82248661>] pci_device_probe+0x121/0x130
> [   25.607699]  [<ffffffff822e4832>] driver_probe_device+0xd2/0x2e0
> [   25.607707]  [<ffffffff822e4adb>] __driver_attach+0x9b/0xa0
> [   25.607714]  [<ffffffff822e3d1b>] bus_for_each_dev+0x6b/0xa0
> [   25.607720]  [<ffffffff822e4591>] driver_attach+0x21/0x30
> [   25.607727]  [<ffffffff822e3425>] bus_add_driver+0x1e5/0x350
> [   25.607734]  [<ffffffff822e4e41>] driver_register+0x81/0x160
> [   25.607742]  [<ffffffff8224890f>] __pci_register_driver+0x6f/0xf0
> [   25.607752]  [<ffffffffa011505b>] igb_init_module+0x5b/0x5d [igb]
> [   25.607769]  [<ffffffff820001dd>] do_one_initcall+0x3d/0x1a0
> [   25.607778]  [<ffffffff820961f6>] sys_init_module+0xe6/0x270
> [   25.607786]  [<ffffffff82003232>] system_call_fastpath+0x16/0x1b
> [   25.607794]  [<00007f84d6783f4a>] 0x7f84d6783f4a
>
> Signed-off-by: Mike Galbraith <mgalbraith@xxxxxxx>
> LKML-Reference: <new-submission>
>
> ---
>  drivers/dca/dca-core.c |   62 +++++++++++++++++++++++++++----------------------
>  1 file changed, 35 insertions(+), 27 deletions(-)
>
> Index: linux-2.6/drivers/dca/dca-core.c
> ===================================================================
> --- linux-2.6.orig/drivers/dca/dca-core.c
> +++ linux-2.6/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
>
>        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 *
>        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
>        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,38 @@ int register_dca_provider(struct dca_pro
>  {
>        int err;
>        unsigned long flags;
> -       struct dca_domain *domain;
> +       struct dca_domain *domain, *newdomain = NULL;
> +        struct pci_bus *rc;
>
>        err = dca_sysfs_add_provider(dca, dev);
>        if (err)
>                return err;
>
> -       spin_lock_irqsave(&dca_lock, flags);
> +       raw_spin_lock_irqsave(&dca_lock, flags);
> +       rc = dca_pci_rc_from_dev(dev);
>        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 +346,7 @@ void unregister_dca_provider(struct dca_
>        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 +355,7 @@ void unregister_dca_provider(struct dca_
>        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);
>  }
>

Hi Mike

Please have a look at tip/rt/2.6.33
Afaict, Thomas already applied your V1 of the patch, plus his fix for
the compile problem.

Since the above looks slightly cleaner, maybe you just need to spin a
clean-up patch
of what is in tip/rt/2.6.33

Thanks
--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux