diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-13 15:39:15 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-13 15:39:15 -0800 |
| commit | f50822fd8675c68d294e89bd102f7b487ca3acd3 (patch) | |
| tree | 75d0db9313494a2ede74761d5ff712e3c547ff37 /drivers/platform/x86/amd | |
| parent | 1b49e363252632d0493546511a41a65ed1a6fbbb (diff) | |
| parent | 5a5203a45b063a594e89a2aeaf9e4923893a5b4c (diff) | |
Merge tag 'platform-drivers-x86-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Ilpo Järvinen:
"Highlights:
- amd/pmf:
- Avoid overwriting BIOS input values when events occur rapidly
- Fix PMF driver issues related to S4 (in part on crypto/ccp side)
- Add NPU metrics API (for accel side consumers)
- Allow disabling Smart PC function through a module parameter
- asus-wmi & HID/asus:
- Unification of backlight control (replaces quirks)
- Support multiple interfaces for controlling keyboard/RGB brightness
- Simplify init sequence
- hp-wmi:
- Add manual fan control for Victus S models
- Add fan mode keep-alive
- Fix platform profile values for Omen 16-wf1xxx
- Add EC offset to get the thermal profile
- intel/pmc: Show substate residencies also for non-primary PMCs
- intel/ISST:
- Store and restore data for all domains
- Write interface improvements
- lenovo-wmi:
- Support multiple Capability Data
- Add HWMON reporting and tuning support
- mellanox/mlx-platform: Add HI173 & HI174 support
- surface/aggregator_registry: Add Surface Pro 11 (QCOM)
- thinkpad_acpi: Add support for HW damage detection capability
- uniwill: Implement cTGP setting
- wmi:
- Introduce marshalling support
- Convert a few drivers to use the new buffer-based WMI API
- tools/power/x86/intel-speed-select: Allow read operations for non-root
- Miscellaneous cleanups / refactoring / improvements"
* tag 'platform-drivers-x86-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (68 commits)
platform/x86: lenovo-wmi-{capdata,other}: Fix HWMON channel visibility
platform/x86: hp-wmi: Add EC offsets to read Victus S thermal profile
platform: mellanox: mlx-platform: Add support DGX flavor of next-generation 800GB/s ethernet switch.
platform: mellanox: mlx-platform: Add support for new Nvidia DGX system based on class VMOD0010
HID: asus: add support for the asus-wmi brightness handler
platform/x86: asus-wmi: add keyboard brightness event handler
platform/x86: asus-wmi: remove unused keyboard backlight quirk
HID: asus: listen to the asus-wmi brightness device instead of creating one
platform/x86: asus-wmi: Add support for multiple kbd led handlers
HID: asus: early return for ROG devices
HID: asus: move vendor initialization to probe
HID: asus: fortify keyboard handshake
HID: asus: use same report_id in response
HID: asus: initialize additional endpoints only for certain devices
HID: asus: simplify RGB init sequence
platform/wmi: string-kunit: Add missing oversized string test case
platform/x86/amd/pmf: Added a module parameter to disable the Smart PC function
platform/x86/uniwill: Implement cTGP setting
platform/x86: uniwill-laptop: Introduce device descriptor system
platform/x86/amd: Use scope-based cleanup for wbrf_record()
...
Diffstat (limited to 'drivers/platform/x86/amd')
| -rw-r--r-- | drivers/platform/x86/amd/pmf/acpi.c | 40 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/core.c | 161 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/pmf.h | 33 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/spc.c | 33 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/tee-if.c | 14 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/wbrf.c | 25 |
6 files changed, 260 insertions, 46 deletions
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c index 13c4fec2c7ef..3d94b03cf794 100644 --- a/drivers/platform/x86/amd/pmf/acpi.c +++ b/drivers/platform/x86/amd/pmf/acpi.c @@ -9,6 +9,9 @@ */ #include <linux/acpi.h> +#include <linux/array_size.h> +#include <linux/cleanup.h> +#include <linux/dev_printk.h> #include "pmf.h" #define APMF_CQL_NOTIFICATION 2 @@ -331,6 +334,39 @@ int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req req, sizeof(*req)); } +/* Store custom BIOS inputs data in ring buffer */ +static void amd_pmf_custom_bios_inputs_rb(struct amd_pmf_dev *pmf_dev) +{ + struct pmf_cbi_ring_buffer *rb = &pmf_dev->cbi_buf; + int i; + + guard(mutex)(&pmf_dev->cbi_mutex); + + switch (pmf_dev->cpu_id) { + case AMD_CPU_ID_PS: + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs_v1); i++) + rb->data[rb->head].val[i] = pmf_dev->req1.custom_policy[i]; + rb->data[rb->head].preq = pmf_dev->req1.pending_req; + break; + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) + rb->data[rb->head].val[i] = pmf_dev->req.custom_policy[i]; + rb->data[rb->head].preq = pmf_dev->req.pending_req; + break; + default: + return; + } + + if (CIRC_SPACE(rb->head, rb->tail, CUSTOM_BIOS_INPUT_RING_ENTRIES) == 0) { + /* Rare case: ensures the newest BIOS input value is kept */ + dev_warn(pmf_dev->dev, "Overwriting BIOS input value, data may be lost\n"); + rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1); + } + + rb->head = (rb->head + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1); +} + static void amd_pmf_handle_early_preq(struct amd_pmf_dev *pdev) { if (!pdev->cb_flag) @@ -356,6 +392,8 @@ static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data) dev_dbg(pmf_dev->dev, "Pending request (preq): 0x%x\n", pmf_dev->req.pending_req); amd_pmf_handle_early_preq(pmf_dev); + + amd_pmf_custom_bios_inputs_rb(pmf_dev); } static void apmf_event_handler_v1(acpi_handle handle, u32 event, void *data) @@ -374,6 +412,8 @@ static void apmf_event_handler_v1(acpi_handle handle, u32 event, void *data) dev_dbg(pmf_dev->dev, "Pending request (preq1): 0x%x\n", pmf_dev->req1.pending_req); amd_pmf_handle_early_preq(pmf_dev); + + amd_pmf_custom_bios_inputs_rb(pmf_dev); } static void apmf_event_handler(acpi_handle handle, u32 event, void *data) diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index 8fc293c9c538..b9e5a2cf3aae 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -8,12 +8,16 @@ * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> */ +#include <linux/array_size.h> +#include <linux/cleanup.h> #include <linux/debugfs.h> #include <linux/iopoll.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/power_supply.h> +#include <linux/string.h> #include <asm/amd/node.h> #include "pmf.h" @@ -53,6 +57,12 @@ static bool force_load; module_param(force_load, bool, 0444); MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)"); +static bool smart_pc_support = true; +module_param(smart_pc_support, bool, 0444); +MODULE_PARM_DESC(smart_pc_support, "Smart PC Support (default = true)"); + +static struct device *pmf_device; + static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data) { struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier); @@ -314,6 +324,126 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) return 0; } +static int is_npu_metrics_supported(struct amd_pmf_dev *pdev) +{ + switch (pdev->cpu_id) { + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int amd_pmf_get_smu_metrics(struct amd_pmf_dev *dev, struct amd_pmf_npu_metrics *data) +{ + int ret, i; + + guard(mutex)(&dev->metrics_mutex); + + ret = is_npu_metrics_supported(dev); + if (ret) + return ret; + + ret = amd_pmf_set_dram_addr(dev, true); + if (ret) + return ret; + + memset(dev->buf, 0, dev->mtable_size); + + /* Send SMU command to get NPU metrics */ + ret = amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, SET_CMD, METRICS_TABLE_ID, NULL); + if (ret) { + dev_err(dev->dev, "SMU command failed to get NPU metrics: %d\n", ret); + return ret; + } + + memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size); + + data->npuclk_freq = dev->m_table_v2.npuclk_freq; + for (i = 0; i < ARRAY_SIZE(data->npu_busy); i++) + data->npu_busy[i] = dev->m_table_v2.npu_busy[i]; + data->npu_power = dev->m_table_v2.npu_power; + data->mpnpuclk_freq = dev->m_table_v2.mpnpuclk_freq; + data->npu_reads = dev->m_table_v2.npu_reads; + data->npu_writes = dev->m_table_v2.npu_writes; + + return 0; +} + +int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info) +{ + struct amd_pmf_dev *pdev; + + if (!info) + return -EINVAL; + + if (!pmf_device) + return -ENODEV; + + pdev = dev_get_drvdata(pmf_device); + if (!pdev) + return -ENODEV; + + return amd_pmf_get_smu_metrics(pdev, info); +} +EXPORT_SYMBOL_NS_GPL(amd_pmf_get_npu_data, "AMD_PMF"); + +static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev) +{ + bool status; + int ret, i; + + for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) { + ret = amd_pmf_tee_init(pdev, &amd_pmf_ta_uuid[i]); + if (ret) { + dev_err(pdev->dev, "TEE init failed for UUID[%d] ret: %d\n", i, ret); + return ret; + } + + ret = amd_pmf_start_policy_engine(pdev); + dev_dbg(pdev->dev, "start policy engine ret: %d (UUID idx: %d)\n", ret, i); + status = ret == TA_PMF_TYPE_SUCCESS; + if (status) + break; + amd_pmf_tee_deinit(pdev); + } + + return 0; +} + +static int amd_pmf_restore_handler(struct device *dev) +{ + struct amd_pmf_dev *pdev = dev_get_drvdata(dev); + int ret; + + if (pdev->buf) { + ret = amd_pmf_set_dram_addr(pdev, false); + if (ret) + return ret; + } + + if (pdev->smart_pc_enabled) + amd_pmf_reinit_ta(pdev); + + return 0; +} + +static int amd_pmf_freeze_handler(struct device *dev) +{ + struct amd_pmf_dev *pdev = dev_get_drvdata(dev); + + if (!pdev->smart_pc_enabled) + return 0; + + cancel_delayed_work_sync(&pdev->pb_work); + /* Clear all TEE resources */ + amd_pmf_tee_deinit(pdev); + pdev->session_id = 0; + + return 0; +} + static int amd_pmf_suspend_handler(struct device *dev) { struct amd_pmf_dev *pdev = dev_get_drvdata(dev); @@ -347,7 +477,12 @@ static int amd_pmf_resume_handler(struct device *dev) return 0; } -static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, amd_pmf_resume_handler); +static const struct dev_pm_ops amd_pmf_pm = { + .suspend = amd_pmf_suspend_handler, + .resume = amd_pmf_resume_handler, + .freeze = amd_pmf_freeze_handler, + .restore = amd_pmf_restore_handler, +}; static void amd_pmf_init_features(struct amd_pmf_dev *dev) { @@ -362,11 +497,15 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev) dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n"); } - amd_pmf_init_smart_pc(dev); - if (dev->smart_pc_enabled) { - dev_dbg(dev->dev, "Smart PC Solution Enabled\n"); - /* If Smart PC is enabled, no need to check for other features */ - return; + if (smart_pc_support) { + amd_pmf_init_smart_pc(dev); + if (dev->smart_pc_enabled) { + dev_dbg(dev->dev, "Smart PC Solution Enabled\n"); + /* If Smart PC is enabled, no need to check for other features */ + return; + } + } else { + dev->smart_pc_enabled = false; } if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { @@ -477,6 +616,14 @@ static int amd_pmf_probe(struct platform_device *pdev) if (err) return err; + err = devm_mutex_init(dev->dev, &dev->cbi_mutex); + if (err) + return err; + + err = devm_mutex_init(dev->dev, &dev->metrics_mutex); + if (err) + return err; + apmf_acpi_init(dev); platform_set_drvdata(pdev, dev); amd_pmf_dbgfs_register(dev); @@ -485,6 +632,8 @@ static int amd_pmf_probe(struct platform_device *pdev) if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2)) amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD); + pmf_device = dev->dev; + dev_info(dev->dev, "registered PMF device successfully\n"); return 0; diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 9144c8c3bbaf..69fef7448744 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -12,7 +12,10 @@ #define PMF_H #include <linux/acpi.h> +#include <linux/amd-pmf-io.h> +#include <linux/circ_buf.h> #include <linux/input.h> +#include <linux/mutex_types.h> #include <linux/platform_device.h> #include <linux/platform_profile.h> @@ -120,6 +123,7 @@ struct cookie_header { #define APTS_MAX_STATES 16 #define CUSTOM_BIOS_INPUT_BITS GENMASK(16, 7) #define BIOS_INPUTS_MAX 10 +#define CUSTOM_BIOS_INPUT_RING_ENTRIES 64 /* Must be power of two for CIRC_* macros */ /* amd_pmf_send_cmd() set/get */ #define SET_CMD false @@ -129,6 +133,12 @@ struct cookie_header { typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data); +static const uuid_t amd_pmf_ta_uuid[] __used = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8, + 0x8a, 0xcc, 0x2b, 0x2b, 0x60, 0xd6), + UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d, + 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43), + }; + /* APTS PMF BIOS Interface */ struct amd_pmf_apts_output { u16 table_version; @@ -365,6 +375,22 @@ struct pmf_bios_inputs_prev { u32 custom_bios_inputs[BIOS_INPUTS_MAX]; }; +/** + * struct pmf_bios_input_entry - Snapshot of custom BIOS input event + * @val: Array of custom BIOS input values + * @preq: Pending request value associated with this event + */ +struct pmf_bios_input_entry { + u32 val[BIOS_INPUTS_MAX]; + u32 preq; +}; + +struct pmf_cbi_ring_buffer { + struct pmf_bios_input_entry data[CUSTOM_BIOS_INPUT_RING_ENTRIES]; + int head; + int tail; +}; + struct amd_pmf_dev { void __iomem *regbase; void __iomem *smu_virt_addr; @@ -413,6 +439,9 @@ struct amd_pmf_dev { struct apmf_sbios_req_v1 req1; struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */ bool cb_flag; /* To handle first custom BIOS input */ + struct pmf_cbi_ring_buffer cbi_buf; + struct mutex cbi_mutex; /* Protects ring buffer access */ + struct mutex metrics_mutex; }; struct apmf_sps_prop_granular_v2 { @@ -895,4 +924,8 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev); +int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid); +void amd_pmf_tee_deinit(struct amd_pmf_dev *dev); +int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev); + #endif /* PMF_H */ diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c index 0a37dc6a7950..f48678a23cc7 100644 --- a/drivers/platform/x86/amd/pmf/spc.c +++ b/drivers/platform/x86/amd/pmf/spc.c @@ -11,6 +11,7 @@ #include <acpi/button.h> #include <linux/amd-pmf-io.h> +#include <linux/cleanup.h> #include <linux/power_supply.h> #include <linux/units.h> #include "pmf.h" @@ -132,32 +133,39 @@ static void amd_pmf_set_ta_custom_bios_input(struct ta_pmf_enact_table *in, int } } -static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, u32 pending_req, +static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, struct pmf_bios_input_entry *data, const struct amd_pmf_pb_bitmap *inputs, - const u32 *custom_policy, struct ta_pmf_enact_table *in) + struct ta_pmf_enact_table *in) { unsigned int i; for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) { - if (!(pending_req & inputs[i].bit_mask)) + if (!(data->preq & inputs[i].bit_mask)) continue; - amd_pmf_set_ta_custom_bios_input(in, i, custom_policy[i]); - pdev->cb_prev.custom_bios_inputs[i] = custom_policy[i]; - dev_dbg(pdev->dev, "Custom BIOS Input[%d]: %u\n", i, custom_policy[i]); + amd_pmf_set_ta_custom_bios_input(in, i, data->val[i]); + pdev->cb_prev.custom_bios_inputs[i] = data->val[i]; + dev_dbg(pdev->dev, "Custom BIOS Input[%d]: %u\n", i, data->val[i]); } } static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev, struct ta_pmf_enact_table *in) { + struct pmf_cbi_ring_buffer *rb = &pdev->cbi_buf; unsigned int i; + guard(mutex)(&pdev->cbi_mutex); + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) amd_pmf_set_ta_custom_bios_input(in, i, pdev->cb_prev.custom_bios_inputs[i]); - if (!(pdev->req.pending_req || pdev->req1.pending_req)) + if (CIRC_CNT(rb->head, rb->tail, CUSTOM_BIOS_INPUT_RING_ENTRIES) == 0) return; + /* If no active custom BIOS input pending request, do not consume further work */ + if (!rb->data[rb->tail].preq) + goto out_rbadvance; + if (!pdev->smart_pc_enabled) return; @@ -165,20 +173,17 @@ static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev, case PMF_IF_V1: if (!is_apmf_bios_input_notifications_supported(pdev)) return; - amd_pmf_update_bios_inputs(pdev, pdev->req1.pending_req, custom_bios_inputs_v1, - pdev->req1.custom_policy, in); + amd_pmf_update_bios_inputs(pdev, &rb->data[rb->tail], custom_bios_inputs_v1, in); break; case PMF_IF_V2: - amd_pmf_update_bios_inputs(pdev, pdev->req.pending_req, custom_bios_inputs, - pdev->req.custom_policy, in); + amd_pmf_update_bios_inputs(pdev, &rb->data[rb->tail], custom_bios_inputs, in); break; default: break; } - /* Clear pending requests after handling */ - memset(&pdev->req, 0, sizeof(pdev->req)); - memset(&pdev->req1, 0, sizeof(pdev->req1)); +out_rbadvance: + rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1); } static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in) diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c index 0abce76f89ff..7ccd93f506b2 100644 --- a/drivers/platform/x86/amd/pmf/tee-if.c +++ b/drivers/platform/x86/amd/pmf/tee-if.c @@ -27,12 +27,6 @@ module_param(pb_side_load, bool, 0444); MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures"); #endif -static const uuid_t amd_pmf_ta_uuid[] = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8, 0x8a, - 0xcc, 0x2b, 0x2b, 0x60, 0xd6), - UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d, 0xc5, - 0x29, 0xb1, 0x3d, 0x85, 0x43), - }; - static const char *amd_pmf_uevent_as_str(unsigned int state) { switch (state) { @@ -324,7 +318,7 @@ static void amd_pmf_invoke_cmd(struct work_struct *work) schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms)); } -static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) +int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) { struct cookie_header *header; int res; @@ -480,7 +474,7 @@ static int amd_pmf_register_input_device(struct amd_pmf_dev *dev) return 0; } -static int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid) +int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid) { u32 size; int ret; @@ -528,7 +522,7 @@ out_ctx: return ret; } -static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev) +void amd_pmf_tee_deinit(struct amd_pmf_dev *dev) { if (!dev->tee_ctx) return; @@ -591,6 +585,8 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) status = ret == TA_PMF_TYPE_SUCCESS; if (status) { dev->cb_flag = true; + dev->cbi_buf.head = 0; + dev->cbi_buf.tail = 0; break; } amd_pmf_tee_deinit(dev); diff --git a/drivers/platform/x86/amd/wbrf.c b/drivers/platform/x86/amd/wbrf.c index 0f58d252b620..dc10d12bc80d 100644 --- a/drivers/platform/x86/amd/wbrf.c +++ b/drivers/platform/x86/amd/wbrf.c @@ -42,8 +42,6 @@ static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head); static int wbrf_record(struct acpi_device *adev, uint8_t action, struct wbrf_ranges_in_out *in) { union acpi_object argv4; - union acpi_object *tmp; - union acpi_object *obj; u32 num_of_ranges = 0; u32 num_of_elements; u32 arg_idx = 0; @@ -74,7 +72,7 @@ static int wbrf_record(struct acpi_device *adev, uint8_t action, struct wbrf_ran */ num_of_elements = 2 * num_of_ranges + 2; - tmp = kcalloc(num_of_elements, sizeof(*tmp), GFP_KERNEL); + union acpi_object *tmp __free(kfree) = kcalloc(num_of_elements, sizeof(*tmp), GFP_KERNEL); if (!tmp) return -ENOMEM; @@ -101,26 +99,19 @@ static int wbrf_record(struct acpi_device *adev, uint8_t action, struct wbrf_ran tmp[arg_idx++].integer.value = in->band_list[i].end; } - obj = acpi_evaluate_dsm(adev->handle, &wifi_acpi_dsm_guid, - WBRF_REVISION, WBRF_RECORD, &argv4); + union acpi_object *obj __free(kfree) = + acpi_evaluate_dsm(adev->handle, &wifi_acpi_dsm_guid, + WBRF_REVISION, WBRF_RECORD, &argv4); - if (!obj) { - kfree(tmp); + if (!obj) return -EINVAL; - } - if (obj->type != ACPI_TYPE_INTEGER) { - ret = -EINVAL; - goto out; - } + if (obj->type != ACPI_TYPE_INTEGER) + return -EINVAL; ret = obj->integer.value; if (ret) - ret = -EINVAL; - -out: - ACPI_FREE(obj); - kfree(tmp); + return -EINVAL; return ret; } |
