f6e5ee066168d24b4903e934e9f934f840f8132a
[openwrt/svn-archive/archive.git] / package / lqtapi / src / tapi / tapi-sysfs-port.c
1 #include <linux/device.h>
2 #include <linux/kernel.h>
3 #include <linux/sysfs.h>
4
5 #include <linux/err.h>
6 #include <linux/tapi/tapi.h>
7
8 struct tapi_sysfs_port {
9 struct tapi_device *tdev;
10 unsigned int id;
11 struct kobject kobj;
12 };
13
14 struct tapi_sysfs_entry {
15 ssize_t (*show)(struct tapi_device *, unsigned int port, char *);
16 ssize_t (*store)(struct tapi_device *, unsigned int port, const char *, size_t);
17 struct attribute attr;
18 };
19
20 static ssize_t tapi_port_store(struct kobject *kobj, struct attribute *attr,
21 const char *s, size_t len)
22 {
23 struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
24 struct tapi_sysfs_entry *entry = container_of(attr, struct tapi_sysfs_entry,
25 attr);
26
27 if (!entry->store)
28 return -ENOSYS;
29
30 return entry->store(port->tdev, port->id, s, len);
31 }
32
33 static ssize_t tapi_port_show(struct kobject *kobj, struct attribute *attr,
34 char *s)
35 {
36 return -ENOSYS;
37 }
38
39 #define TAPI_PORT_ATTR(_name, _mode, _show, _store) \
40 struct tapi_sysfs_entry tapi_port_ ## _name ## _attr = \
41 __ATTR(_name, _mode, _show, _store)
42
43 static int tapi_port_store_ring(struct tapi_device *tdev, unsigned int port,
44 const char *s, size_t len)
45 {
46 int ret;
47 unsigned long val;
48
49 ret = strict_strtoul(s, 10, &val);
50
51 if (ret)
52 return ret;
53
54 ret = tapi_port_set_ring(tdev, &tdev->ports[port], val);
55 if (ret)
56 return ret;
57 return len;
58 }
59
60 static TAPI_PORT_ATTR(ring, 0644, NULL, tapi_port_store_ring);
61
62 static struct attribute *tapi_port_default_attrs[] = {
63 &tapi_port_ring_attr.attr,
64 NULL,
65 };
66
67 static void tapi_port_free(struct kobject *kobj)
68 {
69 struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
70 kfree(port);
71 }
72
73 static struct sysfs_ops tapi_port_sysfs_ops = {
74 .show = tapi_port_show,
75 .store = tapi_port_store,
76 };
77
78 static struct kobj_type tapi_port_ktype = {
79 .release = tapi_port_free,
80 .sysfs_ops = &tapi_port_sysfs_ops,
81 .default_attrs = tapi_port_default_attrs,
82 };
83
84 struct tapi_sysfs_port *tapi_port_alloc(struct tapi_device *tdev, unsigned int id)
85 {
86 struct tapi_sysfs_port *port;
87 int ret;
88
89 port = kzalloc(sizeof(*port), GFP_KERNEL);
90 port->tdev = tdev;
91 port->id = id;
92
93 ret = kobject_init_and_add(&port->kobj, &tapi_port_ktype, &tdev->dev.kobj,
94 "port%d", id);
95 if (ret) {
96 kfree(port);
97 return ERR_PTR(ret);
98 }
99
100 return port;
101 }
102
103 void tapi_port_delete(struct tapi_sysfs_port *port)
104 {
105 kobject_del(&port->kobj);
106 kobject_put(&port->kobj);
107 }