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