Skip to content

Commit 240a3fd

Browse files
committed
Merge: platform/x86/amd/pmf: updates
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1374 Description: Updates for AMD PMF, or Platform Management Framework. JIRA: https://issues.redhat.com/browse/RHEL-104142 Build Info: 68733364 Tested: Successful tested on AMD (amd-strix-01) system. Signed-off-by: Steve Best <sbest@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Scott Weaver <scweaver@redhat.com>
2 parents b2dac9e + 77d621c commit 240a3fd

File tree

11 files changed

+285
-186
lines changed

11 files changed

+285
-186
lines changed

drivers/platform/x86/amd/pmf/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ config AMD_PMF
1111
select ACPI_PLATFORM_PROFILE
1212
depends on TEE && AMDTEE
1313
depends on AMD_SFH_HID
14+
depends on HAS_IOMEM
1415
help
1516
This driver provides support for the AMD Platform Management Framework.
1617
The goal is to enhance end user experience by making AMD PCs smarter,

drivers/platform/x86/amd/pmf/Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# AMD Platform Management Framework
55
#
66

7-
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
8-
amd-pmf-objs := core.o acpi.o sps.o \
9-
auto-mode.o cnqf.o \
10-
tee-if.o spc.o pmf-quirks.o
7+
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
8+
amd-pmf-y := core.o acpi.o sps.o \
9+
auto-mode.o cnqf.o \
10+
tee-if.o spc.o

drivers/platform/x86/amd/pmf/acpi.c

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static void apmf_sbios_heartbeat_notify(struct work_struct *work)
220220
if (!info)
221221
return;
222222

223-
schedule_delayed_work(&dev->heart_beat, msecs_to_jiffies(dev->hb_interval * 1000));
223+
schedule_delayed_work(&dev->heart_beat, secs_to_jiffies(dev->hb_interval));
224224
kfree(info);
225225
}
226226

@@ -321,17 +321,29 @@ int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req
321321
req, sizeof(*req));
322322
}
323323

324+
static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data)
325+
{
326+
struct amd_pmf_dev *pmf_dev = data;
327+
int ret;
328+
329+
guard(mutex)(&pmf_dev->cb_mutex);
330+
331+
ret = apmf_get_sbios_requests_v2(pmf_dev, &pmf_dev->req);
332+
if (ret)
333+
dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret);
334+
}
335+
324336
static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
325337
{
326338
struct amd_pmf_dev *pmf_dev = data;
327339
struct apmf_sbios_req req;
328340
int ret;
329341

330-
mutex_lock(&pmf_dev->update_mutex);
342+
guard(mutex)(&pmf_dev->update_mutex);
331343
ret = apmf_get_sbios_requests(pmf_dev, &req);
332344
if (ret) {
333345
dev_err(pmf_dev->dev, "Failed to get SBIOS requests:%d\n", ret);
334-
goto out;
346+
return;
335347
}
336348

337349
if (req.pending_req & BIT(APMF_AMT_NOTIFICATION)) {
@@ -353,8 +365,6 @@ static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
353365
if (pmf_dev->amt_enabled)
354366
amd_pmf_update_2_cql(pmf_dev, req.cql_event);
355367
}
356-
out:
357-
mutex_unlock(&pmf_dev->update_mutex);
358368
}
359369

360370
static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
@@ -430,40 +440,41 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
430440
apmf_event_handler(ahandle, 0, pmf_dev);
431441
}
432442

433-
return 0;
434-
}
435-
436-
static acpi_status apmf_walk_resources(struct acpi_resource *res, void *data)
437-
{
438-
struct amd_pmf_dev *dev = data;
439-
440-
switch (res->type) {
441-
case ACPI_RESOURCE_TYPE_ADDRESS64:
442-
dev->policy_addr = res->data.address64.address.minimum;
443-
dev->policy_sz = res->data.address64.address.address_length;
444-
break;
445-
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
446-
dev->policy_addr = res->data.fixed_memory32.address;
447-
dev->policy_sz = res->data.fixed_memory32.address_length;
448-
break;
449-
}
450-
451-
if (!dev->policy_addr || dev->policy_sz > POLICY_BUF_MAX_SZ || dev->policy_sz == 0) {
452-
pr_err("Incorrect Policy params, possibly a SBIOS bug\n");
453-
return AE_ERROR;
443+
if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) {
444+
status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY,
445+
apmf_event_handler_v2, pmf_dev);
446+
if (ACPI_FAILURE(status)) {
447+
dev_err(pmf_dev->dev, "failed to install notify handler for custom BIOS inputs\n");
448+
return -ENODEV;
449+
}
454450
}
455451

