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