GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / rapidio / rio-sysfs.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * RapidIO sysfs attributes and support
4  *
5  * Copyright 2005 MontaVista Software, Inc.
6  * Matt Porter <mporter@kernel.crashing.org>
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/rio.h>
11 #include <linux/rio_drv.h>
12 #include <linux/stat.h>
13 #include <linux/capability.h>
14
15 #include "rio.h"
16
17 /* Sysfs support */
18 #define rio_config_attr(field, format_string)                                   \
19 static ssize_t                                                          \
20 field##_show(struct device *dev, struct device_attribute *attr, char *buf)                      \
21 {                                                                       \
22         struct rio_dev *rdev = to_rio_dev(dev);                         \
23                                                                         \
24         return sprintf(buf, format_string, rdev->field);                \
25 }                                                                       \
26 static DEVICE_ATTR_RO(field);
27
28 rio_config_attr(did, "0x%04x\n");
29 rio_config_attr(vid, "0x%04x\n");
30 rio_config_attr(device_rev, "0x%08x\n");
31 rio_config_attr(asm_did, "0x%04x\n");
32 rio_config_attr(asm_vid, "0x%04x\n");
33 rio_config_attr(asm_rev, "0x%04x\n");
34 rio_config_attr(destid, "0x%04x\n");
35 rio_config_attr(hopcount, "0x%02x\n");
36
37 static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
38 {
39         struct rio_dev *rdev = to_rio_dev(dev);
40         char *str = buf;
41         int i;
42
43         for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
44                         i++) {
45                 if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
46                         continue;
47                 str +=
48                     sprintf(str, "%04x %02x\n", i,
49                             rdev->rswitch->route_table[i]);
50         }
51
52         return (str - buf);
53 }
54 static DEVICE_ATTR_RO(routes);
55
56 static ssize_t lprev_show(struct device *dev,
57                           struct device_attribute *attr, char *buf)
58 {
59         struct rio_dev *rdev = to_rio_dev(dev);
60
61         return sprintf(buf, "%s\n",
62                         (rdev->prev) ? rio_name(rdev->prev) : "root");
63 }
64 static DEVICE_ATTR_RO(lprev);
65
66 static ssize_t lnext_show(struct device *dev,
67                           struct device_attribute *attr, char *buf)
68 {
69         struct rio_dev *rdev = to_rio_dev(dev);
70         char *str = buf;
71         int i;
72
73         if (rdev->pef & RIO_PEF_SWITCH) {
74                 for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) {
75                         if (rdev->rswitch->nextdev[i])
76                                 str += sprintf(str, "%s\n",
77                                         rio_name(rdev->rswitch->nextdev[i]));
78                         else
79                                 str += sprintf(str, "null\n");
80                 }
81         }
82
83         return str - buf;
84 }
85 static DEVICE_ATTR_RO(lnext);
86
87 static ssize_t modalias_show(struct device *dev,
88                              struct device_attribute *attr, char *buf)
89 {
90         struct rio_dev *rdev = to_rio_dev(dev);
91
92         return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
93                        rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
94 }
95 static DEVICE_ATTR_RO(modalias);
96
97 static struct attribute *rio_dev_attrs[] = {
98         &dev_attr_did.attr,
99         &dev_attr_vid.attr,
100         &dev_attr_device_rev.attr,
101         &dev_attr_asm_did.attr,
102         &dev_attr_asm_vid.attr,
103         &dev_attr_asm_rev.attr,
104         &dev_attr_lprev.attr,
105         &dev_attr_destid.attr,
106         &dev_attr_modalias.attr,
107
108         /* Switch-only attributes */
109         &dev_attr_routes.attr,
110         &dev_attr_lnext.attr,
111         &dev_attr_hopcount.attr,
112         NULL,
113 };
114
115 static ssize_t
116 rio_read_config(struct file *filp, struct kobject *kobj,
117                 struct bin_attribute *bin_attr,
118                 char *buf, loff_t off, size_t count)
119 {
120         struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
121         unsigned int size = 0x100;
122         loff_t init_off = off;
123         u8 *data = (u8 *) buf;
124
125         /* Several chips lock up trying to read undefined config space */
126         if (capable(CAP_SYS_ADMIN))
127                 size = RIO_MAINT_SPACE_SZ;
128
129         if (off >= size)
130                 return 0;
131         if (off + count > size) {
132                 size -= off;
133                 count = size;
134         } else {
135                 size = count;
136         }
137
138         if ((off & 1) && size) {
139                 u8 val;
140                 rio_read_config_8(dev, off, &val);
141                 data[off - init_off] = val;
142                 off++;
143                 size--;
144         }
145
146         if ((off & 3) && size > 2) {
147                 u16 val;
148                 rio_read_config_16(dev, off, &val);
149                 data[off - init_off] = (val >> 8) & 0xff;
150                 data[off - init_off + 1] = val & 0xff;
151                 off += 2;
152                 size -= 2;
153         }
154
155         while (size > 3) {
156                 u32 val;
157                 rio_read_config_32(dev, off, &val);
158                 data[off - init_off] = (val >> 24) & 0xff;
159                 data[off - init_off + 1] = (val >> 16) & 0xff;
160                 data[off - init_off + 2] = (val >> 8) & 0xff;
161                 data[off - init_off + 3] = val & 0xff;
162                 off += 4;
163                 size -= 4;
164         }
165
166         if (size >= 2) {
167                 u16 val;
168                 rio_read_config_16(dev, off, &val);
169                 data[off - init_off] = (val >> 8) & 0xff;
170                 data[off - init_off + 1] = val & 0xff;
171                 off += 2;
172                 size -= 2;
173         }
174
175         if (size > 0) {
176                 u8 val;
177                 rio_read_config_8(dev, off, &val);
178                 data[off - init_off] = val;
179                 off++;
180                 --size;
181         }
182
183         return count;
184 }
185
186 static ssize_t
187 rio_write_config(struct file *filp, struct kobject *kobj,
188                  struct bin_attribute *bin_attr,
189                  char *buf, loff_t off, size_t count)
190 {
191         struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
192         unsigned int size = count;
193         loff_t init_off = off;
194         u8 *data = (u8 *) buf;
195
196         if (off >= RIO_MAINT_SPACE_SZ)
197                 return 0;
198         if (off + count > RIO_MAINT_SPACE_SZ) {
199                 size = RIO_MAINT_SPACE_SZ - off;
200                 count = size;
201         }
202
203         if ((off & 1) && size) {
204                 rio_write_config_8(dev, off, data[off - init_off]);
205                 off++;
206                 size--;
207         }
208
209         if ((off & 3) && (size > 2)) {
210                 u16 val = data[off - init_off + 1];
211                 val |= (u16) data[off - init_off] << 8;
212                 rio_write_config_16(dev, off, val);
213                 off += 2;
214                 size -= 2;
215         }
216
217         while (size > 3) {
218                 u32 val = data[off - init_off + 3];
219                 val |= (u32) data[off - init_off + 2] << 8;
220                 val |= (u32) data[off - init_off + 1] << 16;
221                 val |= (u32) data[off - init_off] << 24;
222                 rio_write_config_32(dev, off, val);
223                 off += 4;
224                 size -= 4;
225         }
226
227         if (size >= 2) {
228                 u16 val = data[off - init_off + 1];
229                 val |= (u16) data[off - init_off] << 8;
230                 rio_write_config_16(dev, off, val);
231                 off += 2;
232                 size -= 2;
233         }
234
235         if (size) {
236                 rio_write_config_8(dev, off, data[off - init_off]);
237                 off++;
238                 --size;
239         }
240
241         return count;
242 }
243
244 static struct bin_attribute rio_config_attr = {
245         .attr = {
246                  .name = "config",
247                  .mode = S_IRUGO | S_IWUSR,
248                  },
249         .size = RIO_MAINT_SPACE_SZ,
250         .read = rio_read_config,
251         .write = rio_write_config,
252 };
253
254 static struct bin_attribute *rio_dev_bin_attrs[] = {
255         &rio_config_attr,
256         NULL,
257 };
258
259 static umode_t rio_dev_is_attr_visible(struct kobject *kobj,
260                                        struct attribute *attr, int n)
261 {
262         struct rio_dev *rdev = to_rio_dev(kobj_to_dev(kobj));
263         umode_t mode = attr->mode;
264
265         if (!(rdev->pef & RIO_PEF_SWITCH) &&
266             (attr == &dev_attr_routes.attr ||
267              attr == &dev_attr_lnext.attr ||
268              attr == &dev_attr_hopcount.attr)) {
269                 /*
270                  * Hide switch-specific attributes for a non-switch device.
271                  */
272                 mode = 0;
273         }
274
275         return mode;
276 }
277
278 static const struct attribute_group rio_dev_group = {
279         .attrs          = rio_dev_attrs,
280         .is_visible     = rio_dev_is_attr_visible,
281         .bin_attrs      = rio_dev_bin_attrs,
282 };
283
284 const struct attribute_group *rio_dev_groups[] = {
285         &rio_dev_group,
286         NULL,
287 };
288
289 static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count)
290 {
291         long val;
292         int rc;
293
294         if (kstrtol(buf, 0, &val) < 0)
295                 return -EINVAL;
296
297         if (val == RIO_MPORT_ANY) {
298                 rc = rio_init_mports();
299                 goto exit;
300         }
301
302         if (val < 0 || val >= RIO_MAX_MPORTS)
303                 return -EINVAL;
304
305         rc = rio_mport_scan((int)val);
306 exit:
307         if (!rc)
308                 rc = count;
309
310         return rc;
311 }
312 static BUS_ATTR_WO(scan);
313
314 static struct attribute *rio_bus_attrs[] = {
315         &bus_attr_scan.attr,
316         NULL,
317 };
318
319 static const struct attribute_group rio_bus_group = {
320         .attrs = rio_bus_attrs,
321 };
322
323 const struct attribute_group *rio_bus_groups[] = {
324         &rio_bus_group,
325         NULL,
326 };
327
328 static ssize_t
329 port_destid_show(struct device *dev, struct device_attribute *attr,
330                  char *buf)
331 {
332         struct rio_mport *mport = to_rio_mport(dev);
333
334         if (mport)
335                 return sprintf(buf, "0x%04x\n", mport->host_deviceid);
336         else
337                 return -ENODEV;
338 }
339 static DEVICE_ATTR_RO(port_destid);
340
341 static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
342                            char *buf)
343 {
344         struct rio_mport *mport = to_rio_mport(dev);
345
346         if (mport)
347                 return sprintf(buf, "%u\n", mport->sys_size);
348         else
349                 return -ENODEV;
350 }
351 static DEVICE_ATTR_RO(sys_size);
352
353 static struct attribute *rio_mport_attrs[] = {
354         &dev_attr_port_destid.attr,
355         &dev_attr_sys_size.attr,
356         NULL,
357 };
358
359 static const struct attribute_group rio_mport_group = {
360         .attrs = rio_mport_attrs,
361 };
362
363 const struct attribute_group *rio_mport_groups[] = {
364         &rio_mport_group,
365         NULL,
366 };