root/arch/powerpc/platforms/powernv/opal-psr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. psr_show
  2. psr_store
  3. opal_psr_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * PowerNV OPAL Power-Shift-Ratio interface
   4  *
   5  * Copyright 2017 IBM Corp.
   6  */
   7 
   8 #define pr_fmt(fmt)     "opal-psr: " fmt
   9 
  10 #include <linux/of.h>
  11 #include <linux/kobject.h>
  12 #include <linux/slab.h>
  13 
  14 #include <asm/opal.h>
  15 
  16 DEFINE_MUTEX(psr_mutex);
  17 
  18 static struct kobject *psr_kobj;
  19 
  20 struct psr_attr {
  21         u32 handle;
  22         struct kobj_attribute attr;
  23 } *psr_attrs;
  24 
  25 static ssize_t psr_show(struct kobject *kobj, struct kobj_attribute *attr,
  26                         char *buf)
  27 {
  28         struct psr_attr *psr_attr = container_of(attr, struct psr_attr, attr);
  29         struct opal_msg msg;
  30         int psr, ret, token;
  31 
  32         token = opal_async_get_token_interruptible();
  33         if (token < 0) {
  34                 pr_devel("Failed to get token\n");
  35                 return token;
  36         }
  37 
  38         ret = mutex_lock_interruptible(&psr_mutex);
  39         if (ret)
  40                 goto out_token;
  41 
  42         ret = opal_get_power_shift_ratio(psr_attr->handle, token,
  43                                             (u32 *)__pa(&psr));
  44         switch (ret) {
  45         case OPAL_ASYNC_COMPLETION:
  46                 ret = opal_async_wait_response(token, &msg);
  47                 if (ret) {
  48                         pr_devel("Failed to wait for the async response\n");
  49                         ret = -EIO;
  50                         goto out;
  51                 }
  52                 ret = opal_error_code(opal_get_async_rc(msg));
  53                 if (!ret) {
  54                         ret = sprintf(buf, "%u\n", be32_to_cpu(psr));
  55                         if (ret < 0)
  56                                 ret = -EIO;
  57                 }
  58                 break;
  59         case OPAL_SUCCESS:
  60                 ret = sprintf(buf, "%u\n", be32_to_cpu(psr));
  61                 if (ret < 0)
  62                         ret = -EIO;
  63                 break;
  64         default:
  65                 ret = opal_error_code(ret);
  66         }
  67 
  68 out:
  69         mutex_unlock(&psr_mutex);
  70 out_token:
  71         opal_async_release_token(token);
  72         return ret;
  73 }
  74 
  75 static ssize_t psr_store(struct kobject *kobj, struct kobj_attribute *attr,
  76                          const char *buf, size_t count)
  77 {
  78         struct psr_attr *psr_attr = container_of(attr, struct psr_attr, attr);
  79         struct opal_msg msg;
  80         int psr, ret, token;
  81 
  82         ret = kstrtoint(buf, 0, &psr);
  83         if (ret)
  84                 return ret;
  85 
  86         token = opal_async_get_token_interruptible();
  87         if (token < 0) {
  88                 pr_devel("Failed to get token\n");
  89                 return token;
  90         }
  91 
  92         ret = mutex_lock_interruptible(&psr_mutex);
  93         if (ret)
  94                 goto out_token;
  95 
  96         ret = opal_set_power_shift_ratio(psr_attr->handle, token, psr);
  97         switch (ret) {
  98         case OPAL_ASYNC_COMPLETION:
  99                 ret = opal_async_wait_response(token, &msg);
 100                 if (ret) {
 101                         pr_devel("Failed to wait for the async response\n");
 102                         ret = -EIO;
 103                         goto out;
 104                 }
 105                 ret = opal_error_code(opal_get_async_rc(msg));
 106                 if (!ret)
 107                         ret = count;
 108                 break;
 109         case OPAL_SUCCESS:
 110                 ret = count;
 111                 break;
 112         default:
 113                 ret = opal_error_code(ret);
 114         }
 115 
 116 out:
 117         mutex_unlock(&psr_mutex);
 118 out_token:
 119         opal_async_release_token(token);
 120         return ret;
 121 }
 122 
 123 void __init opal_psr_init(void)
 124 {
 125         struct device_node *psr, *node;
 126         int i = 0;
 127 
 128         psr = of_find_compatible_node(NULL, NULL,
 129                                       "ibm,opal-power-shift-ratio");
 130         if (!psr) {
 131                 pr_devel("Power-shift-ratio node not found\n");
 132                 return;
 133         }
 134 
 135         psr_attrs = kcalloc(of_get_child_count(psr), sizeof(*psr_attrs),
 136                             GFP_KERNEL);
 137         if (!psr_attrs)
 138                 return;
 139 
 140         psr_kobj = kobject_create_and_add("psr", opal_kobj);
 141         if (!psr_kobj) {
 142                 pr_warn("Failed to create psr kobject\n");
 143                 goto out;
 144         }
 145 
 146         for_each_child_of_node(psr, node) {
 147                 if (of_property_read_u32(node, "handle",
 148                                          &psr_attrs[i].handle))
 149                         goto out_kobj;
 150 
 151                 sysfs_attr_init(&psr_attrs[i].attr.attr);
 152                 if (of_property_read_string(node, "label",
 153                                             &psr_attrs[i].attr.attr.name))
 154                         goto out_kobj;
 155                 psr_attrs[i].attr.attr.mode = 0664;
 156                 psr_attrs[i].attr.show = psr_show;
 157                 psr_attrs[i].attr.store = psr_store;
 158                 if (sysfs_create_file(psr_kobj, &psr_attrs[i].attr.attr)) {
 159                         pr_devel("Failed to create psr sysfs file %s\n",
 160                                  psr_attrs[i].attr.attr.name);
 161                         goto out_kobj;
 162                 }
 163                 i++;
 164         }
 165 
 166         return;
 167 out_kobj:
 168         kobject_put(psr_kobj);
 169 out:
 170         kfree(psr_attrs);
 171 }

/* [<][>][^][v][top][bottom][index][help] */