Skip to content

Commit

Permalink
Merge branches 'acpi-ec', 'acpi-cppc', 'acpi-fan' and 'acpi-battery'
Browse files Browse the repository at this point in the history
Merge ACPI EC driver changes, CPPC-related changes, ACPI fan driver
changes and ACPI battery driver changes for 5.18-rc1:

 - Make wakeup events checks in the ACPI EC driver more
   straightforward and clean up acpi_ec_submit_event() (Rafael
   Wysocki).

 - Make it possible to obtain the CPU capacity with the help of CPPC
   information (Ionela Voinescu).

 - Improve fine grained fan control in the ACPI fan driver and
   document it (Srinivas Pandruvada).

 - Add device HID and quirk for Microsoft Surface Go 3 to the ACPI
   battery driver (Maximilian Luz).

* acpi-ec:
  ACPI: EC: Rearrange code in acpi_ec_submit_event()
  ACPI: EC: Reduce indentation level in acpi_ec_submit_event()
  ACPI: EC: Do not return result from advance_transaction()

* acpi-cppc:
  arm64, topology: enable use of init_cpu_capacity_cppc()
  arch_topology: obtain cpu capacity using information from CPPC
  x86, ACPI: rename init_freq_invariance_cppc() to arch_init_invariance_cppc()

* acpi-fan:
  Documentation/admin-guide/acpi: Add documentation for fine grain control
  ACPI: fan: Add additional attributes for fine grain control
  ACPI: fan: Properly handle fine grain control
  ACPI: fan: Optimize struct acpi_fan_fif
  ACPI: fan: Separate file for attributes creation
  ACPI: fan: Fix error reporting to user space

* acpi-battery:
  ACPI: battery: Add device HID and quirk for Microsoft Surface Go 3
  • Loading branch information
Rafael J. Wysocki committed Mar 18, 2022
5 parents 03d5c98 + 13a62d0 + 8290931 + 0750b8f + 7dacee0 commit 24b2b09
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 165 deletions.
28 changes: 28 additions & 0 deletions Documentation/admin-guide/acpi/fan_performance_states.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,31 @@ For example::

When a given field is not populated or its value provided by the platform
firmware is invalid, the "not-defined" string is shown instead of the value.

ACPI Fan Fine Grain Control
=============================

When _FIF object specifies support for fine grain control, then fan speed
can be set from 0 to 100% with the recommended minimum "step size" via
_FSL object. User can adjust fan speed using thermal sysfs cooling device.

Here use can look at fan performance states for a reference speed (speed_rpm)
and set it by changing cooling device cur_state. If the fine grain control
is supported then user can also adjust to some other speeds which are
not defined in the performance states.

The support of fine grain control is presented via sysfs attribute
"fine_grain_control". If fine grain control is present, this attribute
will show "1" otherwise "0".

This sysfs attribute is presented in the same directory as performance states.

ACPI Fan Performance Feedback
=============================

The optional _FST object provides status information for the fan device.
This includes field to provide current fan speed in revolutions per minute
at which the fan is rotating.

This speed is presented in the sysfs using the attribute "fan_speed_rpm",
in the same directory as performance states.
4 changes: 4 additions & 0 deletions arch/arm64/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ void update_freq_counters_refs(void);
#define arch_scale_freq_capacity topology_get_freq_scale
#define arch_scale_freq_invariant topology_scale_freq_invariant

#ifdef CONFIG_ACPI_CPPC_LIB
#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
#endif

/* Replace task scheduler's default cpu-invariant accounting */
#define arch_scale_cpu_capacity topology_get_cpu_scale

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ static inline void init_freq_invariance(bool secondary, bool cppc_ready)

#ifdef CONFIG_ACPI_CPPC_LIB
void init_freq_invariance_cppc(void);
#define init_freq_invariance_cppc init_freq_invariance_cppc
#define arch_init_invariance_cppc init_freq_invariance_cppc

bool amd_set_max_freq_ratio(u64 *ratio);
#else
Expand Down
3 changes: 3 additions & 0 deletions drivers/acpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
obj-$(CONFIG_ACPI_TINY_POWER_BUTTON) += tiny-power-button.o
obj-$(CONFIG_ACPI_FAN) += fan.o
fan-objs := fan_core.o
fan-objs += fan_attr.o

obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-$(CONFIG_ACPI_TAD) += acpi_tad.o
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
Expand Down
12 changes: 12 additions & 0 deletions drivers/acpi/battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ MODULE_PARM_DESC(cache_time, "cache time in milliseconds");

static const struct acpi_device_id battery_device_ids[] = {
{"PNP0C0A", 0},

/* Microsoft Surface Go 3 */
{"MSHW0146", 0},

{"", 0},
};

Expand Down Expand Up @@ -1148,6 +1152,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
},
},
{
/* Microsoft Surface Go 3 */
.callback = battery_notification_delay_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
},
},
{},
};

Expand Down
6 changes: 3 additions & 3 deletions drivers/acpi/cppc_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,8 @@ static bool is_cppc_supported(int revision, int num_ent)
* )
*/

#ifndef init_freq_invariance_cppc
static inline void init_freq_invariance_cppc(void) { }
#ifndef arch_init_invariance_cppc
static inline void arch_init_invariance_cppc(void) { }
#endif

/**
Expand Down Expand Up @@ -819,7 +819,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
goto out_free;
}

init_freq_invariance_cppc();
arch_init_invariance_cppc();

kfree(output.pointer);
return 0;
Expand Down
85 changes: 45 additions & 40 deletions drivers/acpi/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ struct acpi_ec_query {
};

static int acpi_ec_submit_query(struct acpi_ec *ec);
static bool advance_transaction(struct acpi_ec *ec, bool interrupt);
static void advance_transaction(struct acpi_ec *ec, bool interrupt);
static void acpi_ec_event_handler(struct work_struct *work);

struct acpi_ec *first_ec;
Expand Down Expand Up @@ -441,36 +441,35 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
return true;
}

static bool acpi_ec_submit_event(struct acpi_ec *ec)
static void acpi_ec_submit_event(struct acpi_ec *ec)
{
/*
* It is safe to mask the events here, because acpi_ec_close_event()
* will run at least once after this.
*/
acpi_ec_mask_events(ec);
if (!acpi_ec_event_enabled(ec))
return false;

if (ec->event_state == EC_EVENT_READY) {
ec_dbg_evt("Command(%s) submitted/blocked",
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
return;

ec->event_state = EC_EVENT_IN_PROGRESS;
/*
* If events_to_process is greqter than 0 at this point, the
* while () loop in acpi_ec_event_handler() is still running
* and incrementing events_to_process will cause it to invoke
* acpi_ec_submit_query() once more, so it is not necessary to
* queue up the event work to start the same loop again.
*/
if (ec->events_to_process++ > 0)
return true;
if (ec->event_state != EC_EVENT_READY)
return;

ec->events_in_progress++;
return queue_work(ec_wq, &ec->work);
}
ec_dbg_evt("Command(%s) submitted/blocked",
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));

ec->event_state = EC_EVENT_IN_PROGRESS;
/*
* The event handling work has not been completed yet, so it needs to be
* flushed.
* If events_to_process is greater than 0 at this point, the while ()
* loop in acpi_ec_event_handler() is still running and incrementing
* events_to_process will cause it to invoke acpi_ec_submit_query() once
* more, so it is not necessary to queue up the event work to start the
* same loop again.
*/
return true;
if (ec->events_to_process++ > 0)
return;

ec->events_in_progress++;
queue_work(ec_wq, &ec->work);
}

static void acpi_ec_complete_event(struct acpi_ec *ec)
Expand Down Expand Up @@ -655,11 +654,10 @@ static void acpi_ec_spurious_interrupt(struct acpi_ec *ec, struct transaction *t
acpi_ec_mask_events(ec);
}

static bool advance_transaction(struct acpi_ec *ec, bool interrupt)
static void advance_transaction(struct acpi_ec *ec, bool interrupt)
{
struct transaction *t = ec->curr;
bool wakeup = false;
bool ret = false;
u8 status;

ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id());
Expand Down Expand Up @@ -724,12 +722,10 @@ static bool advance_transaction(struct acpi_ec *ec, bool interrupt)

out:
if (status & ACPI_EC_FLAG_SCI)
ret = acpi_ec_submit_event(ec);
acpi_ec_submit_event(ec);

if (wakeup && interrupt)
wake_up(&ec->wait);

