gsmi: fix null-deref in gsmi_get_variable
[platform/kernel/linux-starfive.git] / drivers / counter / counter-sysfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Generic Counter sysfs interface
4  * Copyright (C) 2020 William Breathitt Gray
5  */
6 #include <linux/counter.h>
7 #include <linux/device.h>
8 #include <linux/err.h>
9 #include <linux/gfp.h>
10 #include <linux/kernel.h>
11 #include <linux/kfifo.h>
12 #include <linux/kstrtox.h>
13 #include <linux/list.h>
14 #include <linux/mutex.h>
15 #include <linux/spinlock.h>
16 #include <linux/string.h>
17 #include <linux/sysfs.h>
18 #include <linux/types.h>
19
20 #include "counter-sysfs.h"
21
22 static inline struct counter_device *counter_from_dev(struct device *dev)
23 {
24         return container_of(dev, struct counter_device, dev);
25 }
26
27 /**
28  * struct counter_attribute - Counter sysfs attribute
29  * @dev_attr:   device attribute for sysfs
30  * @l:          node to add Counter attribute to attribute group list
31  * @comp:       Counter component callbacks and data
32  * @scope:      Counter scope of the attribute
33  * @parent:     pointer to the parent component
34  */
35 struct counter_attribute {
36         struct device_attribute dev_attr;
37         struct list_head l;
38
39         struct counter_comp comp;
40         enum counter_scope scope;
41         void *parent;
42 };
43
44 #define to_counter_attribute(_dev_attr) \
45         container_of(_dev_attr, struct counter_attribute, dev_attr)
46
47 /**
48  * struct counter_attribute_group - container for attribute group
49  * @name:       name of the attribute group
50  * @attr_list:  list to keep track of created attributes
51  * @num_attr:   number of attributes
52  */
53 struct counter_attribute_group {
54         const char *name;
55         struct list_head attr_list;
56         size_t num_attr;
57 };
58
59 static const char *const counter_function_str[] = {
60         [COUNTER_FUNCTION_INCREASE] = "increase",
61         [COUNTER_FUNCTION_DECREASE] = "decrease",
62         [COUNTER_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
63         [COUNTER_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
64         [COUNTER_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
65         [COUNTER_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
66         [COUNTER_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
67         [COUNTER_FUNCTION_QUADRATURE_X4] = "quadrature x4"
68 };
69
70 static const char *const counter_signal_value_str[] = {
71         [COUNTER_SIGNAL_LEVEL_LOW] = "low",
72         [COUNTER_SIGNAL_LEVEL_HIGH] = "high"
73 };
74
75 static const char *const counter_synapse_action_str[] = {
76         [COUNTER_SYNAPSE_ACTION_NONE] = "none",
77         [COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge",
78         [COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge",
79         [COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges"
80 };
81
82 static const char *const counter_count_direction_str[] = {
83         [COUNTER_COUNT_DIRECTION_FORWARD] = "forward",
84         [COUNTER_COUNT_DIRECTION_BACKWARD] = "backward"
85 };
86
87 static const char *const counter_count_mode_str[] = {
88         [COUNTER_COUNT_MODE_NORMAL] = "normal",
89         [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
90         [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
91         [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
92 };
93
94 static const char *const counter_signal_polarity_str[] = {
95         [COUNTER_SIGNAL_POLARITY_POSITIVE] = "positive",
96         [COUNTER_SIGNAL_POLARITY_NEGATIVE] = "negative"
97 };
98
99 static ssize_t counter_comp_u8_show(struct device *dev,
100                                     struct device_attribute *attr, char *buf)
101 {
102         const struct counter_attribute *const a = to_counter_attribute(attr);
103         struct counter_device *const counter = counter_from_dev(dev);
104         int err;
105         u8 data = 0;
106
107         switch (a->scope) {
108         case COUNTER_SCOPE_DEVICE:
109                 err = a->comp.device_u8_read(counter, &data);
110                 break;
111         case COUNTER_SCOPE_SIGNAL:
112                 err = a->comp.signal_u8_read(counter, a->parent, &data);
113                 break;
114         case COUNTER_SCOPE_COUNT:
115                 err = a->comp.count_u8_read(counter, a->parent, &data);
116                 break;
117         default:
118                 return -EINVAL;
119         }
120         if (err < 0)
121                 return err;
122
123         if (a->comp.type == COUNTER_COMP_BOOL)
124                 /* data should already be boolean but ensure just to be safe */
125                 data = !!data;
126
127         return sysfs_emit(buf, "%u\n", (unsigned int)data);
128 }
129
130 static ssize_t counter_comp_u8_store(struct device *dev,
131                                      struct device_attribute *attr,
132                                      const char *buf, size_t len)
133 {
134         const struct counter_attribute *const a = to_counter_attribute(attr);
135         struct counter_device *const counter = counter_from_dev(dev);
136         int err;
137         bool bool_data = 0;
138         u8 data = 0;
139
140         if (a->comp.type == COUNTER_COMP_BOOL) {
141                 err = kstrtobool(buf, &bool_data);
142                 data = bool_data;
143         } else
144                 err = kstrtou8(buf, 0, &data);
145         if (err < 0)
146                 return err;
147
148         switch (a->scope) {
149         case COUNTER_SCOPE_DEVICE:
150                 err = a->comp.device_u8_write(counter, data);
151                 break;
152         case COUNTER_SCOPE_SIGNAL:
153                 err = a->comp.signal_u8_write(counter, a->parent, data);
154                 break;
155         case COUNTER_SCOPE_COUNT:
156                 err = a->comp.count_u8_write(counter, a->parent, data);
157                 break;
158         default:
159                 return -EINVAL;
160         }
161         if (err < 0)
162                 return err;
163
164         return len;
165 }
166
167 static ssize_t counter_comp_u32_show(struct device *dev,
168                                      struct device_attribute *attr, char *buf)
169 {
170         const struct counter_attribute *const a = to_counter_attribute(attr);
171         struct counter_device *const counter = counter_from_dev(dev);
172         const struct counter_available *const avail = a->comp.priv;
173         int err;
174         u32 data = 0;
175
176         switch (a->scope) {
177         case COUNTER_SCOPE_DEVICE:
178                 err = a->comp.device_u32_read(counter, &data);
179                 break;
180         case COUNTER_SCOPE_SIGNAL:
181                 err = a->comp.signal_u32_read(counter, a->parent, &data);
182                 break;
183         case COUNTER_SCOPE_COUNT:
184                 if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION)
185                         err = a->comp.action_read(counter, a->parent,
186                                                   a->comp.priv, &data);
187                 else
188                         err = a->comp.count_u32_read(counter, a->parent, &data);
189                 break;
190         default:
191                 return -EINVAL;
192         }
193         if (err < 0)
194                 return err;
195
196         switch (a->comp.type) {
197         case COUNTER_COMP_FUNCTION:
198                 return sysfs_emit(buf, "%s\n", counter_function_str[data]);
199         case COUNTER_COMP_SIGNAL_LEVEL:
200                 return sysfs_emit(buf, "%s\n", counter_signal_value_str[data]);
201         case COUNTER_COMP_SYNAPSE_ACTION:
202                 return sysfs_emit(buf, "%s\n", counter_synapse_action_str[data]);
203         case COUNTER_COMP_ENUM:
204                 return sysfs_emit(buf, "%s\n", avail->strs[data]);
205         case COUNTER_COMP_COUNT_DIRECTION:
206                 return sysfs_emit(buf, "%s\n", counter_count_direction_str[data]);
207         case COUNTER_COMP_COUNT_MODE:
208                 return sysfs_emit(buf, "%s\n", counter_count_mode_str[data]);
209         case COUNTER_COMP_SIGNAL_POLARITY:
210                 return sysfs_emit(buf, "%s\n", counter_signal_polarity_str[data]);
211         default:
212                 return sysfs_emit(buf, "%u\n", (unsigned int)data);
213         }
214 }
215
216 static int counter_find_enum(u32 *const enum_item, const u32 *const enums,
217                              const size_t num_enums, const char *const buf,
218                              const char *const string_array[])
219 {
220         size_t index;
221
222         for (index = 0; index < num_enums; index++) {
223                 *enum_item = enums[index];
224                 if (sysfs_streq(buf, string_array[*enum_item]))
225                         return 0;
226         }
227
228         return -EINVAL;
229 }
230
231 static ssize_t counter_comp_u32_store(struct device *dev,
232                                       struct device_attribute *attr,
233                                       const char *buf, size_t len)
234 {
235         const struct counter_attribute *const a = to_counter_attribute(attr);
236         struct counter_device *const counter = counter_from_dev(dev);
237         struct counter_count *const count = a->parent;
238         struct counter_synapse *const synapse = a->comp.priv;
239         const struct counter_available *const avail = a->comp.priv;
240         int err;
241         u32 data = 0;
242
243         switch (a->comp.type) {
244         case COUNTER_COMP_FUNCTION:
245                 err = counter_find_enum(&data, count->functions_list,
246                                         count->num_functions, buf,
247                                         counter_function_str);
248                 break;
249         case COUNTER_COMP_SYNAPSE_ACTION:
250                 err = counter_find_enum(&data, synapse->actions_list,
251                                         synapse->num_actions, buf,
252                                         counter_synapse_action_str);
253                 break;
254         case COUNTER_COMP_ENUM:
255                 err = __sysfs_match_string(avail->strs, avail->num_items, buf);
256                 data = err;
257                 break;
258         case COUNTER_COMP_COUNT_MODE:
259                 err = counter_find_enum(&data, avail->enums, avail->num_items,
260                                         buf, counter_count_mode_str);
261                 break;
262         case COUNTER_COMP_SIGNAL_POLARITY:
263                 err = counter_find_enum(&data, avail->enums, avail->num_items,
264                                         buf, counter_signal_polarity_str);
265                 break;
266         default:
267                 err = kstrtou32(buf, 0, &data);
268                 break;
269         }
270         if (err < 0)
271                 return err;
272
273         switch (a->scope) {
274         case COUNTER_SCOPE_DEVICE:
275                 err = a->comp.device_u32_write(counter, data);
276                 break;
277         case COUNTER_SCOPE_SIGNAL:
278                 err = a->comp.signal_u32_write(counter, a->parent, data);
279                 break;
280         case COUNTER_SCOPE_COUNT:
281                 if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION)
282                         err = a->comp.action_write(counter, count, synapse,
283                                                    data);
284                 else
285                         err = a->comp.count_u32_write(counter, count, data);
286                 break;
287         default:
288                 return -EINVAL;
289         }
290         if (err < 0)
291                 return err;
292
293         return len;
294 }
295
296 static ssize_t counter_comp_u64_show(struct device *dev,
297                                      struct device_attribute *attr, char *buf)
298 {
299         const struct counter_attribute *const a = to_counter_attribute(attr);
300         struct counter_device *const counter = counter_from_dev(dev);
301         int err;
302         u64 data = 0;
303
304         switch (a->scope) {
305         case COUNTER_SCOPE_DEVICE:
306                 err = a->comp.device_u64_read(counter, &data);
307                 break;
308         case COUNTER_SCOPE_SIGNAL:
309                 err = a->comp.signal_u64_read(counter, a->parent, &data);
310                 break;
311         case COUNTER_SCOPE_COUNT:
312                 err = a->comp.count_u64_read(counter, a->parent, &data);
313                 break;
314         default:
315                 return -EINVAL;
316         }
317         if (err < 0)
318                 return err;
319
320         return sysfs_emit(buf, "%llu\n", (unsigned long long)data);
321 }
322
323 static ssize_t counter_comp_u64_store(struct device *dev,
324                                       struct device_attribute *attr,
325                                       const char *buf, size_t len)
326 {
327         const struct counter_attribute *const a = to_counter_attribute(attr);
328         struct counter_device *const counter = counter_from_dev(dev);
329         int err;
330         u64 data = 0;
331
332         err = kstrtou64(buf, 0, &data);
333         if (err < 0)
334                 return err;
335
336         switch (a->scope) {
337         case COUNTER_SCOPE_DEVICE:
338                 err = a->comp.device_u64_write(counter, data);
339                 break;
340         case COUNTER_SCOPE_SIGNAL:
341                 err = a->comp.signal_u64_write(counter, a->parent, data);
342                 break;
343         case COUNTER_SCOPE_COUNT:
344                 err = a->comp.count_u64_write(counter, a->parent, data);
345                 break;
346         default:
347                 return -EINVAL;
348         }
349         if (err < 0)
350                 return err;
351
352         return len;
353 }
354
355 static ssize_t counter_comp_array_u32_show(struct device *dev,
356                                            struct device_attribute *attr,
357                                            char *buf)
358 {
359         const struct counter_attribute *const a = to_counter_attribute(attr);
360         struct counter_device *const counter = counter_from_dev(dev);
361         const struct counter_array *const element = a->comp.priv;
362         int err;
363         u32 data = 0;
364
365         if (a->scope != COUNTER_SCOPE_SIGNAL ||
366             element->type != COUNTER_COMP_SIGNAL_POLARITY)
367                 return -EINVAL;
368
369         err = a->comp.signal_array_u32_read(counter, a->parent, element->idx,
370                                             &data);
371         if (err < 0)
372                 return err;
373
374         return sysfs_emit(buf, "%s\n", counter_signal_polarity_str[data]);
375 }
376
377 static ssize_t counter_comp_array_u32_store(struct device *dev,
378                                             struct device_attribute *attr,
379                                             const char *buf, size_t len)
380 {
381         const struct counter_attribute *const a = to_counter_attribute(attr);
382         struct counter_device *const counter = counter_from_dev(dev);
383         const struct counter_array *const element = a->comp.priv;
384         int err;
385         u32 data = 0;
386
387         if (element->type != COUNTER_COMP_SIGNAL_POLARITY ||
388             a->scope != COUNTER_SCOPE_SIGNAL)
389                 return -EINVAL;
390
391         err = counter_find_enum(&data, element->avail->enums,
392                                 element->avail->num_items, buf,
393                                 counter_signal_polarity_str);
394         if (err < 0)
395                 return err;
396
397         err = a->comp.signal_array_u32_write(counter, a->parent, element->idx,
398                                              data);
399         if (err < 0)
400                 return err;
401
402         return len;
403 }
404
405 static ssize_t counter_comp_array_u64_show(struct device *dev,
406                                            struct device_attribute *attr,
407                                            char *buf)
408 {
409         const struct counter_attribute *const a = to_counter_attribute(attr);
410         struct counter_device *const counter = counter_from_dev(dev);
411         const struct counter_array *const element = a->comp.priv;
412         int err;
413         u64 data = 0;
414
415         switch (a->scope) {
416         case COUNTER_SCOPE_DEVICE:
417                 err = a->comp.device_array_u64_read(counter, element->idx,
418                                                     &data);
419                 break;
420         case COUNTER_SCOPE_SIGNAL:
421                 err = a->comp.signal_array_u64_read(counter, a->parent,
422                                                     element->idx, &data);
423                 break;
424         case COUNTER_SCOPE_COUNT:
425                 err = a->comp.count_array_u64_read(counter, a->parent,
426                                                    element->idx, &data);
427                 break;
428         default:
429                 return -EINVAL;
430         }
431         if (err < 0)
432                 return err;
433
434         return sysfs_emit(buf, "%llu\n", (unsigned long long)data);
435 }
436
437 static ssize_t counter_comp_array_u64_store(struct device *dev,
438                                             struct device_attribute *attr,
439                                             const char *buf, size_t len)
440 {
441         const struct counter_attribute *const a = to_counter_attribute(attr);
442         struct counter_device *const counter = counter_from_dev(dev);
443         const struct counter_array *const element = a->comp.priv;
444         int err;
445         u64 data = 0;
446
447         err = kstrtou64(buf, 0, &data);
448         if (err < 0)
449                 return err;
450
451         switch (a->scope) {
452         case COUNTER_SCOPE_DEVICE:
453                 err = a->comp.device_array_u64_write(counter, element->idx,
454                                                      data);
455                 break;
456         case COUNTER_SCOPE_SIGNAL:
457                 err = a->comp.signal_array_u64_write(counter, a->parent,
458                                                      element->idx, data);
459                 break;
460         case COUNTER_SCOPE_COUNT:
461                 err = a->comp.count_array_u64_write(counter, a->parent,
462                                                     element->idx, data);
463                 break;
464         default:
465                 return -EINVAL;
466         }
467         if (err < 0)
468                 return err;
469
470         return len;
471 }
472
473 static ssize_t enums_available_show(const u32 *const enums,
474                                     const size_t num_enums,
475                                     const char *const strs[], char *buf)
476 {
477         size_t len = 0;
478         size_t index;
479
480         for (index = 0; index < num_enums; index++)
481                 len += sysfs_emit_at(buf, len, "%s\n", strs[enums[index]]);
482
483         return len;
484 }
485
486 static ssize_t strs_available_show(const struct counter_available *const avail,
487                                    char *buf)
488 {
489         size_t len = 0;
490         size_t index;
491
492         for (index = 0; index < avail->num_items; index++)
493                 len += sysfs_emit_at(buf, len, "%s\n", avail->strs[index]);
494
495         return len;
496 }
497
498 static ssize_t counter_comp_available_show(struct device *dev,
499                                            struct device_attribute *attr,
500                                            char *buf)
501 {
502         const struct counter_attribute *const a = to_counter_attribute(attr);
503         const struct counter_count *const count = a->parent;
504         const struct counter_synapse *const synapse = a->comp.priv;
505         const struct counter_available *const avail = a->comp.priv;
506
507         switch (a->comp.type) {
508         case COUNTER_COMP_FUNCTION:
509                 return enums_available_show(count->functions_list,
510                                             count->num_functions,
511                                             counter_function_str, buf);
512         case COUNTER_COMP_SYNAPSE_ACTION:
513                 return enums_available_show(synapse->actions_list,
514                                             synapse->num_actions,
515                                             counter_synapse_action_str, buf);
516         case COUNTER_COMP_ENUM:
517                 return strs_available_show(avail, buf);
518         case COUNTER_COMP_COUNT_MODE:
519                 return enums_available_show(avail->enums, avail->num_items,
520                                             counter_count_mode_str, buf);
521         default:
522                 return -EINVAL;
523         }
524 }
525
526 static int counter_avail_attr_create(struct device *const dev,
527         struct counter_attribute_group *const group,
528         const struct counter_comp *const comp, void *const parent)
529 {
530         struct counter_attribute *counter_attr;
531         struct device_attribute *dev_attr;
532
533         counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL);
534         if (!counter_attr)
535                 return -ENOMEM;
536
537         /* Configure Counter attribute */
538         counter_attr->comp.type = comp->type;
539         counter_attr->comp.priv = comp->priv;
540         counter_attr->parent = parent;
541
542         /* Initialize sysfs attribute */
543         dev_attr = &counter_attr->dev_attr;
544         sysfs_attr_init(&dev_attr->attr);
545
546         /* Configure device attribute */
547         dev_attr->attr.name = devm_kasprintf(dev, GFP_KERNEL, "%s_available",
548                                              comp->name);
549         if (!dev_attr->attr.name)
550                 return -ENOMEM;
551         dev_attr->attr.mode = 0444;
552         dev_attr->show = counter_comp_available_show;
553
554         /* Store list node */
555         list_add(&counter_attr->l, &group->attr_list);
556         group->num_attr++;
557
558         return 0;
559 }
560
561 static int counter_attr_create(struct device *const dev,
562                                struct counter_attribute_group *const group,
563                                const struct counter_comp *const comp,
564                                const enum counter_scope scope,
565                                void *const parent)
566 {
567         const struct counter_array *const array = comp->priv;
568         struct counter_attribute *counter_attr;
569         struct device_attribute *dev_attr;
570
571         counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL);
572         if (!counter_attr)
573                 return -ENOMEM;
574
575         /* Configure Counter attribute */
576         counter_attr->comp = *comp;
577         counter_attr->scope = scope;
578         counter_attr->parent = parent;
579
580         /* Configure device attribute */
581         dev_attr = &counter_attr->dev_attr;
582         sysfs_attr_init(&dev_attr->attr);
583         dev_attr->attr.name = comp->name;
584         switch (comp->type) {
585         case COUNTER_COMP_U8:
586         case COUNTER_COMP_BOOL:
587                 if (comp->device_u8_read) {
588                         dev_attr->attr.mode |= 0444;
589                         dev_attr->show = counter_comp_u8_show;
590                 }
591                 if (comp->device_u8_write) {
592                         dev_attr->attr.mode |= 0200;
593                         dev_attr->store = counter_comp_u8_store;
594                 }
595                 break;
596         case COUNTER_COMP_SIGNAL_LEVEL:
597         case COUNTER_COMP_FUNCTION:
598         case COUNTER_COMP_SYNAPSE_ACTION:
599         case COUNTER_COMP_ENUM:
600         case COUNTER_COMP_COUNT_DIRECTION:
601         case COUNTER_COMP_COUNT_MODE:
602         case COUNTER_COMP_SIGNAL_POLARITY:
603                 if (comp->device_u32_read) {
604                         dev_attr->attr.mode |= 0444;
605                         dev_attr->show = counter_comp_u32_show;
606                 }
607                 if (comp->device_u32_write) {
608                         dev_attr->attr.mode |= 0200;
609                         dev_attr->store = counter_comp_u32_store;
610                 }
611                 break;
612         case COUNTER_COMP_U64:
613                 if (comp->device_u64_read) {
614                         dev_attr->attr.mode |= 0444;
615                         dev_attr->show = counter_comp_u64_show;
616                 }
617                 if (comp->device_u64_write) {
618                         dev_attr->attr.mode |= 0200;
619                         dev_attr->store = counter_comp_u64_store;
620                 }
621                 break;
622         case COUNTER_COMP_ARRAY:
623                 switch (array->type) {
624                 case COUNTER_COMP_SIGNAL_POLARITY:
625                         if (comp->signal_array_u32_read) {
626                                 dev_attr->attr.mode |= 0444;
627                                 dev_attr->show = counter_comp_array_u32_show;
628                         }
629                         if (comp->signal_array_u32_write) {
630                                 dev_attr->attr.mode |= 0200;
631                                 dev_attr->store = counter_comp_array_u32_store;
632                         }
633                         break;
634                 case COUNTER_COMP_U64:
635                         if (comp->device_array_u64_read) {
636                                 dev_attr->attr.mode |= 0444;
637                                 dev_attr->show = counter_comp_array_u64_show;
638                         }
639                         if (comp->device_array_u64_write) {
640                                 dev_attr->attr.mode |= 0200;
641                                 dev_attr->store = counter_comp_array_u64_store;
642                         }
643                         break;
644                 default:
645                         return -EINVAL;
646                 }
647                 break;
648         default:
649                 return -EINVAL;
650         }
651
652         /* Store list node */
653         list_add(&counter_attr->l, &group->attr_list);
654         group->num_attr++;
655
656         /* Create "*_available" attribute if needed */
657         switch (comp->type) {
658         case COUNTER_COMP_FUNCTION:
659         case COUNTER_COMP_SYNAPSE_ACTION:
660         case COUNTER_COMP_ENUM:
661         case COUNTER_COMP_COUNT_MODE:
662                 return counter_avail_attr_create(dev, group, comp, parent);
663         default:
664                 return 0;
665         }
666 }
667
668 static ssize_t counter_comp_name_show(struct device *dev,
669                                       struct device_attribute *attr, char *buf)
670 {
671         return sysfs_emit(buf, "%s\n", to_counter_attribute(attr)->comp.name);
672 }
673
674 static int counter_name_attr_create(struct device *const dev,
675                                     struct counter_attribute_group *const group,
676                                     const char *const name)
677 {
678         struct counter_attribute *counter_attr;
679
680         counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL);
681         if (!counter_attr)
682                 return -ENOMEM;
683
684         /* Configure Counter attribute */
685         counter_attr->comp.name = name;
686
687         /* Configure device attribute */
688         sysfs_attr_init(&counter_attr->dev_attr.attr);
689         counter_attr->dev_attr.attr.name = "name";
690         counter_attr->dev_attr.attr.mode = 0444;
691         counter_attr->dev_attr.show = counter_comp_name_show;
692
693         /* Store list node */
694         list_add(&counter_attr->l, &group->attr_list);
695         group->num_attr++;
696
697         return 0;
698 }
699
700 static ssize_t counter_comp_id_show(struct device *dev,
701                                     struct device_attribute *attr, char *buf)
702 {
703         const size_t id = (size_t)to_counter_attribute(attr)->comp.priv;
704
705         return sysfs_emit(buf, "%zu\n", id);
706 }
707
708 static int counter_comp_id_attr_create(struct device *const dev,
709                                        struct counter_attribute_group *const group,
710                                        const char *name, const size_t id)
711 {
712         struct counter_attribute *counter_attr;
713
714         /* Allocate Counter attribute */
715         counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL);
716         if (!counter_attr)
717                 return -ENOMEM;
718
719         /* Generate component ID name */
720         name = devm_kasprintf(dev, GFP_KERNEL, "%s_component_id", name);
721         if (!name)
722                 return -ENOMEM;
723
724         /* Configure Counter attribute */
725         counter_attr->comp.priv = (void *)id;
726
727         /* Configure device attribute */
728         sysfs_attr_init(&counter_attr->dev_attr.attr);
729         counter_attr->dev_attr.attr.name = name;
730         counter_attr->dev_attr.attr.mode = 0444;
731         counter_attr->dev_attr.show = counter_comp_id_show;
732
733         /* Store list node */
734         list_add(&counter_attr->l, &group->attr_list);
735         group->num_attr++;
736
737         return 0;
738 }
739
740 static int counter_ext_attrs_create(struct device *const dev,
741                                     struct counter_attribute_group *const group,
742                                     const struct counter_comp *const ext,
743                                     const enum counter_scope scope,
744                                     void *const parent, const size_t id)
745 {
746         int err;
747
748         /* Create main extension attribute */
749         err = counter_attr_create(dev, group, ext, scope, parent);
750         if (err < 0)
751                 return err;
752
753         /* Create extension id attribute */
754         return counter_comp_id_attr_create(dev, group, ext->name, id);
755 }
756
757 static int counter_array_attrs_create(struct device *const dev,
758                                       struct counter_attribute_group *const group,
759                                       const struct counter_comp *const comp,
760                                       const enum counter_scope scope,
761                                       void *const parent, const size_t id)
762 {
763         const struct counter_array *const array = comp->priv;
764         struct counter_comp ext = *comp;
765         struct counter_array *element;
766         size_t idx;
767         int err;
768
769         /* Create an attribute for each array element */
770         for (idx = 0; idx < array->length; idx++) {
771                 /* Generate array element attribute name */
772                 ext.name = devm_kasprintf(dev, GFP_KERNEL, "%s%zu", comp->name,
773                                           idx);
774                 if (!ext.name)
775                         return -ENOMEM;
776
777                 /* Allocate and configure array element */
778                 element = devm_kzalloc(dev, sizeof(*element), GFP_KERNEL);
779                 if (!element)
780                         return -ENOMEM;
781                 element->type = array->type;
782                 element->avail = array->avail;
783                 element->idx = idx;
784                 ext.priv = element;
785
786                 /* Create all attributes associated with the array element */
787                 err = counter_ext_attrs_create(dev, group, &ext, scope, parent,
788                                                id + idx);
789                 if (err < 0)
790                         return err;
791         }
792
793         return 0;
794 }
795
796 static int counter_sysfs_exts_add(struct device *const dev,
797                                   struct counter_attribute_group *const group,
798                                   const struct counter_comp *const exts,
799                                   const size_t num_ext,
800                                   const enum counter_scope scope,
801                                   void *const parent)
802 {
803         size_t i;
804         const struct counter_comp *ext;
805         int err;
806         size_t id = 0;
807         const struct counter_array *array;
808
809         /* Create attributes for each extension */
810         for (i = 0; i < num_ext; i++) {
811                 ext = &exts[i];
812                 if (ext->type == COUNTER_COMP_ARRAY) {
813                         err = counter_array_attrs_create(dev, group, ext, scope,
814                                                          parent, id);
815                         array = ext->priv;
816                         id += array->length;
817                 } else {
818                         err = counter_ext_attrs_create(dev, group, ext, scope,
819                                                        parent, id);
820                         id++;
821                 }
822                 if (err < 0)
823                         return err;
824         }
825
826         return 0;
827 }
828
829 static struct counter_comp counter_signal_comp = {
830         .type = COUNTER_COMP_SIGNAL_LEVEL,
831         .name = "signal",
832 };
833
834 static int counter_signal_attrs_create(struct counter_device *const counter,
835         struct counter_attribute_group *const cattr_group,
836         struct counter_signal *const signal)
837 {
838         const enum counter_scope scope = COUNTER_SCOPE_SIGNAL;
839         struct device *const dev = &counter->dev;
840         int err;
841         struct counter_comp comp;
842
843         /* Create main Signal attribute */
844         comp = counter_signal_comp;
845         comp.signal_u32_read = counter->ops->signal_read;
846         err = counter_attr_create(dev, cattr_group, &comp, scope, signal);
847         if (err < 0)
848                 return err;
849
850         /* Create Signal name attribute */
851         err = counter_name_attr_create(dev, cattr_group, signal->name);
852         if (err < 0)
853                 return err;
854
855         /* Add Signal extensions */
856         return counter_sysfs_exts_add(dev, cattr_group, signal->ext,
857                                       signal->num_ext, scope, signal);
858 }
859
860 static int counter_sysfs_signals_add(struct counter_device *const counter,
861         struct counter_attribute_group *const groups)
862 {
863         size_t i;
864         int err;
865
866         /* Add each Signal */
867         for (i = 0; i < counter->num_signals; i++) {
868                 /* Generate Signal attribute directory name */
869                 groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL,
870                                                 "signal%zu", i);
871                 if (!groups[i].name)
872                         return -ENOMEM;
873
874                 /* Create all attributes associated with Signal */
875                 err = counter_signal_attrs_create(counter, groups + i,
876                                                   counter->signals + i);
877                 if (err < 0)
878                         return err;
879         }
880
881         return 0;
882 }
883
884 static int counter_sysfs_synapses_add(struct counter_device *const counter,
885         struct counter_attribute_group *const group,
886         struct counter_count *const count)
887 {
888         size_t i;
889
890         /* Add each Synapse */
891         for (i = 0; i < count->num_synapses; i++) {
892                 struct device *const dev = &counter->dev;
893                 struct counter_synapse *synapse;
894                 size_t id;
895                 struct counter_comp comp;
896                 int err;
897
898                 synapse = count->synapses + i;
899
900                 /* Generate Synapse action name */
901                 id = synapse->signal - counter->signals;
902                 comp.name = devm_kasprintf(dev, GFP_KERNEL, "signal%zu_action",
903                                            id);
904                 if (!comp.name)
905                         return -ENOMEM;
906
907                 /* Create action attribute */
908                 comp.type = COUNTER_COMP_SYNAPSE_ACTION;
909                 comp.action_read = counter->ops->action_read;
910                 comp.action_write = counter->ops->action_write;
911                 comp.priv = synapse;
912                 err = counter_attr_create(dev, group, &comp,
913                                           COUNTER_SCOPE_COUNT, count);
914                 if (err < 0)
915                         return err;
916
917                 /* Create Synapse component ID attribute */
918                 err = counter_comp_id_attr_create(dev, group, comp.name, i);
919                 if (err < 0)
920                         return err;
921         }
922
923         return 0;
924 }
925
926 static struct counter_comp counter_count_comp =
927         COUNTER_COMP_COUNT_U64("count", NULL, NULL);
928
929 static struct counter_comp counter_function_comp = {
930         .type = COUNTER_COMP_FUNCTION,
931         .name = "function",
932 };
933
934 static int counter_count_attrs_create(struct counter_device *const counter,
935         struct counter_attribute_group *const cattr_group,
936         struct counter_count *const count)
937 {
938         const enum counter_scope scope = COUNTER_SCOPE_COUNT;
939         struct device *const dev = &counter->dev;
940         int err;
941         struct counter_comp comp;
942
943         /* Create main Count attribute */
944         comp = counter_count_comp;
945         comp.count_u64_read = counter->ops->count_read;
946         comp.count_u64_write = counter->ops->count_write;
947         err = counter_attr_create(dev, cattr_group, &comp, scope, count);
948         if (err < 0)
949                 return err;
950
951         /* Create Count name attribute */
952         err = counter_name_attr_create(dev, cattr_group, count->name);
953         if (err < 0)
954                 return err;
955
956         /* Create Count function attribute */
957         comp = counter_function_comp;
958         comp.count_u32_read = counter->ops->function_read;
959         comp.count_u32_write = counter->ops->function_write;
960         err = counter_attr_create(dev, cattr_group, &comp, scope, count);
961         if (err < 0)
962                 return err;
963
964         /* Add Count extensions */
965         return counter_sysfs_exts_add(dev, cattr_group, count->ext,
966                                       count->num_ext, scope, count);
967 }
968
969 static int counter_sysfs_counts_add(struct counter_device *const counter,
970         struct counter_attribute_group *const groups)
971 {
972         size_t i;
973         struct counter_count *count;
974         int err;
975
976         /* Add each Count */
977         for (i = 0; i < counter->num_counts; i++) {
978                 count = counter->counts + i;
979
980                 /* Generate Count attribute directory name */
981                 groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL,
982                                                 "count%zu", i);
983                 if (!groups[i].name)
984                         return -ENOMEM;
985
986                 /* Add sysfs attributes of the Synapses */
987                 err = counter_sysfs_synapses_add(counter, groups + i, count);
988                 if (err < 0)
989                         return err;
990
991                 /* Create all attributes associated with Count */
992                 err = counter_count_attrs_create(counter, groups + i, count);
993                 if (err < 0)
994                         return err;
995         }
996
997         return 0;
998 }
999
1000 static int counter_num_signals_read(struct counter_device *counter, u8 *val)
1001 {
1002         *val = counter->num_signals;
1003         return 0;
1004 }
1005
1006 static int counter_num_counts_read(struct counter_device *counter, u8 *val)
1007 {
1008         *val = counter->num_counts;
1009         return 0;
1010 }
1011
1012 static int counter_events_queue_size_read(struct counter_device *counter,
1013                                           u64 *val)
1014 {
1015         *val = kfifo_size(&counter->events);
1016         return 0;
1017 }
1018
1019 static int counter_events_queue_size_write(struct counter_device *counter,
1020                                            u64 val)
1021 {
1022         DECLARE_KFIFO_PTR(events, struct counter_event);
1023         int err;
1024         unsigned long flags;
1025
1026         /* Allocate new events queue */
1027         err = kfifo_alloc(&events, val, GFP_KERNEL);
1028         if (err)
1029                 return err;
1030
1031         /* Swap in new events queue */
1032         mutex_lock(&counter->events_out_lock);
1033         spin_lock_irqsave(&counter->events_in_lock, flags);
1034         kfifo_free(&counter->events);
1035         counter->events.kfifo = events.kfifo;
1036         spin_unlock_irqrestore(&counter->events_in_lock, flags);
1037         mutex_unlock(&counter->events_out_lock);
1038
1039         return 0;
1040 }
1041
1042 static struct counter_comp counter_num_signals_comp =
1043         COUNTER_COMP_DEVICE_U8("num_signals", counter_num_signals_read, NULL);
1044
1045 static struct counter_comp counter_num_counts_comp =
1046         COUNTER_COMP_DEVICE_U8("num_counts", counter_num_counts_read, NULL);
1047
1048 static struct counter_comp counter_events_queue_size_comp =
1049         COUNTER_COMP_DEVICE_U64("events_queue_size",
1050                                 counter_events_queue_size_read,
1051                                 counter_events_queue_size_write);
1052
1053 static int counter_sysfs_attr_add(struct counter_device *const counter,
1054                                   struct counter_attribute_group *cattr_group)
1055 {
1056         const enum counter_scope scope = COUNTER_SCOPE_DEVICE;
1057         struct device *const dev = &counter->dev;
1058         int err;
1059
1060         /* Add Signals sysfs attributes */
1061         err = counter_sysfs_signals_add(counter, cattr_group);
1062         if (err < 0)
1063                 return err;
1064         cattr_group += counter->num_signals;
1065
1066         /* Add Counts sysfs attributes */
1067         err = counter_sysfs_counts_add(counter, cattr_group);
1068         if (err < 0)
1069                 return err;
1070         cattr_group += counter->num_counts;
1071
1072         /* Create name attribute */
1073         err = counter_name_attr_create(dev, cattr_group, counter->name);
1074         if (err < 0)
1075                 return err;
1076
1077         /* Create num_signals attribute */
1078         err = counter_attr_create(dev, cattr_group, &counter_num_signals_comp,
1079                                   scope, NULL);
1080         if (err < 0)
1081                 return err;
1082
1083         /* Create num_counts attribute */
1084         err = counter_attr_create(dev, cattr_group, &counter_num_counts_comp,
1085                                   scope, NULL);
1086         if (err < 0)
1087                 return err;
1088
1089         /* Create events_queue_size attribute */
1090         err = counter_attr_create(dev, cattr_group,
1091                                   &counter_events_queue_size_comp, scope, NULL);
1092         if (err < 0)
1093                 return err;
1094
1095         /* Add device extensions */
1096         return counter_sysfs_exts_add(dev, cattr_group, counter->ext,
1097                                       counter->num_ext, scope, NULL);
1098
1099         return 0;
1100 }
1101
1102 /**
1103  * counter_sysfs_add - Adds Counter sysfs attributes to the device structure
1104  * @counter:    Pointer to the Counter device structure
1105  *
1106  * Counter sysfs attributes are created and added to the respective device
1107  * structure for later registration to the system. Resource-managed memory
1108  * allocation is performed by this function, and this memory should be freed
1109  * when no longer needed (automatically by a device_unregister call, or
1110  * manually by a devres_release_all call).
1111  */
1112 int counter_sysfs_add(struct counter_device *const counter)
1113 {
1114         struct device *const dev = &counter->dev;
1115         const size_t num_groups = counter->num_signals + counter->num_counts + 1;
1116         struct counter_attribute_group *cattr_groups;
1117         size_t i, j;
1118         int err;
1119         struct attribute_group *groups;
1120         struct counter_attribute *p;
1121
1122         /* Allocate space for attribute groups (signals, counts, and ext) */
1123         cattr_groups = devm_kcalloc(dev, num_groups, sizeof(*cattr_groups),
1124                                     GFP_KERNEL);
1125         if (!cattr_groups)
1126                 return -ENOMEM;
1127
1128         /* Initialize attribute lists */
1129         for (i = 0; i < num_groups; i++)
1130                 INIT_LIST_HEAD(&cattr_groups[i].attr_list);
1131
1132         /* Add Counter device sysfs attributes */
1133         err = counter_sysfs_attr_add(counter, cattr_groups);
1134         if (err < 0)
1135                 return err;
1136
1137         /* Allocate attribute group pointers for association with device */
1138         dev->groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev->groups),
1139                                    GFP_KERNEL);
1140         if (!dev->groups)
1141                 return -ENOMEM;
1142
1143         /* Allocate space for attribute groups */
1144         groups = devm_kcalloc(dev, num_groups, sizeof(*groups), GFP_KERNEL);
1145         if (!groups)
1146                 return -ENOMEM;
1147
1148         /* Prepare each group of attributes for association */
1149         for (i = 0; i < num_groups; i++) {
1150                 groups[i].name = cattr_groups[i].name;
1151
1152                 /* Allocate space for attribute pointers */
1153                 groups[i].attrs = devm_kcalloc(dev,
1154                                                cattr_groups[i].num_attr + 1,
1155                                                sizeof(*groups[i].attrs),
1156                                                GFP_KERNEL);
1157                 if (!groups[i].attrs)
1158                         return -ENOMEM;
1159
1160                 /* Add attribute pointers to attribute group */
1161                 j = 0;
1162                 list_for_each_entry(p, &cattr_groups[i].attr_list, l)
1163                         groups[i].attrs[j++] = &p->dev_attr.attr;
1164
1165                 /* Associate attribute group */
1166                 dev->groups[i] = &groups[i];
1167         }
1168
1169         return 0;
1170 }