1 /*
2 * dim2_sysfs.c - MediaLB sysfs information
3 *
4 * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * This file is licensed under GPLv2.
12 */
13
14 /* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
15
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18 #include <linux/kernel.h>
19 #include "dim2_sysfs.h"
20
21 struct bus_attr {
22 struct attribute attr;
23 ssize_t (*show)(struct medialb_bus *bus, char *buf);
24 ssize_t (*store)(struct medialb_bus *bus, const char *buf,
25 size_t count);
26 };
27
state_show(struct medialb_bus * bus,char * buf)28 static ssize_t state_show(struct medialb_bus *bus, char *buf)
29 {
30 bool state = dim2_sysfs_get_state_cb();
31
32 return sprintf(buf, "%s\n", state ? "locked" : "");
33 }
34
35 static struct bus_attr state_attr = __ATTR_RO(state);
36
37 static struct attribute *bus_default_attrs[] = {
38 &state_attr.attr,
39 NULL,
40 };
41
42 static struct attribute_group bus_attr_group = {
43 .attrs = bus_default_attrs,
44 };
45
bus_kobj_release(struct kobject * kobj)46 static void bus_kobj_release(struct kobject *kobj)
47 {
48 }
49
bus_kobj_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)50 static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
51 char *buf)
52 {
53 struct medialb_bus *bus =
54 container_of(kobj, struct medialb_bus, kobj_group);
55 struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
56
57 if (!xattr->show)
58 return -EIO;
59
60 return xattr->show(bus, buf);
61 }
62
bus_kobj_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t count)63 static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
64 const char *buf, size_t count)
65 {
66 ssize_t ret;
67 struct medialb_bus *bus =
68 container_of(kobj, struct medialb_bus, kobj_group);
69 struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
70
71 if (!xattr->store)
72 return -EIO;
73
74 ret = xattr->store(bus, buf, count);
75 return ret;
76 }
77
78 static struct sysfs_ops const bus_kobj_sysfs_ops = {
79 .show = bus_kobj_attr_show,
80 .store = bus_kobj_attr_store,
81 };
82
83 static struct kobj_type bus_ktype = {
84 .release = bus_kobj_release,
85 .sysfs_ops = &bus_kobj_sysfs_ops,
86 };
87
dim2_sysfs_probe(struct medialb_bus * bus,struct kobject * parent_kobj)88 int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
89 {
90 int err;
91
92 kobject_init(&bus->kobj_group, &bus_ktype);
93 err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
94 if (err) {
95 pr_err("kobject_add() failed: %d\n", err);
96 goto err_kobject_add;
97 }
98
99 err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
100 if (err) {
101 pr_err("sysfs_create_group() failed: %d\n", err);
102 goto err_create_group;
103 }
104
105 return 0;
106
107 err_create_group:
108 kobject_put(&bus->kobj_group);
109
110 err_kobject_add:
111 return err;
112 }
113
dim2_sysfs_destroy(struct medialb_bus * bus)114 void dim2_sysfs_destroy(struct medialb_bus *bus)
115 {
116 kobject_put(&bus->kobj_group);
117 }
118