The RTAS call ibm,get-dynamic-sensor-state is used to get the
sensor state identified by the location code and the sensor
token. The librtas library provides an API
rtas_get_dynamic_sensor() which uses /dev/mem access for work
area allocation but is restricted under system lockdown.

This patch provides an interface with new ioctl
 PAPR_DYNAMIC_SENSOR_IOC_GET to the papr-indices character
driver which executes this HCALL and copies the sensor state
in the user specified ioctl buffer.

Refer PAPR 7.3.19 ibm,get-dynamic-sensor-state for more
information on this RTAS call.
- User input parameters to the RTAS call: location code string
  and the sensor token

Expose these interfaces to user space with a /dev/papr-indices
character device using the following programming model:
 int fd = open("/dev/papr-indices", O_RDWR);
 int ret = ioctl(fd, PAPR_DYNAMIC_SENSOR_IOC_GET,
                struct papr_indices_io_block)
  - The user space specifies input parameters in
    papr_indices_io_block struct
  - Returned state for the specified sensor is copied to
    papr_indices_io_block.dynamic_param.state

Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
---
 arch/powerpc/include/asm/rtas.h               |  1 +
 arch/powerpc/kernel/rtas.c                    |  2 +-
 arch/powerpc/platforms/pseries/papr-indices.c | 67 +++++++++++++++++++
 3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 2da52f59e4c6..fcd822f0e1d7 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -517,6 +517,7 @@ extern unsigned long rtas_rmo_buf;
 extern struct mutex rtas_ibm_get_vpd_lock;
 extern struct mutex rtas_ibm_get_indices_lock;
 extern struct mutex rtas_ibm_set_dynamic_indicator_lock;
+extern struct mutex rtas_ibm_get_dynamic_sensor_state_lock;
 
 #define GLOBAL_INTERRUPT_QUEUE 9005
 
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 88fa416730af..a4848e7f248e 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -92,12 +92,12 @@ struct rtas_function {
  * Per-function locks for sequence-based RTAS functions.
  */
 static DEFINE_MUTEX(rtas_ibm_activate_firmware_lock);
-static DEFINE_MUTEX(rtas_ibm_get_dynamic_sensor_state_lock);
 static DEFINE_MUTEX(rtas_ibm_lpar_perftools_lock);
 static DEFINE_MUTEX(rtas_ibm_physical_attestation_lock);
 DEFINE_MUTEX(rtas_ibm_get_vpd_lock);
 DEFINE_MUTEX(rtas_ibm_get_indices_lock);
 DEFINE_MUTEX(rtas_ibm_set_dynamic_indicator_lock);
+DEFINE_MUTEX(rtas_ibm_get_dynamic_sensor_state_lock);
 
 static struct rtas_function rtas_function_table[] __ro_after_init = {
        [RTAS_FNIDX__CHECK_EXCEPTION] = {
diff --git a/arch/powerpc/platforms/pseries/papr-indices.c 
b/arch/powerpc/platforms/pseries/papr-indices.c
index e4b4eb8ece84..ca6ff2529017 100644
--- a/arch/powerpc/platforms/pseries/papr-indices.c
+++ b/arch/powerpc/platforms/pseries/papr-indices.c
@@ -441,6 +441,67 @@ static long papr_dynamic_indicator_ioc_set(struct 
papr_indices_io_block __user *
        return ret;
 }
 
+/**
+ * papr_dynamic_sensor_ioc_get - ibm,get-dynamic-sensor-state RTAS Call
+ * PAPR 2.13 7.3.19
+ *
+ * @ubuf: Input parameters to RTAS call such as sensor token
+ *        Copies the state in user space buffer.
+ *
+ *
+ * Returns success or -errno.
+ */
+
+static long papr_dynamic_sensor_ioc_get(struct papr_indices_io_block __user 
*ubuf)
+{
+       struct papr_indices_io_block kbuf;
+       struct rtas_work_area *work_area;
+       s32 fwrc, token, ret;
+       u32 rets;
+
+       token = rtas_function_token(RTAS_FN_IBM_GET_DYNAMIC_SENSOR_STATE);
+       if (token == RTAS_UNKNOWN_SERVICE)
+               return -ENOENT;
+
+       mutex_lock(&rtas_ibm_get_dynamic_sensor_state_lock);
+       work_area = papr_dynamic_indice_buf_from_user(ubuf, &kbuf);
+       if (IS_ERR(work_area)) {
+               ret = PTR_ERR(work_area);
+               goto out;
+       }
+
+       do {
+               fwrc = rtas_call(token, 2, 2, &rets,
+                               kbuf.dynamic_param.token,
+                               rtas_work_area_phys(work_area));
+       } while (rtas_busy_delay(fwrc));
+
+       rtas_work_area_free(work_area);
+
+       switch (fwrc) {
+       case RTAS_IBM_DYNAMIC_INDICE_SUCCESS:
+               if (put_user(rets, &ubuf->dynamic_param.state))
+                       ret = -EFAULT;
+               else
+                       ret = 0;
+               break;
+       case RTAS_IBM_DYNAMIC_INDICE_NO_INDICATOR:      /* No such indicator */
+               ret = -EOPNOTSUPP;
+               break;
+       default:
+               pr_err("unexpected ibm,get-dynamic-sensor result %d\n",
+                               fwrc);
+               fallthrough;
+       case RTAS_IBM_DYNAMIC_INDICE_HW_ERROR:  /* Hardware/platform error */
+               ret = -EIO;
+               break;
+       }
+
+out:
+       mutex_unlock(&rtas_ibm_get_dynamic_sensor_state_lock);
+       return ret;
+}
+
 /*
  * Top-level ioctl handler for /dev/papr-indices.
  */
@@ -454,6 +515,9 @@ static long papr_indices_dev_ioctl(struct file *filp, 
unsigned int ioctl,
        case PAPR_INDICES_IOC_GET:
                ret = papr_indices_create_handle(argp);
                break;
+       case PAPR_DYNAMIC_SENSOR_IOC_GET:
+               ret = papr_dynamic_sensor_ioc_get(argp);
+               break;
        case PAPR_DYNAMIC_INDICATOR_IOC_SET:
                if (filp->f_mode & FMODE_WRITE)
                        ret = papr_dynamic_indicator_ioc_set(argp);
@@ -486,6 +550,9 @@ static __init int papr_indices_init(void)
        if (!rtas_function_implemented(RTAS_FN_IBM_SET_DYNAMIC_INDICATOR))
                return -ENODEV;
 
+       if (!rtas_function_implemented(RTAS_FN_IBM_GET_DYNAMIC_SENSOR_STATE))
+               return -ENODEV;
+
        return misc_register(&papr_indices_dev);
 }
 machine_device_initcall(pseries, papr_indices_init);
-- 
2.43.5


Reply via email to