0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "opal-sensor-groups: " fmt
0009
0010 #include <linux/of.h>
0011 #include <linux/kobject.h>
0012 #include <linux/slab.h>
0013
0014 #include <asm/opal.h>
0015
0016 static DEFINE_MUTEX(sg_mutex);
0017
0018 static struct kobject *sg_kobj;
0019
0020 struct sg_attr {
0021 u32 handle;
0022 struct kobj_attribute attr;
0023 };
0024
0025 static struct sensor_group {
0026 char name[20];
0027 struct attribute_group sg;
0028 struct sg_attr *sgattrs;
0029 } *sgs;
0030
0031 int sensor_group_enable(u32 handle, bool enable)
0032 {
0033 struct opal_msg msg;
0034 int token, ret;
0035
0036 token = opal_async_get_token_interruptible();
0037 if (token < 0)
0038 return token;
0039
0040 ret = opal_sensor_group_enable(handle, token, enable);
0041 if (ret == OPAL_ASYNC_COMPLETION) {
0042 ret = opal_async_wait_response(token, &msg);
0043 if (ret) {
0044 pr_devel("Failed to wait for the async response\n");
0045 ret = -EIO;
0046 goto out;
0047 }
0048 ret = opal_error_code(opal_get_async_rc(msg));
0049 } else {
0050 ret = opal_error_code(ret);
0051 }
0052
0053 out:
0054 opal_async_release_token(token);
0055 return ret;
0056 }
0057 EXPORT_SYMBOL_GPL(sensor_group_enable);
0058
0059 static ssize_t sg_store(struct kobject *kobj, struct kobj_attribute *attr,
0060 const char *buf, size_t count)
0061 {
0062 struct sg_attr *sattr = container_of(attr, struct sg_attr, attr);
0063 struct opal_msg msg;
0064 u32 data;
0065 int ret, token;
0066
0067 ret = kstrtoint(buf, 0, &data);
0068 if (ret)
0069 return ret;
0070
0071 if (data != 1)
0072 return -EINVAL;
0073
0074 token = opal_async_get_token_interruptible();
0075 if (token < 0) {
0076 pr_devel("Failed to get token\n");
0077 return token;
0078 }
0079
0080 ret = mutex_lock_interruptible(&sg_mutex);
0081 if (ret)
0082 goto out_token;
0083
0084 ret = opal_sensor_group_clear(sattr->handle, token);
0085 switch (ret) {
0086 case OPAL_ASYNC_COMPLETION:
0087 ret = opal_async_wait_response(token, &msg);
0088 if (ret) {
0089 pr_devel("Failed to wait for the async response\n");
0090 ret = -EIO;
0091 goto out;
0092 }
0093 ret = opal_error_code(opal_get_async_rc(msg));
0094 if (!ret)
0095 ret = count;
0096 break;
0097 case OPAL_SUCCESS:
0098 ret = count;
0099 break;
0100 default:
0101 ret = opal_error_code(ret);
0102 }
0103
0104 out:
0105 mutex_unlock(&sg_mutex);
0106 out_token:
0107 opal_async_release_token(token);
0108 return ret;
0109 }
0110
0111 static struct sg_ops_info {
0112 int opal_no;
0113 const char *attr_name;
0114 ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
0115 const char *buf, size_t count);
0116 } ops_info[] = {
0117 { OPAL_SENSOR_GROUP_CLEAR, "clear", sg_store },
0118 };
0119
0120 static void add_attr(int handle, struct sg_attr *attr, int index)
0121 {
0122 attr->handle = handle;
0123 sysfs_attr_init(&attr->attr.attr);
0124 attr->attr.attr.name = ops_info[index].attr_name;
0125 attr->attr.attr.mode = 0220;
0126 attr->attr.store = ops_info[index].store;
0127 }
0128
0129 static int __init add_attr_group(const __be32 *ops, int len, struct sensor_group *sg,
0130 u32 handle)
0131 {
0132 int i, j;
0133 int count = 0;
0134
0135 for (i = 0; i < len; i++)
0136 for (j = 0; j < ARRAY_SIZE(ops_info); j++)
0137 if (be32_to_cpu(ops[i]) == ops_info[j].opal_no) {
0138 add_attr(handle, &sg->sgattrs[count], j);
0139 sg->sg.attrs[count] =
0140 &sg->sgattrs[count].attr.attr;
0141 count++;
0142 }
0143
0144 return sysfs_create_group(sg_kobj, &sg->sg);
0145 }
0146
0147 static int __init get_nr_attrs(const __be32 *ops, int len)
0148 {
0149 int i, j;
0150 int nr_attrs = 0;
0151
0152 for (i = 0; i < len; i++)
0153 for (j = 0; j < ARRAY_SIZE(ops_info); j++)
0154 if (be32_to_cpu(ops[i]) == ops_info[j].opal_no)
0155 nr_attrs++;
0156
0157 return nr_attrs;
0158 }
0159
0160 void __init opal_sensor_groups_init(void)
0161 {
0162 struct device_node *sg, *node;
0163 int i = 0;
0164
0165 sg = of_find_compatible_node(NULL, NULL, "ibm,opal-sensor-group");
0166 if (!sg) {
0167 pr_devel("Sensor groups node not found\n");
0168 return;
0169 }
0170
0171 sgs = kcalloc(of_get_child_count(sg), sizeof(*sgs), GFP_KERNEL);
0172 if (!sgs)
0173 return;
0174
0175 sg_kobj = kobject_create_and_add("sensor_groups", opal_kobj);
0176 if (!sg_kobj) {
0177 pr_warn("Failed to create sensor group kobject\n");
0178 goto out_sgs;
0179 }
0180
0181 for_each_child_of_node(sg, node) {
0182 const __be32 *ops;
0183 u32 sgid, len, nr_attrs, chipid;
0184
0185 ops = of_get_property(node, "ops", &len);
0186 if (!ops)
0187 continue;
0188
0189 nr_attrs = get_nr_attrs(ops, len);
0190 if (!nr_attrs)
0191 continue;
0192
0193 sgs[i].sgattrs = kcalloc(nr_attrs, sizeof(*sgs[i].sgattrs),
0194 GFP_KERNEL);
0195 if (!sgs[i].sgattrs)
0196 goto out_sgs_sgattrs;
0197
0198 sgs[i].sg.attrs = kcalloc(nr_attrs + 1,
0199 sizeof(*sgs[i].sg.attrs),
0200 GFP_KERNEL);
0201
0202 if (!sgs[i].sg.attrs) {
0203 kfree(sgs[i].sgattrs);
0204 goto out_sgs_sgattrs;
0205 }
0206
0207 if (of_property_read_u32(node, "sensor-group-id", &sgid)) {
0208 pr_warn("sensor-group-id property not found\n");
0209 goto out_sgs_sgattrs;
0210 }
0211
0212 if (!of_property_read_u32(node, "ibm,chip-id", &chipid))
0213 sprintf(sgs[i].name, "%pOFn%d", node, chipid);
0214 else
0215 sprintf(sgs[i].name, "%pOFn", node);
0216
0217 sgs[i].sg.name = sgs[i].name;
0218 if (add_attr_group(ops, len, &sgs[i], sgid)) {
0219 pr_warn("Failed to create sensor attribute group %s\n",
0220 sgs[i].sg.name);
0221 goto out_sgs_sgattrs;
0222 }
0223 i++;
0224 }
0225
0226 return;
0227
0228 out_sgs_sgattrs:
0229 while (--i >= 0) {
0230 kfree(sgs[i].sgattrs);
0231 kfree(sgs[i].sg.attrs);
0232 }
0233 kobject_put(sg_kobj);
0234 out_sgs:
0235 kfree(sgs);
0236 }