From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Stephen Berman <stephen.berman@gmx.net>,
"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Subject: [PATCH 4.4 37/38] ACPI: thermal: Do not call acpi_thermal_check() directly
Date: Mon, 8 Feb 2021 16:00:59 +0100 [thread overview]
Message-ID: <20210208145806.712531651@linuxfoundation.org> (raw)
In-Reply-To: <20210208145805.279815326@linuxfoundation.org>
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
commit 81b704d3e4674e09781d331df73d76675d5ad8cb upstream.
Calling acpi_thermal_check() from acpi_thermal_notify() directly
is problematic if _TMP triggers Notify () on the thermal zone for
which it has been evaluated (which happens on some systems), because
it causes a new acpi_thermal_notify() invocation to be queued up
every time and if that takes place too often, an indefinite number of
pending work items may accumulate in kacpi_notify_wq over time.
Besides, it is not really useful to queue up a new invocation of
acpi_thermal_check() if one of them is pending already.
For these reasons, rework acpi_thermal_notify() to queue up a thermal
check instead of calling acpi_thermal_check() directly and only allow
one thermal check to be pending at a time. Moreover, only allow one
acpi_thermal_check_fn() instance at a time to run
thermal_zone_device_update() for one thermal zone and make it return
early if it sees other instances running for the same thermal zone.
While at it, fold acpi_thermal_check() into acpi_thermal_check_fn(),
as it is only called from there after the other changes made here.
[This issue appears to have been exposed by commit 6d25be5782e4
("sched/core, workqueues: Distangle worker accounting from rq
lock"), but it is unclear why it was not visible earlier.]
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=208877
Reported-by: Stephen Berman <stephen.berman@gmx.net>
Diagnosed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Tested-by: Stephen Berman <stephen.berman@gmx.net>
Cc: All applicable <stable@vger.kernel.org>
[bigeasy: Backported to v4.4.y, use atomic_t instead of refcount_t]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/acpi/thermal.c | 54 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 16 deletions(-)
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -188,6 +188,8 @@ struct acpi_thermal {
int tz_enabled;
int kelvin_offset;
struct work_struct thermal_check_work;
+ struct mutex thermal_check_lock;
+ atomic_t thermal_check_count;
};
/* --------------------------------------------------------------------------
@@ -513,16 +515,6 @@ static int acpi_thermal_get_trip_points(
return 0;
}
-static void acpi_thermal_check(void *data)
-{
- struct acpi_thermal *tz = data;
-
- if (!tz->tz_enabled)
- return;
-
- thermal_zone_device_update(tz->thermal_zone);
-}
-
/* sys I/F for generic thermal sysfs support */
static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
@@ -556,6 +548,8 @@ static int thermal_get_mode(struct therm
return 0;
}
+static void acpi_thermal_check_fn(struct work_struct *work);
+
static int thermal_set_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode mode)
{
@@ -581,7 +575,7 @@ static int thermal_set_mode(struct therm
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"%s kernel ACPI thermal control\n",
tz->tz_enabled ? "Enable" : "Disable"));
- acpi_thermal_check(tz);
+ acpi_thermal_check_fn(&tz->thermal_check_work);
}
return 0;
}
@@ -950,6 +944,12 @@ static void acpi_thermal_unregister_ther
Driver Interface
-------------------------------------------------------------------------- */
+static void acpi_queue_thermal_check(struct acpi_thermal *tz)
+{
+ if (!work_pending(&tz->thermal_check_work))
+ queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+}
+
static void acpi_thermal_notify(struct acpi_device *device, u32 event)
{
struct acpi_thermal *tz = acpi_driver_data(device);
@@ -960,17 +960,17 @@ static void acpi_thermal_notify(struct a
switch (event) {
case ACPI_THERMAL_NOTIFY_TEMPERATURE:
- acpi_thermal_check(tz);
+ acpi_queue_thermal_check(tz);
break;
case ACPI_THERMAL_NOTIFY_THRESHOLDS:
acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
- acpi_thermal_check(tz);
+ acpi_queue_thermal_check(tz);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event, 0);
break;
case ACPI_THERMAL_NOTIFY_DEVICES:
acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
- acpi_thermal_check(tz);
+ acpi_queue_thermal_check(tz);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event, 0);
break;
@@ -1070,7 +1070,27 @@ static void acpi_thermal_check_fn(struct
{
struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
thermal_check_work);
- acpi_thermal_check(tz);
+
+ if (!tz->tz_enabled)
+ return;
+ /*
+ * In general, it is not sufficient to check the pending bit, because
+ * subsequent instances of this function may be queued after one of them
+ * has started running (e.g. if _TMP sleeps). Avoid bailing out if just
+ * one of them is running, though, because it may have done the actual
+ * check some time ago, so allow at least one of them to block on the
+ * mutex while another one is running the update.
+ */
+ if (!atomic_add_unless(&tz->thermal_check_count, -1, 1))
+ return;
+
+ mutex_lock(&tz->thermal_check_lock);
+
+ thermal_zone_device_update(tz->thermal_zone);
+
+ atomic_inc(&tz->thermal_check_count);
+
+ mutex_unlock(&tz->thermal_check_lock);
}
static int acpi_thermal_add(struct acpi_device *device)
@@ -1102,6 +1122,8 @@ static int acpi_thermal_add(struct acpi_
if (result)
goto free_memory;
+ atomic_set(&tz->thermal_check_count, 3);
+ mutex_init(&tz->thermal_check_lock);
INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
@@ -1167,7 +1189,7 @@ static int acpi_thermal_resume(struct de
tz->state.active |= tz->trips.active[i].flags.enabled;
}
- queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+ acpi_queue_thermal_check(tz);
return AE_OK;
}
next prev parent reply other threads:[~2021-02-08 15:21 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-08 15:00 [PATCH 4.4 00/38] 4.4.257-rc1 review Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 01/38] net_sched: reject silly cell_log in qdisc_get_rtab() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 02/38] futex,rt_mutex: Provide futex specific rt_mutex API Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 03/38] futex: Remove rt_mutex_deadlock_account_*() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 04/38] futex: Rework inconsistent rt_mutex/futex_q state Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 05/38] futex: Avoid violating the 10th rule of futex Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 06/38] futex: Replace pointless printk in fixup_owner() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 07/38] futex: Provide and use pi_state_update_owner() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 08/38] rtmutex: Remove unused argument from rt_mutex_proxy_unlock() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 09/38] futex: Use pi_state_update_owner() in put_pi_state() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 10/38] futex: Simplify fixup_pi_state_owner() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 11/38] futex: Handle faults correctly for PI futexes Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 12/38] usb: udc: core: Use lock when write to soft_connect Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 13/38] scsi: libfc: Avoid invoking response handler twice if ep is already completed Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 14/38] scsi: ibmvfc: Set default timeout to avoid crash during migration Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 15/38] stable: clamp SUBLEVEL in 4.4 and 4.9 Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 16/38] USB: serial: cp210x: add pid/vid for WSDA-200-USB Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 17/38] USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000 Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 18/38] USB: serial: option: Adding support for Cinterion MV31 Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 19/38] Input: i8042 - unbreak Pegatron C15B Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 20/38] net: lapb: Copy the skb before sending a packet Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 21/38] ELF/MIPS build fix Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 22/38] elfcore: fix building with clang Greg Kroah-Hartman
2021-02-09 12:52 ` Pavel Machek
2021-02-09 13:01 ` Greg Kroah-Hartman
2021-02-09 19:10 ` Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 23/38] USB: gadget: legacy: fix an error code in eth_bind() Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 24/38] USB: usblp: dont call usb_set_interface if theres a single alt Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 25/38] usb: dwc2: Fix endpoint direction check in ep_from_windex Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 26/38] mac80211: fix station rate table updates on assoc Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 27/38] kretprobe: Avoid re-registration of the same kretprobe earlier Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 28/38] cifs: report error instead of invalid when revalidating a dentry fails Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 29/38] mmc: core: Limit retries when analyse of SDIO tuples fails Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 30/38] ARM: footbridge: fix dc21285 PCI configuration accessors Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 31/38] mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 32/38] mm: hugetlb: fix a race between isolating and freeing page Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 33/38] mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 34/38] x86/build: Disable CET instrumentation in the kernel Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 35/38] x86/apic: Add extra serialization for non-serializing MSRs Greg Kroah-Hartman
2021-02-08 15:00 ` [PATCH 4.4 36/38] Input: xpad - sync supported devices with fork on GitHub Greg Kroah-Hartman
2021-02-08 15:00 ` Greg Kroah-Hartman [this message]
2021-02-08 15:01 ` [PATCH 4.4 38/38] ALSA: hda/realtek - Fix typo of pincfg for Dell quirk Greg Kroah-Hartman
2021-02-08 18:36 ` [PATCH 4.4 00/38] 4.4.257-rc1 review Pavel Machek
2021-02-08 20:43 ` Shuah Khan
2021-02-09 18:09 ` Guenter Roeck
2021-02-10 5:04 ` Naresh Kamboju
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210208145806.712531651@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=bigeasy@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=rafael.j.wysocki@intel.com \
--cc=stable@vger.kernel.org \
--cc=stephen.berman@gmx.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.