456-
return AE_OK;
452+
return 0;
457453
}
458454

459455
int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
460456
{
461-
acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
462-
acpi_status status;
457+
struct platform_device *pdev = to_platform_device(pmf_dev->dev);
463458

464-
status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
465-
if (ACPI_FAILURE(status)) {
466-
dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
459+
pmf_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
460+
if (!pmf_dev->res) {
461+
dev_dbg(pmf_dev->dev, "Failed to get I/O memory resource\n");
462+
return -EINVAL;
463+
}
464+
465+
pmf_dev->policy_addr = pmf_dev->res->start;
466+
/*
467+
* We cannot use resource_size() here because it adds an extra byte to round off the size.
468+
* In the case of PMF ResourceTemplate(), this rounding is already handled within the _CRS.
469+
* Using resource_size() would increase the resource size by 1, causing a mismatch with the
470+
* length field and leading to issues. Therefore, simply use end-start of the ACPI resource
471+
* to obtain the actual length.
472+
*/
473+
pmf_dev->policy_sz = pmf_dev->res->end - pmf_dev->res->start;
474+
475+
if (!pmf_dev->policy_addr || pmf_dev->policy_sz > POLICY_BUF_MAX_SZ ||
476+
pmf_dev->policy_sz == 0) {
477+
dev_err(pmf_dev->dev, "Incorrect policy params, possibly a SBIOS bug\n");
467478
return -EINVAL;
468479
}
469480

@@ -488,6 +499,9 @@ void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
488499
if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
489500
is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS))
490501
acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler);
502+
503+
if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2)
504+
acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler_v2);
491505
}
492506

493507
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)

drivers/platform/x86/amd/pmf/auto-mode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
120120
amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
121121
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
122122
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
123-
pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
123+
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_APU]), NULL);
124124
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
125-
pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
125+
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_HS2]), NULL);
126126

127127
if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
128128
apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,

drivers/platform/x86/amd/pmf/cnqf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx,
8181
amd_pmf_send_cmd(dev, SET_SPPT, false, pc->sppt, NULL);
8282
amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pc->sppt_apu_only, NULL);
8383
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pc->stt_min, NULL);
84-
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, pc->stt_skin_temp[STT_TEMP_APU],
85-
NULL);
86-
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, pc->stt_skin_temp[STT_TEMP_HS2],
87-
NULL);
84+
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
85+
fixp_q88_fromint(pc->stt_skin_temp[STT_TEMP_APU]), NULL);
86+
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
87+
fixp_q88_fromint(pc->stt_skin_temp[STT_TEMP_HS2]), NULL);
8888

8989
if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
9090
apmf_update_fan_idx(dev,

drivers/platform/x86/amd/pmf/core.c

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ static void amd_pmf_get_metrics(struct work_struct *work)
127127
ktime_t time_elapsed_ms;
128128
int socket_power;
129129

130-
mutex_lock(&dev->update_mutex);
130+
guard(mutex)(&dev->update_mutex);
131+
131132
/* Transfer table contents */
132133
memset(dev->buf, 0, sizeof(dev->m_table));
133134
amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
@@ -149,7 +150,6 @@ static void amd_pmf_get_metrics(struct work_struct *work)
149150

150151
dev->start_time = ktime_to_ms(ktime_get());
151152
schedule_delayed_work(&dev->work_buffer, msecs_to_jiffies(metrics_table_loop_ms));
152-
mutex_unlock(&dev->update_mutex);
153153
}
154154

155155
static inline u32 amd_pmf_reg_read(struct amd_pmf_dev *dev, int reg_offset)
@@ -176,20 +176,34 @@ static void __maybe_unused amd_pmf_dump_registers(struct amd_pmf_dev *dev)
176176
dev_dbg(dev->dev, "AMD_PMF_REGISTER_MESSAGE:%x\n", value);
177177
}
178178

