1 /* 2 * bus driver for ccwgroup 3 * 4 * Copyright IBM Corp. 2002, 2012 5 * 6 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 7 * Cornelia Huck (cornelia.huck@de.ibm.com) 8 */ 9 #include <linux/module.h> 10 #include <linux/errno.h> 11 #include <linux/slab.h> 12 #include <linux/list.h> 13 #include <linux/device.h> 14 #include <linux/init.h> 15 #include <linux/ctype.h> 16 #include <linux/dcache.h> 17 18 #include <asm/cio.h> 19 #include <asm/ccwdev.h> 20 #include <asm/ccwgroup.h> 21 22 #include "device.h" 23 24 #define CCW_BUS_ID_SIZE 10 25 26 /* In Linux 2.4, we had a channel device layer called "chandev" 27 * that did all sorts of obscure stuff for networking devices. 28 * This is another driver that serves as a replacement for just 29 * one of its functions, namely the translation of single subchannels 30 * to devices that use multiple subchannels. 31 */ 32 33 static struct bus_type ccwgroup_bus_type; 34 35 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) 36 { 37 int i; 38 char str[8]; 39 40 for (i = 0; i < gdev->count; i++) { 41 sprintf(str, "cdev%d", i); 42 sysfs_remove_link(&gdev->dev.kobj, str); 43 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device"); 44 } 45 } 46 47 /* 48 * Remove references from ccw devices to ccw group device and from 49 * ccw group device to ccw devices. 50 */ 51 static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev) 52 { 53 struct ccw_device *cdev; 54 int i; 55 56 for (i = 0; i < gdev->count; i++) { 57 cdev = gdev->cdev[i]; 58 if (!cdev) 59 continue; 60 spin_lock_irq(cdev->ccwlock); 61 dev_set_drvdata(&cdev->dev, NULL); 62 spin_unlock_irq(cdev->ccwlock); 63 gdev->cdev[i] = NULL; 64 put_device(&cdev->dev); 65 } 66 } 67 68 static int ccwgroup_set_online(struct ccwgroup_device *gdev) 69 { 70 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 71 int ret = 0; 72 73 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) 74 return -EAGAIN; 75 if (gdev->state == CCWGROUP_ONLINE) 76 goto out; 77 if (gdrv->set_online) 78 ret = gdrv->set_online(gdev); 79 if (ret) 80 goto out; 81 82 gdev->state = CCWGROUP_ONLINE; 83 out: 84 atomic_set(&gdev->onoff, 0); 85 return ret; 86 } 87 88 static int ccwgroup_set_offline(struct ccwgroup_device *gdev) 89 { 90 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 91 int ret = 0; 92 93 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) 94 return -EAGAIN; 95 if (gdev->state == CCWGROUP_OFFLINE) 96 goto out; 97 if (gdrv->set_offline) 98 ret = gdrv->set_offline(gdev); 99 if (ret) 100 goto out; 101 102 gdev->state = CCWGROUP_OFFLINE; 103 out: 104 atomic_set(&gdev->onoff, 0); 105 return ret; 106 } 107 108 static ssize_t ccwgroup_online_store(struct device *dev, 109 struct device_attribute *attr, 110 const char *buf, size_t count) 111 { 112 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 113 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); 114 unsigned long value; 115 int ret; 116 117 if (!dev->driver) 118 return -EINVAL; 119 if (!try_module_get(gdrv->driver.owner)) 120 return -EINVAL; 121 122 ret = strict_strtoul(buf, 0, &value); 123 if (ret) 124 goto out; 125 126 if (value == 1) 127 ret = ccwgroup_set_online(gdev); 128 else if (value == 0) 129 ret = ccwgroup_set_offline(gdev); 130 else 131 ret = -EINVAL; 132 out: 133 module_put(gdrv->driver.owner); 134 return (ret == 0) ? count : ret; 135 } 136 137 static ssize_t ccwgroup_online_show(struct device *dev, 138 struct device_attribute *attr, 139 char *buf) 140 { 141 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 142 int online; 143 144 online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0; 145 146 return scnprintf(buf, PAGE_SIZE, "%d\n", online); 147 } 148 149 /* 150 * Provide an 'ungroup' attribute so the user can remove group devices no 151 * longer needed or accidentially created. Saves memory :) 152 */ 153 static void ccwgroup_ungroup_callback(struct device *dev) 154 { 155 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 156 157 mutex_lock(&gdev->reg_mutex); 158 if (device_is_registered(&gdev->dev)) { 159 __ccwgroup_remove_symlinks(gdev); 160 device_unregister(dev); 161 __ccwgroup_remove_cdev_refs(gdev); 162 } 163 mutex_unlock(&gdev->reg_mutex); 164 } 165 166 static ssize_t ccwgroup_ungroup_store(struct device *dev, 167 struct device_attribute *attr, 168 const char *buf, size_t count) 169 { 170 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 171 int rc; 172 173 /* Prevent concurrent online/offline processing and ungrouping. */ 174 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) 175 return -EAGAIN; 176 if (gdev->state != CCWGROUP_OFFLINE) { 177 rc = -EINVAL; 178 goto out; 179 } 180 /* Note that we cannot unregister the device from one of its 181 * attribute methods, so we have to use this roundabout approach. 182 */ 183 rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); 184 out: 185 if (rc) { 186 if (rc != -EAGAIN) 187 /* Release onoff "lock" when ungrouping failed. */ 188 atomic_set(&gdev->onoff, 0); 189 return rc; 190 } 191 return count; 192 } 193 static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store); 194 static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store); 195 196 static struct attribute *ccwgroup_attrs[] = { 197 &dev_attr_online.attr, 198 &dev_attr_ungroup.attr, 199 NULL, 200 }; 201 static struct attribute_group ccwgroup_attr_group = { 202 .attrs = ccwgroup_attrs, 203 }; 204 static const struct attribute_group *ccwgroup_attr_groups[] = { 205 &ccwgroup_attr_group, 206 NULL, 207 }; 208 209 static void ccwgroup_release(struct device *dev) 210 { 211 kfree(to_ccwgroupdev(dev)); 212 } 213 214 static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) 215 { 216 char str[8]; 217 int i, rc; 218 219 for (i = 0; i < gdev->count; i++) { 220 rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, 221 &gdev->dev.kobj, "group_device"); 222 if (rc) { 223 for (--i; i >= 0; i--) 224 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, 225 "group_device"); 226 return rc; 227 } 228 } 229 for (i = 0; i < gdev->count; i++) { 230 sprintf(str, "cdev%d", i); 231 rc = sysfs_create_link(&gdev->dev.kobj, 232 &gdev->cdev[i]->dev.kobj, str); 233 if (rc) { 234 for (--i; i >= 0; i--) { 235 sprintf(str, "cdev%d", i); 236 sysfs_remove_link(&gdev->dev.kobj, str); 237 } 238 for (i = 0; i < gdev->count; i++) 239 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, 240 "group_device"); 241 return rc; 242 } 243 } 244 return 0; 245 } 246 247 static int __get_next_id(const char **buf, struct ccw_dev_id *id) 248 { 249 unsigned int cssid, ssid, devno; 250 int ret = 0, len; 251 char *start, *end; 252 253 start = (char *)*buf; 254 end = strchr(start, ','); 255 if (!end) { 256 /* Last entry. Strip trailing newline, if applicable. */ 257 end = strchr(start, '\n'); 258 if (end) 259 *end = '\0'; 260 len = strlen(start) + 1; 261 } else { 262 len = end - start + 1; 263 end++; 264 } 265 if (len <= CCW_BUS_ID_SIZE) { 266 if (sscanf(start, "%2x.%1x.%04x", &cssid, &ssid, &devno) != 3) 267 ret = -EINVAL; 268 } else 269 ret = -EINVAL; 270 271 if (!ret) { 272 id->ssid = ssid; 273 id->devno = devno; 274 } 275 *buf = end; 276 return ret; 277 } 278 279 /** 280 * ccwgroup_create_dev() - create and register a ccw group device 281 * @parent: parent device for the new device 282 * @gdrv: driver for the new group device 283 * @num_devices: number of slave devices 284 * @buf: buffer containing comma separated bus ids of slave devices 285 * 286 * Create and register a new ccw group device as a child of @parent. Slave 287 * devices are obtained from the list of bus ids given in @buf. 288 * Returns: 289 * %0 on success and an error code on failure. 290 * Context: 291 * non-atomic 292 */ 293 int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, 294 int num_devices, const char *buf) 295 { 296 struct ccwgroup_device *gdev; 297 struct ccw_dev_id dev_id; 298 int rc, i; 299 300 gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), 301 GFP_KERNEL); 302 if (!gdev) 303 return -ENOMEM; 304 305 atomic_set(&gdev->onoff, 0); 306 mutex_init(&gdev->reg_mutex); 307 mutex_lock(&gdev->reg_mutex); 308 gdev->count = num_devices; 309 gdev->dev.bus = &ccwgroup_bus_type; 310 gdev->dev.parent = parent; 311 gdev->dev.release = ccwgroup_release; 312 device_initialize(&gdev->dev); 313 314 for (i = 0; i < num_devices && buf; i++) { 315 rc = __get_next_id(&buf, &dev_id); 316 if (rc != 0) 317 goto error; 318 gdev->cdev[i] = get_ccwdev_by_dev_id(&dev_id); 319 /* 320 * All devices have to be of the same type in 321 * order to be grouped. 322 */ 323 if (!gdev->cdev[i] || !gdev->cdev[i]->drv || 324 gdev->cdev[i]->drv != gdev->cdev[0]->drv || 325 gdev->cdev[i]->id.driver_info != 326 gdev->cdev[0]->id.driver_info) { 327 rc = -EINVAL; 328 goto error; 329 } 330 /* Don't allow a device to belong to more than one group. */ 331 spin_lock_irq(gdev->cdev[i]->ccwlock); 332 if (dev_get_drvdata(&gdev->cdev[i]->dev)) { 333 spin_unlock_irq(gdev->cdev[i]->ccwlock); 334 rc = -EINVAL; 335 goto error; 336 } 337 dev_set_drvdata(&gdev->cdev[i]->dev, gdev); 338 spin_unlock_irq(gdev->cdev[i]->ccwlock); 339 } 340 /* Check for sufficient number of bus ids. */ 341 if (i < num_devices) { 342 rc = -EINVAL; 343 goto error; 344 } 345 /* Check for trailing stuff. */ 346 if (i == num_devices && strlen(buf) > 0) { 347 rc = -EINVAL; 348 goto error; 349 } 350 351 dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); 352 gdev->dev.groups = ccwgroup_attr_groups; 353 354 if (gdrv) { 355 gdev->dev.driver = &gdrv->driver; 356 rc = gdrv->setup ? gdrv->setup(gdev) : 0; 357 if (rc) 358 goto error; 359 } 360 rc = device_add(&gdev->dev); 361 if (rc) 362 goto error; 363 rc = __ccwgroup_create_symlinks(gdev); 364 if (rc) { 365 device_del(&gdev->dev); 366 goto error; 367 } 368 mutex_unlock(&gdev->reg_mutex); 369 return 0; 370 error: 371 for (i = 0; i < num_devices; i++) 372 if (gdev->cdev[i]) { 373 spin_lock_irq(gdev->cdev[i]->ccwlock); 374 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 375 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 376 spin_unlock_irq(gdev->cdev[i]->ccwlock); 377 put_device(&gdev->cdev[i]->dev); 378 gdev->cdev[i] = NULL; 379 } 380 mutex_unlock(&gdev->reg_mutex); 381 put_device(&gdev->dev); 382 return rc; 383 } 384 EXPORT_SYMBOL(ccwgroup_create_dev); 385 386 static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, 387 void *data) 388 { 389 struct device *dev = data; 390 391 if (action == BUS_NOTIFY_UNBIND_DRIVER) 392 device_schedule_callback(dev, ccwgroup_ungroup_callback); 393 394 return NOTIFY_OK; 395 } 396 397 static struct notifier_block ccwgroup_nb = { 398 .notifier_call = ccwgroup_notifier 399 }; 400 401 static int __init init_ccwgroup(void) 402 { 403 int ret; 404 405 ret = bus_register(&ccwgroup_bus_type); 406 if (ret) 407 return ret; 408 409 ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb); 410 if (ret) 411 bus_unregister(&ccwgroup_bus_type); 412 413 return ret; 414 } 415 416 static void __exit cleanup_ccwgroup(void) 417 { 418 bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb); 419 bus_unregister(&ccwgroup_bus_type); 420 } 421 422 module_init(init_ccwgroup); 423 module_exit(cleanup_ccwgroup); 424 425 /************************** driver stuff ******************************/ 426 427 static int ccwgroup_remove(struct device *dev) 428 { 429 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 430 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); 431 432 if (!dev->driver) 433 return 0; 434 if (gdrv->remove) 435 gdrv->remove(gdev); 436 437 return 0; 438 } 439 440 static void ccwgroup_shutdown(struct device *dev) 441 { 442 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 443 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); 444 445 if (!dev->driver) 446 return; 447 if (gdrv->shutdown) 448 gdrv->shutdown(gdev); 449 } 450 451 static int ccwgroup_pm_prepare(struct device *dev) 452 { 453 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 454 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 455 456 /* Fail while device is being set online/offline. */ 457 if (atomic_read(&gdev->onoff)) 458 return -EAGAIN; 459 460 if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) 461 return 0; 462 463 return gdrv->prepare ? gdrv->prepare(gdev) : 0; 464 } 465 466 static void ccwgroup_pm_complete(struct device *dev) 467 { 468 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 469 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); 470 471 if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) 472 return; 473 474 if (gdrv->complete) 475 gdrv->complete(gdev); 476 } 477 478 static int ccwgroup_pm_freeze(struct device *dev) 479 { 480 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 481 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 482 483 if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) 484 return 0; 485 486 return gdrv->freeze ? gdrv->freeze(gdev) : 0; 487 } 488 489 static int ccwgroup_pm_thaw(struct device *dev) 490 { 491 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 492 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 493 494 if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) 495 return 0; 496 497 return gdrv->thaw ? gdrv->thaw(gdev) : 0; 498 } 499 500 static int ccwgroup_pm_restore(struct device *dev) 501 { 502 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 503 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); 504 505 if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) 506 return 0; 507 508 return gdrv->restore ? gdrv->restore(gdev) : 0; 509 } 510 511 static const struct dev_pm_ops ccwgroup_pm_ops = { 512 .prepare = ccwgroup_pm_prepare, 513 .complete = ccwgroup_pm_complete, 514 .freeze = ccwgroup_pm_freeze, 515 .thaw = ccwgroup_pm_thaw, 516 .restore = ccwgroup_pm_restore, 517 }; 518 519 static struct bus_type ccwgroup_bus_type = { 520 .name = "ccwgroup", 521 .remove = ccwgroup_remove, 522 .shutdown = ccwgroup_shutdown, 523 .pm = &ccwgroup_pm_ops, 524 }; 525 526 /** 527 * ccwgroup_driver_register() - register a ccw group driver 528 * @cdriver: driver to be registered 529 * 530 * This function is mainly a wrapper around driver_register(). 531 */ 532 int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) 533 { 534 /* register our new driver with the core */ 535 cdriver->driver.bus = &ccwgroup_bus_type; 536 537 return driver_register(&cdriver->driver); 538 } 539 EXPORT_SYMBOL(ccwgroup_driver_register); 540 541 static int __ccwgroup_match_all(struct device *dev, void *data) 542 { 543 return 1; 544 } 545 546 /** 547 * ccwgroup_driver_unregister() - deregister a ccw group driver 548 * @cdriver: driver to be deregistered 549 * 550 * This function is mainly a wrapper around driver_unregister(). 551 */ 552 void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) 553 { 554 struct device *dev; 555 556 /* We don't want ccwgroup devices to live longer than their driver. */ 557 while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, 558 __ccwgroup_match_all))) { 559 struct ccwgroup_device *gdev = to_ccwgroupdev(dev); 560 561 mutex_lock(&gdev->reg_mutex); 562 __ccwgroup_remove_symlinks(gdev); 563 device_unregister(dev); 564 __ccwgroup_remove_cdev_refs(gdev); 565 mutex_unlock(&gdev->reg_mutex); 566 put_device(dev); 567 } 568 driver_unregister(&cdriver->driver); 569 } 570 EXPORT_SYMBOL(ccwgroup_driver_unregister); 571 572 /** 573 * ccwgroup_probe_ccwdev() - probe function for slave devices 574 * @cdev: ccw device to be probed 575 * 576 * This is a dummy probe function for ccw devices that are slave devices in 577 * a ccw group device. 578 * Returns: 579 * always %0 580 */ 581 int ccwgroup_probe_ccwdev(struct ccw_device *cdev) 582 { 583 return 0; 584 } 585 EXPORT_SYMBOL(ccwgroup_probe_ccwdev); 586 587 /** 588 * ccwgroup_remove_ccwdev() - remove function for slave devices 589 * @cdev: ccw device to be removed 590 * 591 * This is a remove function for ccw devices that are slave devices in a ccw 592 * group device. It sets the ccw device offline and also deregisters the 593 * embedding ccw group device. 594 */ 595 void ccwgroup_remove_ccwdev(struct ccw_device *cdev) 596 { 597 struct ccwgroup_device *gdev; 598 599 /* Ignore offlining errors, device is gone anyway. */ 600 ccw_device_set_offline(cdev); 601 /* If one of its devices is gone, the whole group is done for. */ 602 spin_lock_irq(cdev->ccwlock); 603 gdev = dev_get_drvdata(&cdev->dev); 604 if (!gdev) { 605 spin_unlock_irq(cdev->ccwlock); 606 return; 607 } 608 /* Get ccwgroup device reference for local processing. */ 609 get_device(&gdev->dev); 610 spin_unlock_irq(cdev->ccwlock); 611 /* Unregister group device. */ 612 mutex_lock(&gdev->reg_mutex); 613 if (device_is_registered(&gdev->dev)) { 614 __ccwgroup_remove_symlinks(gdev); 615 device_unregister(&gdev->dev); 616 __ccwgroup_remove_cdev_refs(gdev); 617 } 618 mutex_unlock(&gdev->reg_mutex); 619 /* Release ccwgroup device reference for local processing. */ 620 put_device(&gdev->dev); 621 } 622 EXPORT_SYMBOL(ccwgroup_remove_ccwdev); 623 MODULE_LICENSE("GPL"); 624