xref: /linux/net/atm/atm_sysfs.c (revision 367b8112fe2ea5c39a7bb4d263dcdd9b612fae18)
1 /* ATM driver model support. */
2 
3 #include <linux/kernel.h>
4 #include <linux/init.h>
5 #include <linux/kobject.h>
6 #include <linux/atmdev.h>
7 #include "common.h"
8 #include "resources.h"
9 
10 #define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev)
11 
12 static ssize_t show_type(struct device *cdev,
13 			 struct device_attribute *attr, 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 device *cdev,
20 			    struct device_attribute *attr, char *buf)
21 {
22 	char *pos = buf;
23 	struct atm_dev *adev = to_atm_dev(cdev);
24 	int i;
25 
26 	for (i = 0; i < (ESI_LEN - 1); i++)
27 		pos += sprintf(pos, "%02x:", adev->esi[i]);
28 	pos += sprintf(pos, "%02x\n", adev->esi[i]);
29 
30 	return pos - buf;
31 }
32 
33 static ssize_t show_atmaddress(struct device *cdev,
34 			       struct device_attribute *attr, char *buf)
35 {
36 	unsigned long flags;
37 	char *pos = buf;
38 	struct atm_dev *adev = to_atm_dev(cdev);
39 	struct atm_dev_addr *aaddr;
40 	int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
41 	int i, j;
42 
43 	spin_lock_irqsave(&adev->lock, flags);
44 	list_for_each_entry(aaddr, &adev->local, entry) {
45 		for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
46 			if (j == *fmt) {
47 				pos += sprintf(pos, ".");
48 				++fmt;
49 				j = 0;
50 			}
51 			pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]);
52 		}
53 		pos += sprintf(pos, "\n");
54 	}
55 	spin_unlock_irqrestore(&adev->lock, flags);
56 
57 	return pos - buf;
58 }
59 
60 static ssize_t show_carrier(struct device *cdev,
61 			    struct device_attribute *attr, char *buf)
62 {
63 	char *pos = buf;
64 	struct atm_dev *adev = to_atm_dev(cdev);
65 
66 	pos += sprintf(pos, "%d\n",
67 		       adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
68 
69 	return pos - buf;
70 }
71 
72 static ssize_t show_link_rate(struct device *cdev,
73 			      struct device_attribute *attr, char *buf)
74 {
75 	char *pos = buf;
76 	struct atm_dev *adev = to_atm_dev(cdev);
77 	int link_rate;
78 
79 	/* show the link rate, not the data rate */
80 	switch (adev->link_rate) {
81 		case ATM_OC3_PCR:
82 			link_rate = 155520000;
83 			break;
84 		case ATM_OC12_PCR:
85 			link_rate = 622080000;
86 			break;
87 		case ATM_25_PCR:
88 			link_rate = 25600000;
89 			break;
90 		default:
91 			link_rate = adev->link_rate * 8 * 53;
92 	}
93 	pos += sprintf(pos, "%d\n", link_rate);
94 
95 	return pos - buf;
96 }
97 
98 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
99 static DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL);
100 static DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
101 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
102 static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
103 
104 static struct device_attribute *atm_attrs[] = {
105 	&dev_attr_atmaddress,
106 	&dev_attr_address,
107 	&dev_attr_carrier,
108 	&dev_attr_type,
109 	&dev_attr_link_rate,
110 	NULL
111 };
112 
113 
114 static int atm_uevent(struct device *cdev, struct kobj_uevent_env *env)
115 {
116 	struct atm_dev *adev;
117 
118 	if (!cdev)
119 		return -ENODEV;
120 
121 	adev = to_atm_dev(cdev);
122 	if (!adev)
123 		return -ENODEV;
124 
125 	if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number))
126 		return -ENOMEM;
127 
128 	return 0;
129 }
130 
131 static void atm_release(struct device *cdev)
132 {
133 	struct atm_dev *adev = to_atm_dev(cdev);
134 
135 	kfree(adev);
136 }
137 
138 static struct class atm_class = {
139 	.name		= "atm",
140 	.dev_release	= atm_release,
141 	.dev_uevent		= atm_uevent,
142 };
143 
144 int atm_register_sysfs(struct atm_dev *adev)
145 {
146 	struct device *cdev = &adev->class_dev;
147 	int i, j, err;
148 
149 	cdev->class = &atm_class;
150 	dev_set_drvdata(cdev, adev);
151 
152 	snprintf(cdev->bus_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number);
153 	err = device_register(cdev);
154 	if (err < 0)
155 		return err;
156 
157 	for (i = 0; atm_attrs[i]; i++) {
158 		err = device_create_file(cdev, atm_attrs[i]);
159 		if (err)
160 			goto err_out;
161 	}
162 
163 	return 0;
164 
165 err_out:
166 	for (j = 0; j < i; j++)
167 		device_remove_file(cdev, atm_attrs[j]);
168 	device_del(cdev);
169 	return err;
170 }
171 
172 void atm_unregister_sysfs(struct atm_dev *adev)
173 {
174 	struct device *cdev = &adev->class_dev;
175 
176 	device_del(cdev);
177 }
178 
179 int __init atm_sysfs_init(void)
180 {
181 	return class_register(&atm_class);
182 }
183 
184 void __exit atm_sysfs_exit(void)
185 {
186 	class_unregister(&atm_class);
187 }
188