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 112 /* Switch-only attributes */ 113 &dev_attr_routes.attr, 114 &dev_attr_lnext.attr, 115 &dev_attr_hopcount.attr, 116 NULL, 117 }; 118 119 static ssize_t 120 rio_read_config(struct file *filp, struct kobject *kobj, 121 struct bin_attribute *bin_attr, 122 char *buf, loff_t off, size_t count) 123 { 124 struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj)); 125 unsigned int size = 0x100; 126 loff_t init_off = off; 127 u8 *data = (u8 *) buf; 128 129 /* Several chips lock up trying to read undefined config space */ 130 if (capable(CAP_SYS_ADMIN)) 131 size = RIO_MAINT_SPACE_SZ; 132 133 if (off >= size) 134 return 0; 135 if (off + count > size) { 136 size -= off; 137 count = size; 138 } else { 139 size = count; 140 } 141 142 if ((off & 1) && size) { 143 u8 val; 144 rio_read_config_8(dev, off, &val); 145 data[off - init_off] = val; 146 off++; 147 size--; 148 } 149 150 if ((off & 3) && size > 2) { 151 u16 val; 152 rio_read_config_16(dev, off, &val); 153 data[off - init_off] = (val >> 8) & 0xff; 154 data[off - init_off + 1] = val & 0xff; 155 off += 2; 156 size -= 2; 157 } 158 159 while (size > 3) { 160 u32 val; 161 rio_read_config_32(dev, off, &val); 162 data[off - init_off] = (val >> 24) & 0xff; 163 data[off - init_off + 1] = (val >> 16) & 0xff; 164 data[off - init_off + 2] = (val >> 8) & 0xff; 165 data[off - init_off + 3] = val & 0xff; 166 off += 4; 167 size -= 4; 168 } 169 170 if (size >= 2) { 171 u16 val; 172 rio_read_config_16(dev, off, &val); 173 data[off - init_off] = (val >> 8) & 0xff; 174 data[off - init_off + 1] = val & 0xff; 175 off += 2; 176 size -= 2; 177 } 178 179 if (size > 0) { 180 u8 val; 181 rio_read_config_8(dev, off, &val); 182 data[off - init_off] = val; 183 off++; 184 --size; 185 } 186 187 return count; 188 } 189 190 static ssize_t 191 rio_write_config(struct file *filp, struct kobject *kobj, 192 struct bin_attribute *bin_attr, 193 char *buf, loff_t off, size_t count) 194 { 195 struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj)); 196 unsigned int size = count; 197 loff_t init_off = off; 198 u8 *data = (u8 *) buf; 199 200 if (off >= RIO_MAINT_SPACE_SZ) 201 return 0; 202 if (off + count > RIO_MAINT_SPACE_SZ) { 203 size = RIO_MAINT_SPACE_SZ - off; 204 count = size; 205 } 206 207 if ((off & 1) && size) { 208 rio_write_config_8(dev, off, data[off - init_off]); 209 off++; 210 size--; 211 } 212 213 if ((off & 3) && (size > 2)) { 214 u16 val = data[off - init_off + 1]; 215 val |= (u16) data[off - init_off] << 8; 216 rio_write_config_16(dev, off, val); 217 off += 2; 218 size -= 2; 219 } 220 221 while (size > 3) { 222 u32 val = data[off - init_off + 3]; 223 val |= (u32) data[off - init_off + 2] << 8; 224 val |= (u32) data[off - init_off + 1] << 16; 225 val |= (u32) data[off - init_off] << 24; 226 rio_write_config_32(dev, off, val); 227 off += 4; 228 size -= 4; 229 } 230 231 if (size >= 2) { 232 u16 val = data[off - init_off + 1]; 233 val |= (u16) data[off - init_off] << 8; 234 rio_write_config_16(dev, off, val); 235 off += 2; 236 size -= 2; 237 } 238 239 if (size) { 240 rio_write_config_8(dev, off, data[off - init_off]); 241 off++; 242 --size; 243 } 244 245 return count; 246 } 247 248 static struct bin_attribute rio_config_attr = { 249 .attr = { 250 .name = "config", 251 .mode = S_IRUGO | S_IWUSR, 252 }, 253 .size = RIO_MAINT_SPACE_SZ, 254 .read = rio_read_config, 255 .write = rio_write_config, 256 }; 257 258 static struct bin_attribute *rio_dev_bin_attrs[] = { 259 &rio_config_attr, 260 NULL, 261 }; 262 263 static umode_t rio_dev_is_attr_visible(struct kobject *kobj, 264 struct attribute *attr, int n) 265 { 266 struct rio_dev *rdev = to_rio_dev(kobj_to_dev(kobj)); 267 umode_t mode = attr->mode; 268 269 if (!(rdev->pef & RIO_PEF_SWITCH) && 270 (attr == &dev_attr_routes.attr || 271 attr == &dev_attr_lnext.attr || 272 attr == &dev_attr_hopcount.attr)) { 273 /* 274 * Hide switch-specific attributes for a non-switch device. 275 */ 276 mode = 0; 277 } 278 279 return mode; 280 } 281 282 static const struct attribute_group rio_dev_group = { 283 .attrs = rio_dev_attrs, 284 .is_visible = rio_dev_is_attr_visible, 285 .bin_attrs = rio_dev_bin_attrs, 286 }; 287 288 const struct attribute_group *rio_dev_groups[] = { 289 &rio_dev_group, 290 NULL, 291 }; 292 293 static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count) 294 { 295 long val; 296 int rc; 297 298 if (kstrtol(buf, 0, &val) < 0) 299 return -EINVAL; 300 301 if (val == RIO_MPORT_ANY) { 302 rc = rio_init_mports(); 303 goto exit; 304 } 305 306 if (val < 0 || val >= RIO_MAX_MPORTS) 307 return -EINVAL; 308 309 rc = rio_mport_scan((int)val); 310 exit: 311 if (!rc) 312 rc = count; 313 314 return rc; 315 } 316 static BUS_ATTR_WO(scan); 317 318 static struct attribute *rio_bus_attrs[] = { 319 &bus_attr_scan.attr, 320 NULL, 321 }; 322 323 static const struct attribute_group rio_bus_group = { 324 .attrs = rio_bus_attrs, 325 }; 326 327 const struct attribute_group *rio_bus_groups[] = { 328 &rio_bus_group, 329 NULL, 330 }; 331 332 static ssize_t 333 port_destid_show(struct device *dev, struct device_attribute *attr, 334 char *buf) 335 { 336 struct rio_mport *mport = to_rio_mport(dev); 337 338 if (mport) 339 return sprintf(buf, "0x%04x\n", mport->host_deviceid); 340 else 341 return -ENODEV; 342 } 343 static DEVICE_ATTR_RO(port_destid); 344 345 static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr, 346 char *buf) 347 { 348 struct rio_mport *mport = to_rio_mport(dev); 349 350 if (mport) 351 return sprintf(buf, "%u\n", mport->sys_size); 352 else 353 return -ENODEV; 354 } 355 static DEVICE_ATTR_RO(sys_size); 356 357 static struct attribute *rio_mport_attrs[] = { 358 &dev_attr_port_destid.attr, 359 &dev_attr_sys_size.attr, 360 NULL, 361 }; 362 363 static const struct attribute_group rio_mport_group = { 364 .attrs = rio_mport_attrs, 365 }; 366 367 const struct attribute_group *rio_mport_groups[] = { 368 &rio_mport_group, 369 NULL, 370 }; 371