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