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