Skip to content

Commit 7a7a1ca

Browse files
sudeep-hollactmarinas
authored andcommitted
arm64: FFH: Move ACPI specific code into drivers/acpi/arm64/
The ACPI FFH Opregion code can be moved out of arm64 arch code as it just uses SMCCC. Move all the ACPI FFH Opregion code into drivers/acpi/arm64/ffh.c Signed-off-by: Sudeep Holla <[email protected]> Acked-by: Catalin Marinas <[email protected]> Acked-by: Hanjun Guo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 99e7a8a commit 7a7a1ca

File tree

3 files changed

+108
-105
lines changed

3 files changed

+108
-105
lines changed

arch/arm64/kernel/acpi.c

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -422,108 +422,3 @@ void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
422422
{
423423
memblock_mark_nomap(addr, size);
424424
}
425-
426-
#ifdef CONFIG_ACPI_FFH
427-
/*
428-
* Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
429-
* specified in https://developer.arm.com/docs/den0048/latest
430-
*/
431-
struct acpi_ffh_data {
432-
struct acpi_ffh_info info;
433-
void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
434-
unsigned long a2, unsigned long a3,
435-
unsigned long a4, unsigned long a5,
436-
unsigned long a6, unsigned long a7,
437-
struct arm_smccc_res *args,
438-
struct arm_smccc_quirk *res);
439-
void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
440-
struct arm_smccc_1_2_regs *res);
441-
};
442-
443-
int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
444-
{
445-
enum arm_smccc_conduit conduit;
446-
struct acpi_ffh_data *ffh_ctxt;
447-
448-
if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
449-
return -EOPNOTSUPP;
450-
451-
conduit = arm_smccc_1_1_get_conduit();
452-
if (conduit == SMCCC_CONDUIT_NONE) {
453-
pr_err("%s: invalid SMCCC conduit\n", __func__);
454-
return -EOPNOTSUPP;
455-
}
456-
457-
ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
458-
if (!ffh_ctxt)
459-
return -ENOMEM;
460-
461-
if (conduit == SMCCC_CONDUIT_SMC) {
462-
ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
463-
ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
464-
} else {
465-
ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
466-
ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
467-
}
468-
469-
memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
470-
471-
*region_ctxt = ffh_ctxt;
472-
return AE_OK;
473-
}
474-
475-
static bool acpi_ffh_smccc_owner_allowed(u32 fid)
476-
{
477-
int owner = ARM_SMCCC_OWNER_NUM(fid);
478-
479-
if (owner == ARM_SMCCC_OWNER_STANDARD ||
480-
owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
481-
return true;
482-
483-
return false;
484-
}
485-
486-
int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
487-
{
488-
int ret = 0;
489-
struct acpi_ffh_data *ffh_ctxt = region_context;
490-
491-
if (ffh_ctxt->info.offset == 0) {
492-
/* SMC/HVC 32bit call */
493-
struct arm_smccc_res res;
494-
u32 a[8] = { 0 }, *ptr = (u32 *)value;
495-
496-
if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
497-
!acpi_ffh_smccc_owner_allowed(*ptr) ||
498-
ffh_ctxt->info.length > 32) {
499-
ret = AE_ERROR;
500-
} else {
501-
int idx, len = ffh_ctxt->info.length >> 2;
502-
503-
for (idx = 0; idx < len; idx++)
504-
a[idx] = *(ptr + idx);
505-
506-
ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
507-
a[5], a[6], a[7], &res, NULL);
508-
memcpy(value, &res, sizeof(res));
509-
}
510-
511-
} else if (ffh_ctxt->info.offset == 1) {
512-
/* SMC/HVC 64bit call */
513-
struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
514-
515-
if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
516-
!acpi_ffh_smccc_owner_allowed(r->a0) ||
517-
ffh_ctxt->info.length > sizeof(*r)) {
518-
ret = AE_ERROR;
519-
} else {
520-
ffh_ctxt->invoke_ffh64_fn(r, r);
521-
memcpy(value, r, ffh_ctxt->info.length);
522-
}
523-
} else {
524-
ret = AE_ERROR;
525-
}
526-
527-
return ret;
528-
}
529-
#endif /* CONFIG_ACPI_FFH */

