Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
f46117bf
Commit
f46117bf
authored
Jun 26, 2023
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge back earlier Intel thermal control material for 6.5.
parents
0bb619f9
ea197ea2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
275 additions
and
0 deletions
+275
-0
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
+218
-0
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
+57
-0
No files found.
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
View file @
f46117bf
...
...
@@ -203,6 +203,151 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp,
}
EXPORT_SYMBOL
(
acpi_parse_art
);
/*
* acpi_parse_psvt - Passive Table (PSVT) for passive cooling
*
* @handle: ACPI handle of the device which contains PSVT
* @psvt_count: the number of valid entries resulted from parsing PSVT
* @psvtp: pointer to array of psvt entries
*
*/
static
int
acpi_parse_psvt
(
acpi_handle
handle
,
int
*
psvt_count
,
struct
psvt
**
psvtp
)
{
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
int
nr_bad_entries
=
0
,
revision
=
0
;
union
acpi_object
*
p
;
acpi_status
status
;
int
i
,
result
=
0
;
struct
psvt
*
psvts
;
if
(
!
acpi_has_method
(
handle
,
"PSVT"
))
return
-
ENODEV
;
status
=
acpi_evaluate_object
(
handle
,
"PSVT"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
p
=
buffer
.
pointer
;
if
(
!
p
||
(
p
->
type
!=
ACPI_TYPE_PACKAGE
))
{
result
=
-
EFAULT
;
goto
end
;
}
/* first package is the revision number */
if
(
p
->
package
.
count
>
0
)
{
union
acpi_object
*
prev
=
&
(
p
->
package
.
elements
[
0
]);
if
(
prev
->
type
==
ACPI_TYPE_INTEGER
)
revision
=
(
int
)
prev
->
integer
.
value
;
}
else
{
result
=
-
EFAULT
;
goto
end
;
}
/* Support only version 2 */
if
(
revision
!=
2
)
{
result
=
-
EFAULT
;
goto
end
;
}
*
psvt_count
=
p
->
package
.
count
-
1
;
if
(
!*
psvt_count
)
{
result
=
-
EFAULT
;
goto
end
;
}
psvts
=
kcalloc
(
*
psvt_count
,
sizeof
(
*
psvts
),
GFP_KERNEL
);
if
(
!
psvts
)
{
result
=
-
ENOMEM
;
goto
end
;
}
/* Start index is 1 because the first package is the revision number */
for
(
i
=
1
;
i
<
p
->
package
.
count
;
i
++
)
{
struct
acpi_buffer
psvt_int_format
=
{
sizeof
(
"RRNNNNNNNNNN"
),
"RRNNNNNNNNNN"
};
struct
acpi_buffer
psvt_str_format
=
{
sizeof
(
"RRNNNNNSNNNN"
),
"RRNNNNNSNNNN"
};
union
acpi_object
*
package
=
&
(
p
->
package
.
elements
[
i
]);
struct
psvt
*
psvt
=
&
psvts
[
i
-
1
-
nr_bad_entries
];
struct
acpi_buffer
*
psvt_format
=
&
psvt_int_format
;
struct
acpi_buffer
element
=
{
0
,
NULL
};
union
acpi_object
*
knob
;
struct
acpi_device
*
res
;
struct
psvt
*
psvt_ptr
;
element
.
length
=
ACPI_ALLOCATE_BUFFER
;
element
.
pointer
=
NULL
;
if
(
package
->
package
.
count
>=
ACPI_NR_PSVT_ELEMENTS
)
{
knob
=
&
(
package
->
package
.
elements
[
ACPI_PSVT_CONTROL_KNOB
]);
}
else
{
nr_bad_entries
++
;
pr_info
(
"PSVT package %d is invalid, ignored
\n
"
,
i
);
continue
;
}
if
(
knob
->
type
==
ACPI_TYPE_STRING
)
{
psvt_format
=
&
psvt_str_format
;
if
(
knob
->
string
.
length
>
ACPI_LIMIT_STR_MAX_LEN
-
1
)
{
pr_info
(
"PSVT package %d limit string len exceeds max
\n
"
,
i
);
knob
->
string
.
length
=
ACPI_LIMIT_STR_MAX_LEN
-
1
;
}
}
status
=
acpi_extract_package
(
&
(
p
->
package
.
elements
[
i
]),
psvt_format
,
&
element
);
if
(
ACPI_FAILURE
(
status
))
{
nr_bad_entries
++
;
pr_info
(
"PSVT package %d is invalid, ignored
\n
"
,
i
);
continue
;
}
psvt_ptr
=
(
struct
psvt
*
)
element
.
pointer
;
memcpy
(
psvt
,
psvt_ptr
,
sizeof
(
*
psvt
));
/* The limit element can be string or U64 */
psvt
->
control_knob_type
=
(
u64
)
knob
->
type
;
if
(
knob
->
type
==
ACPI_TYPE_STRING
)
{
memset
(
&
psvt
->
limit
,
0
,
sizeof
(
u64
));
strncpy
(
psvt
->
limit
.
string
,
psvt_ptr
->
limit
.
str_ptr
,
knob
->
string
.
length
);
}
else
{
psvt
->
limit
.
integer
=
psvt_ptr
->
limit
.
integer
;
}
kfree
(
element
.
pointer
);
res
=
acpi_fetch_acpi_dev
(
psvt
->
source
);
if
(
!
res
)
{
nr_bad_entries
++
;
pr_info
(
"Failed to get source ACPI device
\n
"
);
continue
;
}
res
=
acpi_fetch_acpi_dev
(
psvt
->
target
);
if
(
!
res
)
{
nr_bad_entries
++
;
pr_info
(
"Failed to get target ACPI device
\n
"
);
continue
;
}
}
/* don't count bad entries */
*
psvt_count
-=
nr_bad_entries
;
if
(
!*
psvt_count
)
{
result
=
-
EFAULT
;
kfree
(
psvts
);
goto
end
;
}
*
psvtp
=
psvts
;
return
0
;
end:
kfree
(
buffer
.
pointer
);
return
result
;
}
/* get device name from acpi handle */
static
void
get_single_name
(
acpi_handle
handle
,
char
*
name
)
...
...
@@ -289,6 +434,57 @@ static int fill_trt(char __user *ubuf)
return
ret
;
}
static
int
fill_psvt
(
char
__user
*
ubuf
)
{
int
i
,
ret
,
count
,
psvt_len
;
union
psvt_object
*
psvt_user
;
struct
psvt
*
psvts
;
ret
=
acpi_parse_psvt
(
acpi_thermal_rel_handle
,
&
count
,
&
psvts
);
if
(
ret
)
return
ret
;
psvt_len
=
count
*
sizeof
(
*
psvt_user
);
psvt_user
=
kzalloc
(
psvt_len
,
GFP_KERNEL
);
if
(
!
psvt_user
)
{
ret
=
-
ENOMEM
;
goto
free_psvt
;
}
/* now fill in user psvt data */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
/* userspace psvt needs device name instead of acpi reference */
get_single_name
(
psvts
[
i
].
source
,
psvt_user
[
i
].
source_device
);
get_single_name
(
psvts
[
i
].
target
,
psvt_user
[
i
].
target_device
);
psvt_user
[
i
].
priority
=
psvts
[
i
].
priority
;
psvt_user
[
i
].
sample_period
=
psvts
[
i
].
sample_period
;
psvt_user
[
i
].
passive_temp
=
psvts
[
i
].
passive_temp
;
psvt_user
[
i
].
source_domain
=
psvts
[
i
].
source_domain
;
psvt_user
[
i
].
control_knob
=
psvts
[
i
].
control_knob
;
psvt_user
[
i
].
step_size
=
psvts
[
i
].
step_size
;
psvt_user
[
i
].
limit_coeff
=
psvts
[
i
].
limit_coeff
;
psvt_user
[
i
].
unlimit_coeff
=
psvts
[
i
].
unlimit_coeff
;
psvt_user
[
i
].
control_knob_type
=
psvts
[
i
].
control_knob_type
;
if
(
psvt_user
[
i
].
control_knob_type
==
ACPI_TYPE_STRING
)
strncpy
(
psvt_user
[
i
].
limit
.
string
,
psvts
[
i
].
limit
.
string
,
ACPI_LIMIT_STR_MAX_LEN
);
else
psvt_user
[
i
].
limit
.
integer
=
psvts
[
i
].
limit
.
integer
;
}
if
(
copy_to_user
(
ubuf
,
psvt_user
,
psvt_len
))
ret
=
-
EFAULT
;
kfree
(
psvt_user
);
free_psvt:
kfree
(
psvts
);
return
ret
;
}
static
long
acpi_thermal_rel_ioctl
(
struct
file
*
f
,
unsigned
int
cmd
,
unsigned
long
__arg
)
{
...
...
@@ -298,6 +494,7 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
char
__user
*
arg
=
(
void
__user
*
)
__arg
;
struct
trt
*
trts
=
NULL
;
struct
art
*
arts
=
NULL
;
struct
psvt
*
psvts
;
switch
(
cmd
)
{
case
ACPI_THERMAL_GET_TRT_COUNT
:
...
...
@@ -336,6 +533,27 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
case
ACPI_THERMAL_GET_ART
:
return
fill_art
(
arg
);
case
ACPI_THERMAL_GET_PSVT_COUNT
:
ret
=
acpi_parse_psvt
(
acpi_thermal_rel_handle
,
&
count
,
&
psvts
);
if
(
!
ret
)
{
kfree
(
psvts
);
return
put_user
(
count
,
(
unsigned
long
__user
*
)
__arg
);
}
return
ret
;
case
ACPI_THERMAL_GET_PSVT_LEN
:
/* total length of the data retrieved (count * PSVT entry size) */
ret
=
acpi_parse_psvt
(
acpi_thermal_rel_handle
,
&
count
,
&
psvts
);
length
=
count
*
sizeof
(
union
psvt_object
);
if
(
!
ret
)
{
kfree
(
psvts
);
return
put_user
(
length
,
(
unsigned
long
__user
*
)
__arg
);
}
return
ret
;
case
ACPI_THERMAL_GET_PSVT
:
return
fill_psvt
(
arg
);
default:
return
-
ENOTTY
;
}
...
...
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h
View file @
f46117bf
...
...
@@ -14,6 +14,16 @@
#define ACPI_THERMAL_GET_TRT _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long)
#define ACPI_THERMAL_GET_ART _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long)
/*
* ACPI_THERMAL_GET_PSVT_COUNT = Number of PSVT entries
* ACPI_THERMAL_GET_PSVT_LEN = Total return data size (PSVT count x each
* PSVT entry size)
* ACPI_THERMAL_GET_PSVT = Get the data as an array of psvt_objects
*/
#define ACPI_THERMAL_GET_PSVT_LEN _IOR(ACPI_THERMAL_MAGIC, 7, unsigned long)
#define ACPI_THERMAL_GET_PSVT_COUNT _IOR(ACPI_THERMAL_MAGIC, 8, unsigned long)
#define ACPI_THERMAL_GET_PSVT _IOR(ACPI_THERMAL_MAGIC, 9, unsigned long)
struct
art
{
acpi_handle
source
;
acpi_handle
target
;
...
...
@@ -43,6 +53,32 @@ struct trt {
u64
reserved4
;
}
__packed
;
#define ACPI_NR_PSVT_ELEMENTS 12
#define ACPI_PSVT_CONTROL_KNOB 7
#define ACPI_LIMIT_STR_MAX_LEN 8
struct
psvt
{
acpi_handle
source
;
acpi_handle
target
;
u64
priority
;
u64
sample_period
;
u64
passive_temp
;
u64
source_domain
;
u64
control_knob
;
union
{
/* For limit_type = ACPI_TYPE_INTEGER */
u64
integer
;
/* For limit_type = ACPI_TYPE_STRING */
char
string
[
ACPI_LIMIT_STR_MAX_LEN
];
char
*
str_ptr
;
}
limit
;
u64
step_size
;
u64
limit_coeff
;
u64
unlimit_coeff
;
/* Spec calls this field reserved, so we borrow it for type info */
u64
control_knob_type
;
/* ACPI_TYPE_STRING or ACPI_TYPE_INTEGER */
}
__packed
;
#define ACPI_NR_ART_ELEMENTS 13
/* for usrspace */
union
art_object
{
...
...
@@ -77,6 +113,27 @@ union trt_object {
u64
__data
[
8
];
};
union
psvt_object
{
struct
{
char
source_device
[
8
];
char
target_device
[
8
];
u64
priority
;
u64
sample_period
;
u64
passive_temp
;
u64
source_domain
;
u64
control_knob
;
union
{
u64
integer
;
char
string
[
ACPI_LIMIT_STR_MAX_LEN
];
}
limit
;
u64
step_size
;
u64
limit_coeff
;
u64
unlimit_coeff
;
u64
control_knob_type
;
};
u64
__data
[
ACPI_NR_PSVT_ELEMENTS
];
};
#ifdef __KERNEL__
int
acpi_thermal_rel_misc_device_add
(
acpi_handle
handle
);
int
acpi_thermal_rel_misc_device_remove
(
acpi_handle
handle
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment