diff options
author | Roman Kagan <rkagan@mail.ru> | 2006-06-29 15:36:34 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-29 19:58:19 -0400 |
commit | 656d98b09d57d4e1185c5d2436a42600d48fbcb5 (patch) | |
tree | 42c8795ea142e6c0a002bcdb26d255e2b8693e4c | |
parent | d17f086550a6fdb13fe82371d60ebf80904c6f96 (diff) |
[ATM]: basic sysfs support for ATM devices
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/atmdev.h | 4 | ||||
-rw-r--r-- | net/atm/Makefile | 2 | ||||
-rw-r--r-- | net/atm/atm_sysfs.c | 176 | ||||
-rw-r--r-- | net/atm/common.c | 7 | ||||
-rw-r--r-- | net/atm/common.h | 2 | ||||
-rw-r--r-- | net/atm/resources.c | 22 | ||||
-rw-r--r-- | net/atm/resources.h | 2 |
7 files changed, 209 insertions, 6 deletions
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 1eb238affb12..41788a31c438 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #define LINUX_ATMDEV_H | 7 | #define LINUX_ATMDEV_H |
8 | 8 | ||
9 | 9 | ||
10 | #include <linux/device.h> | ||
10 | #include <linux/atmapi.h> | 11 | #include <linux/atmapi.h> |
11 | #include <linux/atm.h> | 12 | #include <linux/atm.h> |
12 | #include <linux/atmioc.h> | 13 | #include <linux/atmioc.h> |
@@ -358,6 +359,7 @@ struct atm_dev { | |||
358 | struct proc_dir_entry *proc_entry; /* proc entry */ | 359 | struct proc_dir_entry *proc_entry; /* proc entry */ |
359 | char *proc_name; /* proc entry name */ | 360 | char *proc_name; /* proc entry name */ |
360 | #endif | 361 | #endif |
362 | struct class_device class_dev; /* sysfs class device */ | ||
361 | struct list_head dev_list; /* linkage */ | 363 | struct list_head dev_list; /* linkage */ |
362 | }; | 364 | }; |
363 | 365 | ||
@@ -459,7 +461,7 @@ static inline void atm_dev_put(struct atm_dev *dev) | |||
459 | BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags)); | 461 | BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags)); |
460 | if (dev->ops->dev_close) | 462 | if (dev->ops->dev_close) |
461 | dev->ops->dev_close(dev); | 463 | dev->ops->dev_close(dev); |
462 | kfree(dev); | 464 | class_device_put(&dev->class_dev); |
463 | } | 465 | } |
464 | } | 466 | } |
465 | 467 | ||
diff --git a/net/atm/Makefile b/net/atm/Makefile index d5818751f6ba..89656d6c0b90 100644 --- a/net/atm/Makefile +++ b/net/atm/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the ATM Protocol Families. | 2 | # Makefile for the ATM Protocol Families. |
3 | # | 3 | # |
4 | 4 | ||
5 | atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o | 5 | atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o |
6 | mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o | 6 | mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o |
7 | 7 | ||
8 | obj-$(CONFIG_ATM) += atm.o | 8 | obj-$(CONFIG_ATM) += atm.o |
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c new file mode 100644 index 000000000000..5df4b9a068bb --- /dev/null +++ b/net/atm/atm_sysfs.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* ATM driver model support. */ | ||
2 | |||
3 | #include <linux/config.h> | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/kobject.h> | ||
7 | #include <linux/atmdev.h> | ||
8 | #include "common.h" | ||
9 | #include "resources.h" | ||
10 | |||
11 | #define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev) | ||
12 | |||
13 | static ssize_t show_type(struct class_device *cdev, char *buf) | ||
14 | { | ||
15 | struct atm_dev *adev = to_atm_dev(cdev); | ||
16 | return sprintf(buf, "%s\n", adev->type); | ||
17 | } | ||
18 | |||
19 | static ssize_t show_address(struct class_device *cdev, char *buf) | ||
20 | { | ||
21 | char *pos = buf; | ||
22 | struct atm_dev *adev = to_atm_dev(cdev); | ||
23 | int i; | ||
24 | |||
25 | for (i = 0; i < (ESI_LEN - 1); i++) | ||
26 | pos += sprintf(pos, "%02x:", adev->esi[i]); | ||
27 | pos += sprintf(pos, "%02x\n", adev->esi[i]); | ||
28 | |||
29 | return pos - buf; | ||
30 | } | ||
31 | |||
32 | static ssize_t show_atmaddress(struct class_device *cdev, char *buf) | ||
33 | { | ||
34 | unsigned long flags; | ||
35 | char *pos = buf; | ||
36 | struct atm_dev *adev = to_atm_dev(cdev); | ||
37 | struct atm_dev_addr *aaddr; | ||
38 | int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; | ||
39 | int i, j; | ||
40 | |||
41 | spin_lock_irqsave(&adev->lock, flags); | ||
42 | list_for_each_entry(aaddr, &adev->local, entry) { | ||
43 | for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { | ||
44 | if (j == *fmt) { | ||
45 | pos += sprintf(pos, "."); | ||
46 | ++fmt; | ||
47 | j = 0; | ||
48 | } | ||
49 | pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]); | ||
50 | } | ||
51 | pos += sprintf(pos, "\n"); | ||
52 | } | ||
53 | spin_unlock_irqrestore(&adev->lock, flags); | ||
54 | |||
55 | return pos - buf; | ||
56 | } | ||
57 | |||
58 | static ssize_t show_carrier(struct class_device *cdev, char *buf) | ||
59 | { | ||
60 | char *pos = buf; | ||
61 | struct atm_dev *adev = to_atm_dev(cdev); | ||
62 | |||
63 | pos += sprintf(pos, "%d\n", | ||
64 | adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); | ||
65 | |||
66 | return pos - buf; | ||
67 | } | ||
68 | |||
69 | static ssize_t show_link_rate(struct class_device *cdev, char *buf) | ||
70 | { | ||
71 | char *pos = buf; | ||
72 | struct atm_dev *adev = to_atm_dev(cdev); | ||
73 | int link_rate; | ||
74 | |||
75 | /* show the link rate, not the data rate */ | ||
76 | switch (adev->link_rate) { | ||
77 | case ATM_OC3_PCR: | ||
78 | link_rate = 155520000; | ||
79 | break; | ||
80 | case ATM_OC12_PCR: | ||
81 | link_rate = 622080000; | ||
82 | break; | ||
83 | case ATM_25_PCR: | ||
84 | link_rate = 25600000; | ||
85 | break; | ||
86 | default: | ||
87 | link_rate = adev->link_rate * 8 * 53; | ||
88 | } | ||
89 | pos += sprintf(pos, "%d\n", link_rate); | ||
90 | |||
91 | return pos - buf; | ||
92 | } | ||
93 | |||
94 | static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | ||
95 | static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); | ||
96 | static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); | ||
97 | static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | ||
98 | static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); | ||
99 | |||
100 | static struct class_device_attribute *atm_attrs[] = { | ||
101 | &class_device_attr_atmaddress, | ||
102 | &class_device_attr_address, | ||
103 | &class_device_attr_carrier, | ||
104 | &class_device_attr_type, | ||
105 | &class_device_attr_link_rate, | ||
106 | NULL | ||
107 | }; | ||
108 | |||
109 | static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) | ||
110 | { | ||
111 | struct atm_dev *adev; | ||
112 | int i = 0, len = 0; | ||
113 | |||
114 | if (!cdev) | ||
115 | return -ENODEV; | ||
116 | |||
117 | adev = to_atm_dev(cdev); | ||
118 | if (!adev) | ||
119 | return -ENODEV; | ||
120 | |||
121 | if (add_uevent_var(envp, num_envp, &i, buf, size, &len, | ||
122 | "NAME=%s%d", adev->type, adev->number)) | ||
123 | return -ENOMEM; | ||
124 | |||
125 | envp[i] = NULL; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static void atm_release(struct class_device *cdev) | ||
130 | { | ||
131 | struct atm_dev *adev = to_atm_dev(cdev); | ||
132 | |||
133 | kfree(adev); | ||
134 | } | ||
135 | |||
136 | static struct class atm_class = { | ||
137 | .name = "atm", | ||
138 | .release = atm_release, | ||
139 | .uevent = atm_uevent, | ||
140 | }; | ||
141 | |||
142 | int atm_register_sysfs(struct atm_dev *adev) | ||
143 | { | ||
144 | struct class_device *cdev = &adev->class_dev; | ||
145 | int i, err; | ||
146 | |||
147 | cdev->class = &atm_class; | ||
148 | class_set_devdata(cdev, adev); | ||
149 | |||
150 | snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number); | ||
151 | err = class_device_register(cdev); | ||
152 | if (err < 0) | ||
153 | return err; | ||
154 | |||
155 | for (i = 0; atm_attrs[i]; i++) | ||
156 | class_device_create_file(cdev, atm_attrs[i]); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | void atm_unregister_sysfs(struct atm_dev *adev) | ||
162 | { | ||
163 | struct class_device *cdev = &adev->class_dev; | ||
164 | |||
165 | class_device_del(cdev); | ||
166 | } | ||
167 | |||
168 | int __init atm_sysfs_init(void) | ||
169 | { | ||
170 | return class_register(&atm_class); | ||
171 | } | ||
172 | |||
173 | void __exit atm_sysfs_exit(void) | ||
174 | { | ||
175 | class_unregister(&atm_class); | ||
176 | } | ||
diff --git a/net/atm/common.c b/net/atm/common.c index ae002220fa99..35ab1a61e831 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -791,8 +791,14 @@ static int __init atm_init(void) | |||
791 | printk(KERN_ERR "atm_proc_init() failed with %d\n",error); | 791 | printk(KERN_ERR "atm_proc_init() failed with %d\n",error); |
792 | goto out_atmsvc_exit; | 792 | goto out_atmsvc_exit; |
793 | } | 793 | } |
794 | if ((error = atm_sysfs_init()) < 0) { | ||
795 | printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error); | ||
796 | goto out_atmproc_exit; | ||
797 | } | ||
794 | out: | 798 | out: |
795 | return error; | 799 | return error; |
800 | out_atmproc_exit: | ||
801 | atm_proc_exit(); | ||
796 | out_atmsvc_exit: | 802 | out_atmsvc_exit: |
797 | atmsvc_exit(); | 803 | atmsvc_exit(); |
798 | out_atmpvc_exit: | 804 | out_atmpvc_exit: |
@@ -805,6 +811,7 @@ out_unregister_vcc_proto: | |||
805 | static void __exit atm_exit(void) | 811 | static void __exit atm_exit(void) |
806 | { | 812 | { |
807 | atm_proc_exit(); | 813 | atm_proc_exit(); |
814 | atm_sysfs_exit(); | ||
808 | atmsvc_exit(); | 815 | atmsvc_exit(); |
809 | atmpvc_exit(); | 816 | atmpvc_exit(); |
810 | proto_unregister(&vcc_proto); | 817 | proto_unregister(&vcc_proto); |
diff --git a/net/atm/common.h b/net/atm/common.h index 4887c317cefe..a422da7788fb 100644 --- a/net/atm/common.h +++ b/net/atm/common.h | |||
@@ -28,6 +28,8 @@ int atmpvc_init(void); | |||
28 | void atmpvc_exit(void); | 28 | void atmpvc_exit(void); |
29 | int atmsvc_init(void); | 29 | int atmsvc_init(void); |
30 | void atmsvc_exit(void); | 30 | void atmsvc_exit(void); |
31 | int atm_sysfs_init(void); | ||
32 | void atm_sysfs_exit(void); | ||
31 | 33 | ||
32 | #ifdef CONFIG_PROC_FS | 34 | #ifdef CONFIG_PROC_FS |
33 | int atm_proc_init(void); | 35 | int atm_proc_init(void); |
diff --git a/net/atm/resources.c b/net/atm/resources.c index 18ac80698f83..534baf704056 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c | |||
@@ -114,14 +114,27 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, | |||
114 | printk(KERN_ERR "atm_dev_register: " | 114 | printk(KERN_ERR "atm_dev_register: " |
115 | "atm_proc_dev_register failed for dev %s\n", | 115 | "atm_proc_dev_register failed for dev %s\n", |
116 | type); | 116 | type); |
117 | mutex_unlock(&atm_dev_mutex); | 117 | goto out_fail; |
118 | kfree(dev); | 118 | } |
119 | return NULL; | 119 | |
120 | if (atm_register_sysfs(dev) < 0) { | ||
121 | printk(KERN_ERR "atm_dev_register: " | ||
122 | "atm_register_sysfs failed for dev %s\n", | ||
123 | type); | ||
124 | atm_proc_dev_deregister(dev); | ||
125 | goto out_fail; | ||
120 | } | 126 | } |
127 | |||
121 | list_add_tail(&dev->dev_list, &atm_devs); | 128 | list_add_tail(&dev->dev_list, &atm_devs); |
122 | mutex_unlock(&atm_dev_mutex); | ||
123 | 129 | ||
130 | out: | ||
131 | mutex_unlock(&atm_dev_mutex); | ||
124 | return dev; | 132 | return dev; |
133 | |||
134 | out_fail: | ||
135 | kfree(dev); | ||
136 | dev = NULL; | ||
137 | goto out; | ||
125 | } | 138 | } |
126 | 139 | ||
127 | 140 | ||
@@ -140,6 +153,7 @@ void atm_dev_deregister(struct atm_dev *dev) | |||
140 | mutex_unlock(&atm_dev_mutex); | 153 | mutex_unlock(&atm_dev_mutex); |
141 | 154 | ||
142 | atm_dev_release_vccs(dev); | 155 | atm_dev_release_vccs(dev); |
156 | atm_unregister_sysfs(dev); | ||
143 | atm_proc_dev_deregister(dev); | 157 | atm_proc_dev_deregister(dev); |
144 | 158 | ||
145 | atm_dev_put(dev); | 159 | atm_dev_put(dev); |
diff --git a/net/atm/resources.h b/net/atm/resources.h index ac7222fee7a8..644989980c37 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h | |||
@@ -43,4 +43,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev) | |||
43 | 43 | ||
44 | #endif /* CONFIG_PROC_FS */ | 44 | #endif /* CONFIG_PROC_FS */ |
45 | 45 | ||
46 | int atm_register_sysfs(struct atm_dev *adev); | ||
47 | void atm_unregister_sysfs(struct atm_dev *adev); | ||
46 | #endif | 48 | #endif |