drivers/acpi/arm64/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-$(CONFIG_ACPI_AGDI) += agdi.o
33
obj-$(CONFIG_ACPI_APMT) += apmt.o
4+
obj-$(CONFIG_ACPI_FFH) += ffh.o
45
obj-$(CONFIG_ACPI_GTDT) += gtdt.o
56
obj-$(CONFIG_ACPI_IORT) += iort.o
67
obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o

drivers/acpi/arm64/ffh.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <linux/acpi.h>
3+
#include <linux/arm-smccc.h>
4+
#include <linux/slab.h>
5+
6+
/*
7+
* Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
8+
* specified in https://developer.arm.com/docs/den0048/latest
9+
*/
10+
struct acpi_ffh_data {
11+
struct acpi_ffh_info info;
12+
void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
13+
unsigned long a2, unsigned long a3,
14+
unsigned long a4, unsigned long a5,
15+
unsigned long a6, unsigned long a7,
16+
struct arm_smccc_res *args,
17+
struct arm_smccc_quirk *res);
18+
void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
19+
struct arm_smccc_1_2_regs *res);
20+
};
21+
22+
int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
23+
{
24+
enum arm_smccc_conduit conduit;
25+
struct acpi_ffh_data *ffh_ctxt;
26+
27+
if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
28+
return -EOPNOTSUPP;
29+
30+
conduit = arm_smccc_1_1_get_conduit();
31+
if (conduit == SMCCC_CONDUIT_NONE) {
32+
pr_err("%s: invalid SMCCC conduit\n", __func__);
33+
return -EOPNOTSUPP;
34+
}
35+
36+
ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
37+
if (!ffh_ctxt)
38+
return -ENOMEM;
39+
40+
if (conduit == SMCCC_CONDUIT_SMC) {
41+
ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
42+
ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
43+
} else {
44+
ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
45+
ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
46+
}
47+
48+
memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
49+
50+
*region_ctxt = ffh_ctxt;
51+
return AE_OK;
52+
}
53+
54+
static bool acpi_ffh_smccc_owner_allowed(u32 fid)
55+
{
56+
int owner = ARM_SMCCC_OWNER_NUM(fid);
57+
58+
if (owner == ARM_SMCCC_OWNER_STANDARD ||
59+
owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
60+
return true;
61+
62+
return false;
63+
}
64+
65+
int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
66+
{
67+
int ret = 0;
68+
struct acpi_ffh_data *ffh_ctxt = region_context;
69+
70+
if (ffh_ctxt->info.offset == 0) {
71+
/* SMC/HVC 32bit call */
72+
struct arm_smccc_res res;
73+
u32 a[8] = { 0 }, *ptr = (u32 *)value;
74+
75+
if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
76+
!acpi_ffh_smccc_owner_allowed(*ptr) ||
77+
ffh_ctxt->info.length > 32) {
78+
ret = AE_ERROR;
79+
} else {
80+
int idx, len = ffh_ctxt->info.length >> 2;
81+
82+
for (idx = 0; idx < len; idx++)
83+
a[idx] = *(ptr + idx);
84+
85+
ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
86+
a[5], a[6], a[7], &res, NULL);
87+
memcpy(value, &res, sizeof(res));
88+
}
89+
90+
} else if (ffh_ctxt->info.offset == 1) {
91+
/* SMC/HVC 64bit call */
92+
struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
93+
94+
if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
95+
!acpi_ffh_smccc_owner_allowed(r->a0) ||
96+
ffh_ctxt->info.length > sizeof(*r)) {
97+
ret = AE_ERROR;
98+
} else {
99+
ffh_ctxt->invoke_ffh64_fn(r, r);
100+
memcpy(value, r, ffh_ctxt->info.length);
101+
}
102+
} else {
103+
ret = AE_ERROR;
104+
}
105+
106+
return ret;
107+
}

0 commit comments

Comments
 (0)