]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
656d98b0 RK |
2 | /* ATM driver model support. */ |
3 | ||
656d98b0 | 4 | #include <linux/kernel.h> |
5a0e3ad6 | 5 | #include <linux/slab.h> |
656d98b0 RK |
6 | #include <linux/init.h> |
7 | #include <linux/kobject.h> | |
8 | #include <linux/atmdev.h> | |
9 | #include "common.h" | |
10 | #include "resources.h" | |
11 | ||
12 | #define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev) | |
13 | ||
48afdaea | 14 | static ssize_t type_show(struct device *cdev, |
ef39592f | 15 | struct device_attribute *attr, char *buf) |
656d98b0 RK |
16 | { |
17 | struct atm_dev *adev = to_atm_dev(cdev); | |
3c417771 C |
18 | |
19 | return scnprintf(buf, PAGE_SIZE, "%s\n", adev->type); | |
656d98b0 RK |
20 | } |
21 | ||
48afdaea | 22 | static ssize_t address_show(struct device *cdev, |
ef39592f | 23 | struct device_attribute *attr, char *buf) |
656d98b0 | 24 | { |
656d98b0 | 25 | struct atm_dev *adev = to_atm_dev(cdev); |
656d98b0 | 26 | |
3c417771 | 27 | return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi); |
656d98b0 RK |
28 | } |
29 | ||
48afdaea | 30 | static ssize_t atmaddress_show(struct device *cdev, |
ef39592f | 31 | struct device_attribute *attr, char *buf) |
656d98b0 | 32 | { |
f7d57453 | 33 | unsigned long flags; |
656d98b0 | 34 | struct atm_dev *adev = to_atm_dev(cdev); |
f7d57453 | 35 | struct atm_dev_addr *aaddr; |
79ac5224 | 36 | int count = 0; |
656d98b0 | 37 | |
f7d57453 YH |
38 | spin_lock_irqsave(&adev->lock, flags); |
39 | list_for_each_entry(aaddr, &adev->local, entry) { | |
79ac5224 AS |
40 | count += scnprintf(buf + count, PAGE_SIZE - count, |
41 | "%1phN.%2phN.%10phN.%6phN.%1phN\n", | |
42 | &aaddr->addr.sas_addr.prv[0], | |
43 | &aaddr->addr.sas_addr.prv[1], | |
44 | &aaddr->addr.sas_addr.prv[3], | |
45 | &aaddr->addr.sas_addr.prv[13], | |
46 | &aaddr->addr.sas_addr.prv[19]); | |
656d98b0 | 47 | } |
f7d57453 | 48 | spin_unlock_irqrestore(&adev->lock, flags); |
656d98b0 | 49 | |
3c417771 | 50 | return count; |
656d98b0 RK |
51 | } |
52 | ||
48afdaea | 53 | static ssize_t atmindex_show(struct device *cdev, |
e7a46b4d DW |
54 | struct device_attribute *attr, char *buf) |
55 | { | |
56 | struct atm_dev *adev = to_atm_dev(cdev); | |
57 | ||
3c417771 | 58 | return scnprintf(buf, PAGE_SIZE, "%d\n", adev->number); |
e7a46b4d DW |
59 | } |
60 | ||
48afdaea | 61 | static ssize_t carrier_show(struct device *cdev, |
ef39592f | 62 | struct device_attribute *attr, char *buf) |
656d98b0 | 63 | { |
656d98b0 RK |
64 | struct atm_dev *adev = to_atm_dev(cdev); |
65 | ||
3c417771 C |
66 | return scnprintf(buf, PAGE_SIZE, "%d\n", |
67 | adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); | |
656d98b0 RK |
68 | } |
69 | ||
48afdaea | 70 | static ssize_t link_rate_show(struct device *cdev, |
ef39592f | 71 | struct device_attribute *attr, char *buf) |
656d98b0 | 72 | { |
656d98b0 RK |
73 | struct atm_dev *adev = to_atm_dev(cdev); |
74 | int link_rate; | |
75 | ||
76 | /* show the link rate, not the data rate */ | |
77 | switch (adev->link_rate) { | |
f0a6cb11 JP |
78 | case ATM_OC3_PCR: |
79 | link_rate = 155520000; | |
80 | break; | |
81 | case ATM_OC12_PCR: | |
82 | link_rate = 622080000; | |
83 | break; | |
84 | case ATM_25_PCR: | |
85 | link_rate = 25600000; | |
86 | break; | |
87 | default: | |
88 | link_rate = adev->link_rate * 8 * 53; | |
656d98b0 | 89 | } |
3c417771 | 90 | return scnprintf(buf, PAGE_SIZE, "%d\n", link_rate); |
656d98b0 RK |
91 | } |
92 | ||
48afdaea Y |
93 | static DEVICE_ATTR_RO(address); |
94 | static DEVICE_ATTR_RO(atmaddress); | |
95 | static DEVICE_ATTR_RO(atmindex); | |
96 | static DEVICE_ATTR_RO(carrier); | |
97 | static DEVICE_ATTR_RO(type); | |
98 | static DEVICE_ATTR_RO(link_rate); | |
ef39592f KS |
99 | |
100 | static struct device_attribute *atm_attrs[] = { | |
101 | &dev_attr_atmaddress, | |
102 | &dev_attr_address, | |
e7a46b4d | 103 | &dev_attr_atmindex, |
ef39592f KS |
104 | &dev_attr_carrier, |
105 | &dev_attr_type, | |
106 | &dev_attr_link_rate, | |
656d98b0 RK |
107 | NULL |
108 | }; | |
109 | ||
ef39592f | 110 | |
23680f0b | 111 | static int atm_uevent(const struct device *cdev, struct kobj_uevent_env *env) |
656d98b0 | 112 | { |
23680f0b | 113 | const struct atm_dev *adev; |
656d98b0 RK |
114 | |
115 | if (!cdev) | |
116 | return -ENODEV; | |
117 | ||
118 | adev = to_atm_dev(cdev); | |
656d98b0 | 119 | |
7eff2e7a | 120 | if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number)) |
656d98b0 RK |
121 | return -ENOMEM; |
122 | ||
656d98b0 RK |
123 | return 0; |
124 | } | |
125 | ||
ef39592f | 126 | static void atm_release(struct device *cdev) |
656d98b0 RK |
127 | { |
128 | struct atm_dev *adev = to_atm_dev(cdev); | |
129 | ||
130 | kfree(adev); | |
131 | } | |
132 | ||
133 | static struct class atm_class = { | |
134 | .name = "atm", | |
ef39592f KS |
135 | .dev_release = atm_release, |
136 | .dev_uevent = atm_uevent, | |
656d98b0 RK |
137 | }; |
138 | ||
d9ca676b | 139 | int atm_register_sysfs(struct atm_dev *adev, struct device *parent) |
656d98b0 | 140 | { |
ef39592f | 141 | struct device *cdev = &adev->class_dev; |
97f80bc6 | 142 | int i, j, err; |
656d98b0 RK |
143 | |
144 | cdev->class = &atm_class; | |
d9ca676b | 145 | cdev->parent = parent; |
ef39592f | 146 | dev_set_drvdata(cdev, adev); |
656d98b0 | 147 | |
fb28ad35 | 148 | dev_set_name(cdev, "%s%d", adev->type, adev->number); |
ef39592f | 149 | err = device_register(cdev); |
656d98b0 RK |
150 | if (err < 0) |
151 | return err; | |
152 | ||
97f80bc6 | 153 | for (i = 0; atm_attrs[i]; i++) { |
ef39592f | 154 | err = device_create_file(cdev, atm_attrs[i]); |
97f80bc6 JG |
155 | if (err) |
156 | goto err_out; | |
157 | } | |
656d98b0 RK |
158 | |
159 | return 0; | |
97f80bc6 JG |
160 | |
161 | err_out: | |
162 | for (j = 0; j < i; j++) | |
ef39592f KS |
163 | device_remove_file(cdev, atm_attrs[j]); |
164 | device_del(cdev); | |
97f80bc6 | 165 | return err; |
656d98b0 RK |
166 | } |
167 | ||
168 | void atm_unregister_sysfs(struct atm_dev *adev) | |
169 | { | |
ef39592f | 170 | struct device *cdev = &adev->class_dev; |
656d98b0 | 171 | |
ef39592f | 172 | device_del(cdev); |
656d98b0 RK |
173 | } |
174 | ||
175 | int __init atm_sysfs_init(void) | |
176 | { | |
177 | return class_register(&atm_class); | |
178 | } | |
179 | ||
180 | void __exit atm_sysfs_exit(void) | |
181 | { | |
182 | class_unregister(&atm_class); | |
183 | } |