~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/platforms/powernv/opal-sysparam.c

Version: ~ [ linux-5.9-rc5 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * PowerNV system parameter code
  3  *
  4  * Copyright (C) 2013 IBM
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * This program is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program; if not, write to the Free Software
 18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  */
 20 
 21 #include <linux/kobject.h>
 22 #include <linux/mutex.h>
 23 #include <linux/slab.h>
 24 #include <linux/of.h>
 25 #include <linux/gfp.h>
 26 #include <linux/stat.h>
 27 #include <asm/opal.h>
 28 
 29 #define MAX_PARAM_DATA_LEN      64
 30 
 31 static DEFINE_MUTEX(opal_sysparam_mutex);
 32 static struct kobject *sysparam_kobj;
 33 static void *param_data_buf;
 34 
 35 struct param_attr {
 36         struct list_head list;
 37         u32 param_id;
 38         u32 param_size;
 39         struct kobj_attribute kobj_attr;
 40 };
 41 
 42 static ssize_t opal_get_sys_param(u32 param_id, u32 length, void *buffer)
 43 {
 44         struct opal_msg msg;
 45         ssize_t ret;
 46         int token;
 47 
 48         token = opal_async_get_token_interruptible();
 49         if (token < 0) {
 50                 if (token != -ERESTARTSYS)
 51                         pr_err("%s: Couldn't get the token, returning\n",
 52                                         __func__);
 53                 ret = token;
 54                 goto out;
 55         }
 56 
 57         ret = opal_get_param(token, param_id, (u64)buffer, length);
 58         if (ret != OPAL_ASYNC_COMPLETION) {
 59                 ret = opal_error_code(ret);
 60                 goto out_token;
 61         }
 62 
 63         ret = opal_async_wait_response(token, &msg);
 64         if (ret) {
 65                 pr_err("%s: Failed to wait for the async response, %zd\n",
 66                                 __func__, ret);
 67                 goto out_token;
 68         }
 69 
 70         ret = opal_error_code(opal_get_async_rc(msg));
 71 
 72 out_token:
 73         opal_async_release_token(token);
 74 out:
 75         return ret;
 76 }
 77 
 78 static int opal_set_sys_param(u32 param_id, u32 length, void *buffer)
 79 {
 80         struct opal_msg msg;
 81         int ret, token;
 82 
 83         token = opal_async_get_token_interruptible();
 84         if (token < 0) {
 85                 if (token != -ERESTARTSYS)
 86                         pr_err("%s: Couldn't get the token, returning\n",
 87                                         __func__);
 88                 ret = token;
 89                 goto out;
 90         }
 91 
 92         ret = opal_set_param(token, param_id, (u64)buffer, length);
 93 
 94         if (ret != OPAL_ASYNC_COMPLETION) {
 95                 ret = opal_error_code(ret);
 96                 goto out_token;
 97         }
 98 
 99         ret = opal_async_wait_response(token, &msg);
100         if (ret) {
101                 pr_err("%s: Failed to wait for the async response, %d\n",
102                                 __func__, ret);
103                 goto out_token;
104         }
105 
106         ret = opal_error_code(opal_get_async_rc(msg));
107 
108 out_token:
109         opal_async_release_token(token);
110 out:
111         return ret;
112 }
113 
114 static ssize_t sys_param_show(struct kobject *kobj,
115                 struct kobj_attribute *kobj_attr, char *buf)
116 {
117         struct param_attr *attr = container_of(kobj_attr, struct param_attr,
118                         kobj_attr);
119         ssize_t ret;
120 
121         mutex_lock(&opal_sysparam_mutex);
122         ret = opal_get_sys_param(attr->param_id, attr->param_size,
123                         param_data_buf);
124         if (ret)
125                 goto out;
126 
127         memcpy(buf, param_data_buf, attr->param_size);
128 
129         ret = attr->param_size;
130 out:
131         mutex_unlock(&opal_sysparam_mutex);
132         return ret;
133 }
134 
135 static ssize_t sys_param_store(struct kobject *kobj,
136                 struct kobj_attribute *kobj_attr, const char *buf, size_t count)
137 {
138         struct param_attr *attr = container_of(kobj_attr, struct param_attr,
139                         kobj_attr);
140         ssize_t ret;
141 
142         /* MAX_PARAM_DATA_LEN is sizeof(param_data_buf) */
143         if (count > MAX_PARAM_DATA_LEN)
144                 count = MAX_PARAM_DATA_LEN;
145 
146         mutex_lock(&opal_sysparam_mutex);
147         memcpy(param_data_buf, buf, count);
148         ret = opal_set_sys_param(attr->param_id, attr->param_size,
149                         param_data_buf);
150         mutex_unlock(&opal_sysparam_mutex);
151         if (!ret)
152                 ret = count;
153         return ret;
154 }
155 
156 void __init opal_sys_param_init(void)
157 {
158         struct device_node *sysparam;
159         struct param_attr *attr;
160         u32 *id, *size;
161         int count, i;
162         u8 *perm;
163 
164         if (!opal_kobj) {
165                 pr_warn("SYSPARAM: opal kobject is not available\n");
166                 goto out;
167         }
168 
169         /* Some systems do not use sysparams; this is not an error */
170         sysparam = of_find_node_by_path("/ibm,opal/sysparams");
171         if (!sysparam)
172                 goto out;
173 
174         if (!of_device_is_compatible(sysparam, "ibm,opal-sysparams")) {
175                 pr_err("SYSPARAM: Opal sysparam node not compatible\n");
176                 goto out_node_put;
177         }
178 
179         sysparam_kobj = kobject_create_and_add("sysparams", opal_kobj);
180         if (!sysparam_kobj) {
181                 pr_err("SYSPARAM: Failed to create sysparam kobject\n");
182                 goto out_node_put;
183         }
184 
185         /* Allocate big enough buffer for any get/set transactions */
186         param_data_buf = kzalloc(MAX_PARAM_DATA_LEN, GFP_KERNEL);
187         if (!param_data_buf) {
188                 pr_err("SYSPARAM: Failed to allocate memory for param data "
189                                 "buf\n");
190                 goto out_kobj_put;
191         }
192 
193         /* Number of parameters exposed through DT */
194         count = of_property_count_strings(sysparam, "param-name");
195         if (count < 0) {
196                 pr_err("SYSPARAM: No string found of property param-name in "
197                                 "the node %s\n", sysparam->name);
198                 goto out_param_buf;
199         }
200 
201         id = kzalloc(sizeof(*id) * count, GFP_KERNEL);
202         if (!id) {
203                 pr_err("SYSPARAM: Failed to allocate memory to read parameter "
204                                 "id\n");
205                 goto out_param_buf;
206         }
207 
208         size = kzalloc(sizeof(*size) * count, GFP_KERNEL);
209         if (!size) {
210                 pr_err("SYSPARAM: Failed to allocate memory to read parameter "
211                                 "size\n");
212                 goto out_free_id;
213         }
214 
215         perm = kzalloc(sizeof(*perm) * count, GFP_KERNEL);
216         if (!perm) {
217                 pr_err("SYSPARAM: Failed to allocate memory to read supported "
218                                 "action on the parameter");
219                 goto out_free_size;
220         }
221 
222         if (of_property_read_u32_array(sysparam, "param-id", id, count)) {
223                 pr_err("SYSPARAM: Missing property param-id in the DT\n");
224                 goto out_free_perm;
225         }
226 
227         if (of_property_read_u32_array(sysparam, "param-len", size, count)) {
228                 pr_err("SYSPARAM: Missing property param-len in the DT\n");
229                 goto out_free_perm;
230         }
231 
232 
233         if (of_property_read_u8_array(sysparam, "param-perm", perm, count)) {
234                 pr_err("SYSPARAM: Missing property param-perm in the DT\n");
235                 goto out_free_perm;
236         }
237 
238         attr = kzalloc(sizeof(*attr) * count, GFP_KERNEL);
239         if (!attr) {
240                 pr_err("SYSPARAM: Failed to allocate memory for parameter "
241                                 "attributes\n");
242                 goto out_free_perm;
243         }
244 
245         /* For each of the parameters, populate the parameter attributes */
246         for (i = 0; i < count; i++) {
247                 if (size[i] > MAX_PARAM_DATA_LEN) {
248                         pr_warn("SYSPARAM: Not creating parameter %d as size "
249                                 "exceeds buffer length\n", i);
250                         continue;
251                 }
252 
253                 sysfs_attr_init(&attr[i].kobj_attr.attr);
254                 attr[i].param_id = id[i];
255                 attr[i].param_size = size[i];
256                 if (of_property_read_string_index(sysparam, "param-name", i,
257                                 &attr[i].kobj_attr.attr.name))
258                         continue;
259 
260                 /* If the parameter is read-only or read-write */
261                 switch (perm[i] & 3) {
262                 case OPAL_SYSPARAM_READ:
263                         attr[i].kobj_attr.attr.mode = S_IRUGO;
264                         break;
265                 case OPAL_SYSPARAM_WRITE:
266                         attr[i].kobj_attr.attr.mode = S_IWUSR;
267                         break;
268                 case OPAL_SYSPARAM_RW:
269                         attr[i].kobj_attr.attr.mode = S_IRUGO | S_IWUSR;
270                         break;
271                 default:
272                         break;
273                 }
274 
275                 attr[i].kobj_attr.show = sys_param_show;
276                 attr[i].kobj_attr.store = sys_param_store;
277 
278                 if (sysfs_create_file(sysparam_kobj, &attr[i].kobj_attr.attr)) {
279                         pr_err("SYSPARAM: Failed to create sysfs file %s\n",
280                                         attr[i].kobj_attr.attr.name);
281                         goto out_free_attr;
282                 }
283         }
284 
285         kfree(perm);
286         kfree(size);
287         kfree(id);
288         of_node_put(sysparam);
289         return;
290 
291 out_free_attr:
292         kfree(attr);
293 out_free_perm:
294         kfree(perm);
295 out_free_size:
296         kfree(size);
297 out_free_id:
298         kfree(id);
299 out_param_buf:
300         kfree(param_data_buf);
301 out_kobj_put:
302         kobject_put(sysparam_kobj);
303 out_node_put:
304         of_node_put(sysparam);
305 out:
306         return;
307 }
308 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp