Message ID | CA+icZUUz1ExQHWo1OhVJSZdLf6mopu4hWURcSd4tGtuyCj4TSQ@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Aug 14, 2015 at 11:39 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote: > On Thursday, August 13, 2015 10:39:08 PM Sedat Dilek wrote: >> >> --f46d04447e7fc2306e051d3753a5 >> Content-Type: text/plain; charset=UTF-8 >> >> On Thu, Aug 13, 2015 at 6:53 PM, Hans de Goede <hdegoede@redhat.com> wrote: >> > Before this commit, the following would happen: >> > >> > a) acpi_video_get_backlight_type() gets called >> > b) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() >> > c) acpi_video_init_backlight_type() locks its function static init_mutex >> > d) acpi_video_init_backlight_type() calls backlight_register_notifier() >> > e) backlight_register_notifier() takes its notifier-chain lock >> > >> > And when the backlight notifier chain gets called we've: >> > >> > 1) blocking_notifier_call_chain() gets called >> > 2) blocking_notifier_call_chain() takes the notifier-chain lock >> > 3) blocking_notifier_call_chain() calls acpi_video_backlight_notify() >> > 4) acpi_video_backlight_notify() calls acpi_video_get_backlight_type() >> > 5) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() >> > 6) acpi_video_init_backlight_type() locks its function static init_mutex >> > >> > So in the first call sequence we have: >> > >> > a) init_mutex gets locked >> > b) notifier-chain gets locked >> > >> > and in the second call sequence we have: >> > >> > 1) notifier-chain gets locked >> > 2) init_mutex gets locked >> > >> > And we've a circular locking dependency. This specific locking dependency >> > is fixable without using the big hammer otherwise known as a workqueue, >> > but further analysis shows a similar problem with the backlight notifier >> > chain lock vs register_count_mutex from drivers/acpi/acpi_video.c, >> > and fixing that becomes problematic. >> > >> > So this commit simply fixes this with the big hammer, performance >> > wise this is a non issue as we expect the work to get scheduled >> > exactly zero or one times during normal system use. >> > >> >> This patch on top of Linux v4.2-rc6 fixes the issue for me. >> >> Feel free to add my... >> >> Reported-by: Sedat Dilek <sedat.dilek@gmail.com> >> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> > > Applied, thanks! > Thanks for carrying this one. Isn't this a for-4.2/acpi-video-fixes? Why did you apply this in your linux-next Git branch? - sed@ - [1] http://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git/commit/?h=linux-next&id=7231ed1a813e0a9d249bbbe58e66ca058aee83e1 > Rafael >
On Thursday, August 13, 2015 10:39:08 PM Sedat Dilek wrote: > > --f46d04447e7fc2306e051d3753a5 > Content-Type: text/plain; charset=UTF-8 > > On Thu, Aug 13, 2015 at 6:53 PM, Hans de Goede <hdegoede@redhat.com> wrote: > > Before this commit, the following would happen: > > > > a) acpi_video_get_backlight_type() gets called > > b) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() > > c) acpi_video_init_backlight_type() locks its function static init_mutex > > d) acpi_video_init_backlight_type() calls backlight_register_notifier() > > e) backlight_register_notifier() takes its notifier-chain lock > > > > And when the backlight notifier chain gets called we've: > > > > 1) blocking_notifier_call_chain() gets called > > 2) blocking_notifier_call_chain() takes the notifier-chain lock > > 3) blocking_notifier_call_chain() calls acpi_video_backlight_notify() > > 4) acpi_video_backlight_notify() calls acpi_video_get_backlight_type() > > 5) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() > > 6) acpi_video_init_backlight_type() locks its function static init_mutex > > > > So in the first call sequence we have: > > > > a) init_mutex gets locked > > b) notifier-chain gets locked > > > > and in the second call sequence we have: > > > > 1) notifier-chain gets locked > > 2) init_mutex gets locked > > > > And we've a circular locking dependency. This specific locking dependency > > is fixable without using the big hammer otherwise known as a workqueue, > > but further analysis shows a similar problem with the backlight notifier > > chain lock vs register_count_mutex from drivers/acpi/acpi_video.c, > > and fixing that becomes problematic. > > > > So this commit simply fixes this with the big hammer, performance > > wise this is a non issue as we expect the work to get scheduled > > exactly zero or one times during normal system use. > > > > This patch on top of Linux v4.2-rc6 fixes the issue for me. > > Feel free to add my... > > Reported-by: Sedat Dilek <sedat.dilek@gmail.com> > Tested-by: Sedat Dilek <sedat.dilek@gmail.com> Applied, thanks! Rafael
On Fri, Aug 14, 2015 at 12:16 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote: > On Friday, August 14, 2015 11:36:41 AM Sedat Dilek wrote: >> On Fri, Aug 14, 2015 at 11:39 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote: >> > On Thursday, August 13, 2015 10:39:08 PM Sedat Dilek wrote: >> >> >> >> --f46d04447e7fc2306e051d3753a5 >> >> Content-Type: text/plain; charset=UTF-8 >> >> >> >> On Thu, Aug 13, 2015 at 6:53 PM, Hans de Goede <hdegoede@redhat.com> wrote: >> >> > Before this commit, the following would happen: >> >> > >> >> > a) acpi_video_get_backlight_type() gets called >> >> > b) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() >> >> > c) acpi_video_init_backlight_type() locks its function static init_mutex >> >> > d) acpi_video_init_backlight_type() calls backlight_register_notifier() >> >> > e) backlight_register_notifier() takes its notifier-chain lock >> >> > >> >> > And when the backlight notifier chain gets called we've: >> >> > >> >> > 1) blocking_notifier_call_chain() gets called >> >> > 2) blocking_notifier_call_chain() takes the notifier-chain lock >> >> > 3) blocking_notifier_call_chain() calls acpi_video_backlight_notify() >> >> > 4) acpi_video_backlight_notify() calls acpi_video_get_backlight_type() >> >> > 5) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() >> >> > 6) acpi_video_init_backlight_type() locks its function static init_mutex >> >> > >> >> > So in the first call sequence we have: >> >> > >> >> > a) init_mutex gets locked >> >> > b) notifier-chain gets locked >> >> > >> >> > and in the second call sequence we have: >> >> > >> >> > 1) notifier-chain gets locked >> >> > 2) init_mutex gets locked >> >> > >> >> > And we've a circular locking dependency. This specific locking dependency >> >> > is fixable without using the big hammer otherwise known as a workqueue, >> >> > but further analysis shows a similar problem with the backlight notifier >> >> > chain lock vs register_count_mutex from drivers/acpi/acpi_video.c, >> >> > and fixing that becomes problematic. >> >> > >> >> > So this commit simply fixes this with the big hammer, performance >> >> > wise this is a non issue as we expect the work to get scheduled >> >> > exactly zero or one times during normal system use. >> >> > >> >> >> >> This patch on top of Linux v4.2-rc6 fixes the issue for me. >> >> >> >> Feel free to add my... >> >> >> >> Reported-by: Sedat Dilek <sedat.dilek@gmail.com> >> >> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> >> > >> > Applied, thanks! >> > >> >> Thanks for carrying this one. >> Isn't this a for-4.2/acpi-video-fixes? > > I have no branch like that. > I wanted to say it's "for 4.2-rc7". >> Why did you apply this in your linux-next Git branch? > > Because that's what I do normally with patches I'm going to push to Linus. > OK, thanks. - sed@ - > Thanks, > Rafael >
On Friday, August 14, 2015 11:36:41 AM Sedat Dilek wrote: > On Fri, Aug 14, 2015 at 11:39 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote: > > On Thursday, August 13, 2015 10:39:08 PM Sedat Dilek wrote: > >> > >> --f46d04447e7fc2306e051d3753a5 > >> Content-Type: text/plain; charset=UTF-8 > >> > >> On Thu, Aug 13, 2015 at 6:53 PM, Hans de Goede <hdegoede@redhat.com> wrote: > >> > Before this commit, the following would happen: > >> > > >> > a) acpi_video_get_backlight_type() gets called > >> > b) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() > >> > c) acpi_video_init_backlight_type() locks its function static init_mutex > >> > d) acpi_video_init_backlight_type() calls backlight_register_notifier() > >> > e) backlight_register_notifier() takes its notifier-chain lock > >> > > >> > And when the backlight notifier chain gets called we've: > >> > > >> > 1) blocking_notifier_call_chain() gets called > >> > 2) blocking_notifier_call_chain() takes the notifier-chain lock > >> > 3) blocking_notifier_call_chain() calls acpi_video_backlight_notify() > >> > 4) acpi_video_backlight_notify() calls acpi_video_get_backlight_type() > >> > 5) acpi_video_get_backlight_type() calls acpi_video_init_backlight_type() > >> > 6) acpi_video_init_backlight_type() locks its function static init_mutex > >> > > >> > So in the first call sequence we have: > >> > > >> > a) init_mutex gets locked > >> > b) notifier-chain gets locked > >> > > >> > and in the second call sequence we have: > >> > > >> > 1) notifier-chain gets locked > >> > 2) init_mutex gets locked > >> > > >> > And we've a circular locking dependency. This specific locking dependency > >> > is fixable without using the big hammer otherwise known as a workqueue, > >> > but further analysis shows a similar problem with the backlight notifier > >> > chain lock vs register_count_mutex from drivers/acpi/acpi_video.c, > >> > and fixing that becomes problematic. > >> > > >> > So this commit simply fixes this with the big hammer, performance > >> > wise this is a non issue as we expect the work to get scheduled > >> > exactly zero or one times during normal system use. > >> > > >> > >> This patch on top of Linux v4.2-rc6 fixes the issue for me. > >> > >> Feel free to add my... > >> > >> Reported-by: Sedat Dilek <sedat.dilek@gmail.com> > >> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> > > > > Applied, thanks! > > > > Thanks for carrying this one. > Isn't this a for-4.2/acpi-video-fixes? I have no branch like that. > Why did you apply this in your linux-next Git branch? Because that's what I do normally with patches I'm going to push to Linus. Thanks, Rafael
Hans de Goede (1): ACPI / video: Fix circular lock dependency issue in the video-detect code drivers/acpi/video_detect.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 815f75ef2411..2922f1f252d5 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/types.h> +#include <linux/workqueue.h> #include <acpi/video.h> ACPI_MODULE_NAME("video"); @@ -41,6 +42,7 @@ void acpi_video_unregister_backlight(void); static bool backlight_notifier_registered; static struct notifier_block backlight_nb; +static struct work_struct backlight_notify_work; static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef; static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef; @@ -262,6 +264,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = { { }, }; +/* This uses a workqueue to avoid various locking ordering issues */ +static void acpi_video_backlight_notify_work(struct work_struct *work) +{ + if (acpi_video_get_backlight_type() != acpi_backlight_video) + acpi_video_unregister_backlight(); +} + static int acpi_video_backlight_notify(struct notifier_block *nb, unsigned long val, void *bd) { @@ -269,9 +278,8 @@ static int acpi_video_backlight_notify(struct notifier_block *nb, /* A raw bl registering may change video -> native */ if (backlight->props.type == BACKLIGHT_RAW && - val == BACKLIGHT_REGISTERED && - acpi_video_get_backlight_type() != acpi_backlight_video) - acpi_video_unregister_backlight(); + val == BACKLIGHT_REGISTERED) + schedule_work(&backlight_notify_work); return NOTIFY_OK; } @@ -304,6 +312,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void) acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, find_video, NULL, &video_caps, NULL); + INIT_WORK(&backlight_notify_work, + acpi_video_backlight_notify_work); backlight_nb.notifier_call = acpi_video_backlight_notify; backlight_nb.priority = 0; if (backlight_register_notifier(&backlight_nb) == 0)