forked from pool/librtas
161 lines
4.7 KiB
Diff
161 lines
4.7 KiB
Diff
|
From ba73b7e26a517396bc0b053e1e3dab658cbde890 Mon Sep 17 00:00:00 2001
|
||
|
From: Haren Myneni <haren@linux.ibm.com>
|
||
|
Date: Sun, 9 Mar 2025 16:29:12 -0700
|
||
|
Subject: [PATCH 6/9] librtas: Use /dev/papr-indices when available for
|
||
|
get-dynamic-sensor-state
|
||
|
|
||
|
The current rtas_get_dynamic_sensor() allocates RTAS work area
|
||
|
and invokes sys_rtas() in the user space. But this interface will
|
||
|
not work under system lockdown due to restricted access to /dev/mem.
|
||
|
|
||
|
This patch add changes to use new kernel interface provided by
|
||
|
/dev/papr-indices entry with PAPR_DYNAMIC_SENSOR_IOC_GET ioctl.
|
||
|
The new state of sensor token will be returned from the user
|
||
|
passed papr_indices_io_block to the ioctl.
|
||
|
|
||
|
If /dev/papr-indices entry is available, the new kernel interface
|
||
|
is used with the following programming model:
|
||
|
|
||
|
fd = open("/dev/papr-indices", O_RDWR);
|
||
|
copy location-code to
|
||
|
papr_indices_io_block.dynamic_param.location_code_str
|
||
|
papr_indices_io_block.dynamic_param.token = token-val;
|
||
|
ret = ioctl(fd, PAPR_DYNAMIC_SENSOR_IOC_GET,
|
||
|
papr_indices_io_block);
|
||
|
state = papr_indices_io_block.dynamic_param.state
|
||
|
|
||
|
Signed-off-by: Haren Myneni <haren@linux.ibm.com>
|
||
|
---
|
||
|
librtas_src/indices.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
|
||
|
1 file changed, 89 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/librtas_src/indices.c b/librtas_src/indices.c
|
||
|
index 67744c9..27d537c 100644
|
||
|
--- a/librtas_src/indices.c
|
||
|
+++ b/librtas_src/indices.c
|
||
|
@@ -34,7 +34,7 @@ static const char indices_devpath[] = "/dev/papr-indices";
|
||
|
* @param state reference to state variable
|
||
|
* @return 0 on success, !0 otherwise
|
||
|
*/
|
||
|
-int rtas_get_dynamic_sensor(int sensor, void *loc_code, int *state)
|
||
|
+int get_dynamic_sensor_fallback(int sensor, void *loc_code, int *state)
|
||
|
{
|
||
|
uint32_t loc_pa = 0;
|
||
|
void *locbuf;
|
||
|
@@ -217,6 +217,85 @@ static int get_indices_chardev(int is_sensor, int type, char *workarea,
|
||
|
return rtas_status;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Only to be used when converting an actual error from a syscall.
|
||
|
+ */
|
||
|
+static int chardev_backconvert_errno(int saved_errno)
|
||
|
+{
|
||
|
+ const struct {
|
||
|
+ int linux_errno;
|
||
|
+ int rtas_status;
|
||
|
+ } map[] = {
|
||
|
+#define errno_to_status(e, s) { .linux_errno = (e), .rtas_status = (s), }
|
||
|
+ errno_to_status(EINVAL, -9999),
|
||
|
+ errno_to_status(EPERM, -9002),
|
||
|
+ errno_to_status(EOPNOTSUPP, -3),
|
||
|
+ errno_to_status(EIO, -1),
|
||
|
+ errno_to_status(EFAULT, -1),
|
||
|
+#undef errno_to_status
|
||
|
+ };
|
||
|
+
|
||
|
+ for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); ++i)
|
||
|
+ if (map[i].linux_errno == saved_errno)
|
||
|
+ return map[i].rtas_status;
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+static int dynamic_common_io_setup(unsigned long ioctalval,
|
||
|
+ void *loc_code,
|
||
|
+ struct papr_indices_io_block *buf)
|
||
|
+{
|
||
|
+ size_t length;
|
||
|
+ char *loc_str;
|
||
|
+ int fd, ret = -EINVAL;
|
||
|
+
|
||
|
+ fd = open(indices_devpath, O_RDWR);
|
||
|
+ if (fd < 0) {
|
||
|
+ /*
|
||
|
+ * Should not be here. May be /dev/papr-indices removed
|
||
|
+ */
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
+ length = be32toh(*(uint32_t *)loc_code);
|
||
|
+
|
||
|
+ if (length < 1) {
|
||
|
+ dbg("Invalid length(%lu) of location code string\n", length);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ loc_str = (char *)((char *)loc_code + sizeof(uint32_t));
|
||
|
+ if (strlen(loc_str) != (length - 1)) {
|
||
|
+ dbg("location code string length is not matched with the passed length(%lu)\n", length);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ memcpy(&buf->dynamic_param.location_code_str, loc_str, length);
|
||
|
+
|
||
|
+ ret = ioctl(fd, ioctalval, buf);
|
||
|
+ if (ret != 0)
|
||
|
+ ret = chardev_backconvert_errno(errno);
|
||
|
+out:
|
||
|
+ close(fd);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int get_dynamic_sensor_chardev(int sensor, void *loc_code, int *state)
|
||
|
+{
|
||
|
+ struct papr_indices_io_block buf = {};
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ buf.dynamic_param.token = sensor;
|
||
|
+ ret = dynamic_common_io_setup(PAPR_DYNAMIC_SENSOR_IOC_GET,
|
||
|
+ loc_code, &buf);
|
||
|
+ if (ret != 0)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ *state = buf.dynamic_param.state;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
static bool indices_can_use_chardev(void)
|
||
|
{
|
||
|
struct stat statbuf;
|
||
|
@@ -235,6 +314,7 @@ static bool indices_can_use_chardev(void)
|
||
|
|
||
|
static int (*get_indices_fn)(int is_sensor, int type, char *workarea,
|
||
|
size_t size, int start, int *next);
|
||
|
+static int (*get_dynamic_sensor_fn)(int sensor, void *loc_code, int *state);
|
||
|
|
||
|
static void indices_fn_setup(void)
|
||
|
{
|
||
|
@@ -242,6 +322,8 @@ static void indices_fn_setup(void)
|
||
|
|
||
|
get_indices_fn = use_chardev ?
|
||
|
get_indices_chardev : get_indices_fallback;
|
||
|
+ get_dynamic_sensor_fn = use_chardev ?
|
||
|
+ get_dynamic_sensor_chardev : get_dynamic_sensor_fallback;
|
||
|
}
|
||
|
|
||
|
static pthread_once_t indices_fn_setup_once = PTHREAD_ONCE_INIT;
|
||
|
@@ -253,3 +335,9 @@ int rtas_get_indices(int is_sensor, int type, char *workarea, size_t size,
|
||
|
return get_indices_fn(is_sensor, type, workarea, size,
|
||
|
start, next);
|
||
|
}
|
||
|
+
|
||
|
+int rtas_get_dynamic_sensor(int sensor, void *loc_code, int *state)
|
||
|
+{
|
||
|
+ pthread_once(&indices_fn_setup_once, indices_fn_setup);
|
||
|
+ return get_dynamic_sensor_fn(sensor, loc_code, state);
|
||
|
+}
|
||
|
--
|
||
|
2.47.1
|
||
|
|