return ret;
}

static void start_transaction(struct acpi_ec *ec)
Expand Down Expand Up @@ -1242,6 +1238,7 @@ static void acpi_ec_event_handler(struct work_struct *work)
acpi_ec_submit_query(ec);

spin_lock_irq(&ec->lock);

ec->events_to_process--;
}

Expand All @@ -1250,27 +1247,30 @@ static void acpi_ec_event_handler(struct work_struct *work)
* event handling work again regardless of whether or not the query
* queued up above is processed successfully.
*/
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT)
if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) {
bool guard_timeout;

acpi_ec_complete_event(ec);
else
acpi_ec_close_event(ec);

spin_unlock_irq(&ec->lock);
ec_dbg_evt("Event stopped");

spin_unlock_irq(&ec->lock);

ec_dbg_evt("Event stopped");
guard_timeout = !!ec_guard(ec);

if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ec_guard(ec)) {
spin_lock_irq(&ec->lock);

/* Take care of SCI_EVT unless someone else is doing that. */
if (!ec->curr)
if (guard_timeout && !ec->curr)
advance_transaction(ec, false);
} else {
acpi_ec_close_event(ec);

spin_unlock_irq(&ec->lock);
ec_dbg_evt("Event stopped");
}

spin_lock_irq(&ec->lock);
ec->events_in_progress--;

spin_unlock_irq(&ec->lock);
}

Expand Down Expand Up @@ -2051,6 +2051,11 @@ void acpi_ec_set_gpe_wake_mask(u8 action)
acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
}

static bool acpi_ec_work_in_progress(struct acpi_ec *ec)
{
return ec->events_in_progress + ec->queries_in_progress > 0;
}

bool acpi_ec_dispatch_gpe(void)
{
bool work_in_progress = false;
Expand Down Expand Up @@ -2084,7 +2089,8 @@ bool acpi_ec_dispatch_gpe(void)
if (acpi_ec_gpe_status_set(first_ec)) {
pm_pr_dbg("ACPI EC GPE status set\n");

work_in_progress = advance_transaction(first_ec, false);
advance_transaction(first_ec, false);
work_in_progress = acpi_ec_work_in_progress(first_ec);
}

spin_unlock_irq(&first_ec->lock);
Expand All @@ -2102,8 +2108,7 @@ bool acpi_ec_dispatch_gpe(void)

spin_lock_irq(&first_ec->lock);

work_in_progress = first_ec->events_in_progress +
first_ec->queries_in_progress > 0;
work_in_progress = acpi_ec_work_in_progress(first_ec);

spin_unlock_irq(&first_ec->lock);
} while (work_in_progress && !pm_wakeup_pending());
Expand Down
44 changes: 44 additions & 0 deletions drivers/acpi/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,53 @@
*
* Add new device IDs before the generic ACPI fan one.
*/

#ifndef _ACPI_FAN_H_
#define _ACPI_FAN_H_

#define ACPI_FAN_DEVICE_IDS \
{"INT3404", }, /* Fan */ \
{"INTC1044", }, /* Fan for Tiger Lake generation */ \
{"INTC1048", }, /* Fan for Alder Lake generation */ \
{"INTC10A2", }, /* Fan for Raptor Lake generation */ \
{"PNP0C0B", } /* Generic ACPI fan */

#define ACPI_FPS_NAME_LEN 20

struct acpi_fan_fps {
u64 control;
u64 trip_point;
u64 speed;
u64 noise_level;
u64 power;
char name[ACPI_FPS_NAME_LEN];
struct device_attribute dev_attr;
};

struct acpi_fan_fif {
u8 revision;
u8 fine_grain_ctrl;
u8 step_size;
u8 low_speed_notification;
};

struct acpi_fan_fst {
u64 revision;
u64 control;
u64 speed;
};

struct acpi_fan {
bool acpi4;
struct acpi_fan_fif fif;
struct acpi_fan_fps *fps;
int fps_count;
struct thermal_cooling_device *cdev;
struct device_attribute fst_speed;
struct device_attribute fine_grain_control;
};

int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst);
int acpi_fan_create_attributes(struct acpi_device *device);
void acpi_fan_delete_attributes(struct acpi_device *device);
#endif
Loading

0 comments on commit 24b2b09

Please sign in to comment.