]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ACPI: CPPC: Make rmw_lock a raw_spin_lock
authorPierre Gondois <pierre.gondois@arm.com>
Mon, 28 Oct 2024 12:56:56 +0000 (13:56 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 29 Oct 2024 11:56:19 +0000 (12:56 +0100)
The following BUG was triggered:

=============================
[ BUG: Invalid wait context ]
6.12.0-rc2-XXX #406 Not tainted
-----------------------------
kworker/1:1/62 is trying to lock:
ffffff8801593030 (&cpc_ptr->rmw_lock){+.+.}-{3:3}, at: cpc_write+0xcc/0x370
other info that might help us debug this:
context-{5:5}
2 locks held by kworker/1:1/62:
  #0: ffffff897ef5ec98 (&rq->__lock){-.-.}-{2:2}, at: raw_spin_rq_lock_nested+0x2c/0x50
  #1: ffffff880154e238 (&sg_policy->update_lock){....}-{2:2}, at: sugov_update_shared+0x3c/0x280
stack backtrace:
CPU: 1 UID: 0 PID: 62 Comm: kworker/1:1 Not tainted 6.12.0-rc2-g9654bd3e8806 #406
Workqueue:  0x0 (events)
Call trace:
  dump_backtrace+0xa4/0x130
  show_stack+0x20/0x38
  dump_stack_lvl+0x90/0xd0
  dump_stack+0x18/0x28
  __lock_acquire+0x480/0x1ad8
  lock_acquire+0x114/0x310
  _raw_spin_lock+0x50/0x70
  cpc_write+0xcc/0x370
  cppc_set_perf+0xa0/0x3a8
  cppc_cpufreq_fast_switch+0x40/0xc0
  cpufreq_driver_fast_switch+0x4c/0x218
  sugov_update_shared+0x234/0x280
  update_load_avg+0x6ec/0x7b8
  dequeue_entities+0x108/0x830
  dequeue_task_fair+0x58/0x408
  __schedule+0x4f0/0x1070
  schedule+0x54/0x130
  worker_thread+0xc0/0x2e8
  kthread+0x130/0x148
  ret_from_fork+0x10/0x20

sugov_update_shared() locks a raw_spinlock while cpc_write() locks a
spinlock.

To have a correct wait-type order, update rmw_lock to a raw spinlock and
ensure that interrupts will be disabled on the CPU holding it.

Fixes: 60949b7b8054 ("ACPI: CPPC: Fix MASK_VAL() usage")
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Link: https://patch.msgid.link/20241028125657.1271512-1-pierre.gondois@arm.com
[ rjw: Changelog edits ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/cppc_acpi.c
include/acpi/cppc_acpi.h

index c3fc2c05d8687eff4f24f23a94580fb90579f54d..1a40f0514eaa368322b86e1be61bc7d6d56f9944 100644 (file)
@@ -867,7 +867,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 
        /* Store CPU Logical ID */
        cpc_ptr->cpu_id = pr->id;
-       spin_lock_init(&cpc_ptr->rmw_lock);
+       raw_spin_lock_init(&cpc_ptr->rmw_lock);
 
        /* Parse PSD data for this CPU */
        ret = acpi_get_psd(cpc_ptr, handle);
@@ -1087,6 +1087,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
        int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
        struct cpc_reg *reg = &reg_res->cpc_entry.reg;
        struct cpc_desc *cpc_desc;
+       unsigned long flags;
 
        size = GET_BIT_WIDTH(reg);
 
@@ -1126,7 +1127,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                        return -ENODEV;
                }
 
-               spin_lock(&cpc_desc->rmw_lock);
+               raw_spin_lock_irqsave(&cpc_desc->rmw_lock, flags);
                switch (size) {
                case 8:
                        prev_val = readb_relaxed(vaddr);
@@ -1141,7 +1142,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                        prev_val = readq_relaxed(vaddr);
                        break;
                default:
-                       spin_unlock(&cpc_desc->rmw_lock);
+                       raw_spin_unlock_irqrestore(&cpc_desc->rmw_lock, flags);
                        return -EFAULT;
                }
                val = MASK_VAL_WRITE(reg, prev_val, val);
@@ -1174,7 +1175,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
        }
 
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
-               spin_unlock(&cpc_desc->rmw_lock);
+               raw_spin_unlock_irqrestore(&cpc_desc->rmw_lock, flags);
 
        return ret_val;
 }
index 76e44e102780e4f8ffe22cf331cc36f162c67f64..62d368bcd9eca5eb105b6be7d6bfa0b6183fb766 100644 (file)
@@ -65,7 +65,7 @@ struct cpc_desc {
        int write_cmd_status;
        int write_cmd_id;
        /* Lock used for RMW operations in cpc_write() */
-       spinlock_t rmw_lock;
+       raw_spinlock_t rmw_lock;
        struct cpc_register_resource cpc_regs[MAX_CPC_REG_ENT];
        struct acpi_psd_package domain_info;
        struct kobject kobj;