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