179+
/**
180+
* fixp_q88_fromint: Convert integer to Q8.8
181+
* @val: input value
182+
*
183+
* Converts an integer into binary fixed point format where 8 bits
184+
* are used for integer and 8 bits are used for the decimal.
185+
*
186+
* Return: unsigned integer converted to Q8.8 format
187+
*/
188+
u32 fixp_q88_fromint(u32 val)
189+
{
190+
return val << 8;
191+
}
192+
179193
int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32 *data)
180194
{
181195
int rc;
182196
u32 val;
183197

184-
mutex_lock(&dev->lock);
198+
guard(mutex)(&dev->lock);
185199

186200
/* Wait until we get a valid response */
187201
rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMF_REGISTER_RESPONSE,
188202
val, val != 0, PMF_MSG_DELAY_MIN_US,
189203
PMF_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
190204
if (rc) {
191205
dev_err(dev->dev, "failed to talk to SMU\n");
192-
goto out_unlock;
206+
return rc;
193207
}
194208

195209
/* Write zero to response register */
@@ -207,7 +221,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
207221
PMF_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
208222
if (rc) {
209223
dev_err(dev->dev, "SMU response timed out\n");
210-
goto out_unlock;
224+
return rc;
211225
}
212226

213227
switch (val) {
@@ -221,21 +235,19 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
221235
case AMD_PMF_RESULT_CMD_REJECT_BUSY:
222236
dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val);
223237
rc = -EBUSY;
224-
goto out_unlock;
238+
break;
225239
case AMD_PMF_RESULT_CMD_UNKNOWN:
226240
dev_err(dev->dev, "SMU cmd unknown. err: 0x%x\n", val);
227241
rc = -EINVAL;
228-
goto out_unlock;
242+
break;
229243
case AMD_PMF_RESULT_CMD_REJECT_PREREQ:
230244
case AMD_PMF_RESULT_FAILED:
231245
default:
232246
dev_err(dev->dev, "SMU cmd failed. err: 0x%x\n", val);
233247
rc = -EIO;
234-
goto out_unlock;
248+
break;
235249
}
236250

237-
out_unlock:
238-
mutex_unlock(&dev->lock);
239251
amd_pmf_dump_registers(dev);
240252
return rc;
241253
}
@@ -268,7 +280,7 @@ int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev, bool alloc_buffer)
268280
dev_err(dev->dev, "Invalid CPU id: 0x%x", dev->cpu_id);
269281
}
270282

271-
dev->buf = kzalloc(dev->mtable_size, GFP_KERNEL);
283+
dev->buf = devm_kzalloc(dev->dev, dev->mtable_size, GFP_KERNEL);
272284
if (!dev->buf)
273285
return -ENOMEM;
274286
}
@@ -429,18 +441,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
429441

430442
err = amd_smn_read(0, AMD_PMF_BASE_ADDR_LO, &val);
431443
if (err) {
432-
dev_err(dev->dev, "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_LO);
433444
pci_dev_put(rdev);
434-
return pcibios_err_to_errno(err);
445+
return dev_err_probe(dev->dev, pcibios_err_to_errno(err),
446+
"error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_LO);
435447
}
436448

437449
base_addr_lo = val & AMD_PMF_BASE_ADDR_HI_MASK;
438450

439451
err = amd_smn_read(0, AMD_PMF_BASE_ADDR_HI, &val);
440452
if (err) {
441-
dev_err(dev->dev, "error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_HI);
442453
pci_dev_put(rdev);
443-
return pcibios_err_to_errno(err);
454+
return dev_err_probe(dev->dev, pcibios_err_to_errno(err),
455+
"error in reading from 0x%x\n", AMD_PMF_BASE_ADDR_HI);
444456
}
445457

446458
base_addr_hi = val & AMD_PMF_BASE_ADDR_LO_MASK;
@@ -454,8 +466,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
454466

455467
mutex_init(&dev->lock);
456468
mutex_init(&dev->update_mutex);
469+
mutex_init(&dev->cb_mutex);
457470

458-
amd_pmf_quirks_init(dev);
459471
apmf_acpi_init(dev);
460472
platform_set_drvdata(pdev, dev);
461473
amd_pmf_dbgfs_register(dev);
@@ -480,7 +492,7 @@ static void amd_pmf_remove(struct platform_device *pdev)
480492
amd_pmf_dbgfs_unregister(dev);
481493
mutex_destroy(&dev->lock);
482494
mutex_destroy(&dev->update_mutex);
483-
kfree(dev->buf);
495+
mutex_destroy(&dev->cb_mutex);
484496
}
485497

486498
static const struct attribute_group *amd_pmf_driver_groups[] = {

drivers/platform/x86/amd/pmf/pmf-quirks.c

Lines changed: 0 additions & 66 deletions
This file was deleted.

0 commit comments

Comments
 (0)