[ifxmips]
[openwrt.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 }