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