rio-sysfs.c (7924B)
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) \ 19static ssize_t \ 20field##_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} \ 26static DEVICE_ATTR_RO(field); 27 28rio_config_attr(did, "0x%04x\n"); 29rio_config_attr(vid, "0x%04x\n"); 30rio_config_attr(device_rev, "0x%08x\n"); 31rio_config_attr(asm_did, "0x%04x\n"); 32rio_config_attr(asm_vid, "0x%04x\n"); 33rio_config_attr(asm_rev, "0x%04x\n"); 34rio_config_attr(destid, "0x%04x\n"); 35rio_config_attr(hopcount, "0x%02x\n"); 36 37static 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} 54static DEVICE_ATTR_RO(routes); 55 56static 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} 64static DEVICE_ATTR_RO(lprev); 65 66static 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} 85static DEVICE_ATTR_RO(lnext); 86 87static 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} 95static DEVICE_ATTR_RO(modalias); 96 97static 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 115static ssize_t 116rio_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 186static ssize_t 187rio_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 244static 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 254static struct bin_attribute *rio_dev_bin_attrs[] = { 255 &rio_config_attr, 256 NULL, 257}; 258 259static 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 278static 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 284const struct attribute_group *rio_dev_groups[] = { 285 &rio_dev_group, 286 NULL, 287}; 288 289static 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); 306exit: 307 if (!rc) 308 rc = count; 309 310 return rc; 311} 312static BUS_ATTR_WO(scan); 313 314static struct attribute *rio_bus_attrs[] = { 315 &bus_attr_scan.attr, 316 NULL, 317}; 318 319static const struct attribute_group rio_bus_group = { 320 .attrs = rio_bus_attrs, 321}; 322 323const struct attribute_group *rio_bus_groups[] = { 324 &rio_bus_group, 325 NULL, 326}; 327 328static ssize_t 329port_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} 339static DEVICE_ATTR_RO(port_destid); 340 341static 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} 351static DEVICE_ATTR_RO(sys_size); 352 353static struct attribute *rio_mport_attrs[] = { 354 &dev_attr_port_destid.attr, 355 &dev_attr_sys_size.attr, 356 NULL, 357}; 358 359static const struct attribute_group rio_mport_group = { 360 .attrs = rio_mport_attrs, 361}; 362 363const struct attribute_group *rio_mport_groups[] = { 364 &rio_mport_group, 365 NULL, 366};