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

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

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ 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.81 ] ~ [ 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-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ 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 OPAL Sensor-groups interface
  3  *
  4  * Copyright 2017 IBM Corp.
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public License
  8  * as published by the Free Software Foundation; either version
  9  * 2 of the License, or (at your option) any later version.
 10  */
 11 
 12 #define pr_fmt(fmt)     "opal-sensor-groups: " fmt
 13 
 14 #include <linux/of.h>
 15 #include <linux/kobject.h>
 16 #include <linux/slab.h>
 17 
 18 #include <asm/opal.h>
 19 
 20 DEFINE_MUTEX(sg_mutex);
 21 
 22 static struct kobject *sg_kobj;
 23 
 24 struct sg_attr {
 25         u32 handle;
 26         struct kobj_attribute attr;
 27 };
 28 
 29 static struct sensor_group {
 30         char name[20];
 31         struct attribute_group sg;
 32         struct sg_attr *sgattrs;
 33 } *sgs;
 34 
 35 int sensor_group_enable(u32 handle, bool enable)
 36 {
 37         struct opal_msg msg;
 38         int token, ret;
 39 
 40         token = opal_async_get_token_interruptible();
 41         if (token < 0)
 42                 return token;
 43 
 44         ret = opal_sensor_group_enable(handle, token, enable);
 45         if (ret == 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         } else {
 54                 ret = opal_error_code(ret);
 55         }
 56 
 57 out:
 58         opal_async_release_token(token);
 59         return ret;
 60 }
 61 EXPORT_SYMBOL_GPL(sensor_group_enable);
 62 
 63 static ssize_t sg_store(struct kobject *kobj, struct kobj_attribute *attr,
 64                         const char *buf, size_t count)
 65 {
 66         struct sg_attr *sattr = container_of(attr, struct sg_attr, attr);
 67         struct opal_msg msg;
 68         u32 data;
 69         int ret, token;
 70 
 71         ret = kstrtoint(buf, 0, &data);
 72         if (ret)
 73                 return ret;
 74 
 75         if (data != 1)
 76                 return -EINVAL;
 77 
 78         token = opal_async_get_token_interruptible();
 79         if (token < 0) {
 80                 pr_devel("Failed to get token\n");
 81                 return token;
 82         }
 83 
 84         ret = mutex_lock_interruptible(&sg_mutex);
 85         if (ret)
 86                 goto out_token;
 87 
 88         ret = opal_sensor_group_clear(sattr->handle, token);
 89         switch (ret) {
 90         case OPAL_ASYNC_COMPLETION:
 91                 ret = opal_async_wait_response(token, &msg);
 92                 if (ret) {
 93                         pr_devel("Failed to wait for the async response\n");
 94                         ret = -EIO;
 95                         goto out;
 96                 }
 97                 ret = opal_error_code(opal_get_async_rc(msg));
 98                 if (!ret)
 99                         ret = count;
100                 break;
101         case OPAL_SUCCESS:
102                 ret = count;
103                 break;
104         default:
105                 ret = opal_error_code(ret);
106         }
107 
108 out:
109         mutex_unlock(&sg_mutex);
110 out_token:
111         opal_async_release_token(token);
112         return ret;
113 }
114 
115 static struct sg_ops_info {
116         int opal_no;
117         const char *attr_name;
118         ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
119                         const char *buf, size_t count);
120 } ops_info[] = {
121         { OPAL_SENSOR_GROUP_CLEAR, "clear", sg_store },
122 };
123 
124 static void add_attr(int handle, struct sg_attr *attr, int index)
125 {
126         attr->handle = handle;
127         sysfs_attr_init(&attr->attr.attr);
128         attr->attr.attr.name = ops_info[index].attr_name;
129         attr->attr.attr.mode = 0220;
130         attr->attr.store = ops_info[index].store;
131 }
132 
133 static int add_attr_group(const __be32 *ops, int len, struct sensor_group *sg,
134                            u32 handle)
135 {
136         int i, j;
137         int count = 0;
138 
139         for (i = 0; i < len; i++)
140                 for (j = 0; j < ARRAY_SIZE(ops_info); j++)
141                         if (be32_to_cpu(ops[i]) == ops_info[j].opal_no) {
142                                 add_attr(handle, &sg->sgattrs[count], j);
143                                 sg->sg.attrs[count] =
144                                         &sg->sgattrs[count].attr.attr;
145                                 count++;
146                         }
147 
148         return sysfs_create_group(sg_kobj, &sg->sg);
149 }
150 
151 static int get_nr_attrs(const __be32 *ops, int len)
152 {
153         int i, j;
154         int nr_attrs = 0;
155 
156         for (i = 0; i < len; i++)
157                 for (j = 0; j < ARRAY_SIZE(ops_info); j++)
158                         if (be32_to_cpu(ops[i]) == ops_info[j].opal_no)
159                                 nr_attrs++;
160 
161         return nr_attrs;
162 }
163 
164 void __init opal_sensor_groups_init(void)
165 {
166         struct device_node *sg, *node;
167         int i = 0;
168 
169         sg = of_find_compatible_node(NULL, NULL, "ibm,opal-sensor-group");
170         if (!sg) {
171                 pr_devel("Sensor groups node not found\n");
172                 return;
173         }
174 
175         sgs = kcalloc(of_get_child_count(sg), sizeof(*sgs), GFP_KERNEL);
176         if (!sgs)
177                 return;
178 
179         sg_kobj = kobject_create_and_add("sensor_groups", opal_kobj);
180         if (!sg_kobj) {
181                 pr_warn("Failed to create sensor group kobject\n");
182                 goto out_sgs;
183         }
184 
185         for_each_child_of_node(sg, node) {
186                 const __be32 *ops;
187                 u32 sgid, len, nr_attrs, chipid;
188 
189                 ops = of_get_property(node, "ops", &len);
190                 if (!ops)
191                         continue;
192 
193                 nr_attrs = get_nr_attrs(ops, len);
194                 if (!nr_attrs)
195                         continue;
196 
197                 sgs[i].sgattrs = kcalloc(nr_attrs, sizeof(*sgs[i].sgattrs),
198                                          GFP_KERNEL);
199                 if (!sgs[i].sgattrs)
200                         goto out_sgs_sgattrs;
201 
202                 sgs[i].sg.attrs = kcalloc(nr_attrs + 1,
203                                           sizeof(*sgs[i].sg.attrs),
204                                           GFP_KERNEL);
205 
206                 if (!sgs[i].sg.attrs) {
207                         kfree(sgs[i].sgattrs);
208                         goto out_sgs_sgattrs;
209                 }
210 
211                 if (of_property_read_u32(node, "sensor-group-id", &sgid)) {
212                         pr_warn("sensor-group-id property not found\n");
213                         goto out_sgs_sgattrs;
214                 }
215 
216                 if (!of_property_read_u32(node, "ibm,chip-id", &chipid))
217                         sprintf(sgs[i].name, "%pOFn%d", node, chipid);
218                 else
219                         sprintf(sgs[i].name, "%pOFn", node);
220 
221                 sgs[i].sg.name = sgs[i].name;
222                 if (add_attr_group(ops, len, &sgs[i], sgid)) {
223                         pr_warn("Failed to create sensor attribute group %s\n",
224                                 sgs[i].sg.name);
225                         goto out_sgs_sgattrs;
226                 }
227                 i++;
228         }
229 
230         return;
231 
232 out_sgs_sgattrs:
233         while (--i >= 0) {
234                 kfree(sgs[i].sgattrs);
235                 kfree(sgs[i].sg.attrs);
236         }
237         kobject_put(sg_kobj);
238 out_sgs:
239         kfree(sgs);
240 }
241 

~ [ 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