Commit f74c91413ec6140ee0553180c5f56fdd27c22a2e

Authored by Bartlomiej Zolnierkiewicz
1 parent 50672e5d74

ide: add warm-plug support for IDE devices (take 2)

* Add 'struct class ide_port_class' ('ide_port' class) and a 'struct
  device *portdev' ('ide_port' class device) in ide_hwif_t.

* Register 'ide_port' class in ide_init() and unregister it in
  cleanup_module().

* Create ->portdev in ide_register_port () and unregister it in
  ide_unregister().

* Add "delete_devices" class device attribute for unregistering IDE devices
  on a port and "scan" one for probing+registering IDE devices on a port.

* Add ide_sysfs_register_port() helper for registering "delete_devices"
  and "scan" attributes with ->portdev.  Call it in ide_device_add_all().

* Document IDE warm-plug support in Documentation/ide/warm-plug-howto.txt.

v2:
* Convert patch from using 'struct class_device' to use 'struct device'.
  (thanks to Kay Sievers for doing it)

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>

Showing 4 changed files with 110 additions and 3 deletions Side-by-side Diff

Documentation/ide/warm-plug-howto.txt
  1 +
  2 +IDE warm-plug HOWTO
  3 +===================
  4 +
  5 +To warm-plug devices on a port 'idex':
  6 +
  7 +# echo -n "1" > /sys/class/ide_port/idex/delete_devices
  8 +
  9 +unplug old device(s) and plug new device(s)
  10 +
  11 +# echo -n "1" > /sys/class/ide_port/idex/scan
  12 +
  13 +done
drivers/ide/ide-probe.c
... ... @@ -623,7 +623,7 @@
623 623 complete(&hwif->gendev_rel_comp);
624 624 }
625 625  
626   -static void ide_register_port(ide_hwif_t *hwif)
  626 +static int ide_register_port(ide_hwif_t *hwif)
627 627 {
628 628 int ret;
629 629  
630 630  
... ... @@ -639,9 +639,23 @@
639 639 }
640 640 hwif->gendev.release = hwif_release_dev;
641 641 ret = device_register(&hwif->gendev);
642   - if (ret < 0)
  642 + if (ret < 0) {
643 643 printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
644 644 __FUNCTION__, ret);
  645 + goto out;
  646 + }
  647 +
  648 + get_device(&hwif->gendev);
  649 +
  650 + hwif->portdev = device_create(ide_port_class, &hwif->gendev,
  651 + MKDEV(0, 0), hwif->name);
  652 + if (IS_ERR(hwif->portdev)) {
  653 + ret = PTR_ERR(hwif->portdev);
  654 + device_unregister(&hwif->gendev);
  655 + }
  656 + dev_set_drvdata(hwif->portdev, hwif);
  657 +out:
  658 + return ret;
645 659 }
646 660  
647 661 /**
... ... @@ -1378,6 +1392,58 @@
1378 1392 }
1379 1393 }
1380 1394  
  1395 +static ssize_t store_delete_devices(struct device *portdev,
  1396 + struct device_attribute *attr,
  1397 + const char *buf, size_t n)
  1398 +{
  1399 + ide_hwif_t *hwif = dev_get_drvdata(portdev);
  1400 +
  1401 + if (strncmp(buf, "1", n))
  1402 + return -EINVAL;
  1403 +
  1404 + ide_port_unregister_devices(hwif);
  1405 +
  1406 + return n;
  1407 +};
  1408 +
  1409 +static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
  1410 +
  1411 +static ssize_t store_scan(struct device *portdev,
  1412 + struct device_attribute *attr,
  1413 + const char *buf, size_t n)
  1414 +{
  1415 + ide_hwif_t *hwif = dev_get_drvdata(portdev);
  1416 +
  1417 + if (strncmp(buf, "1", n))
  1418 + return -EINVAL;
  1419 +
  1420 + ide_port_unregister_devices(hwif);
  1421 + ide_port_scan(hwif);
  1422 +
  1423 + return n;
  1424 +};
  1425 +
  1426 +static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
  1427 +
  1428 +static struct device_attribute *ide_port_attrs[] = {
  1429 + &dev_attr_delete_devices,
  1430 + &dev_attr_scan,
  1431 + NULL
  1432 +};
  1433 +
  1434 +static int ide_sysfs_register_port(ide_hwif_t *hwif)
  1435 +{
  1436 + int i, rc;
  1437 +
  1438 + for (i = 0; ide_port_attrs[i]; i++) {
  1439 + rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
  1440 + if (rc)
  1441 + break;
  1442 + }
  1443 +
  1444 + return rc;
  1445 +}
  1446 +
1381 1447 int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
1382 1448 {
1383 1449 ide_hwif_t *hwif, *mate = NULL;
... ... @@ -1474,6 +1540,7 @@
1474 1540 hwif = &ide_hwifs[idx[i]];
1475 1541  
1476 1542 if (hwif->present) {
  1543 + ide_sysfs_register_port(hwif);
1477 1544 ide_proc_register_port(hwif);
1478 1545 ide_proc_port_register_devices(hwif);
1479 1546 }
... ... @@ -78,6 +78,8 @@
78 78 /* default maximum number of failures */
79 79 #define IDE_DEFAULT_MAX_FAILURES 1
80 80  
  81 +struct class *ide_port_class;
  82 +
81 83 static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
82 84 IDE2_MAJOR, IDE3_MAJOR,
83 85 IDE4_MAJOR, IDE5_MAJOR,
... ... @@ -591,6 +593,7 @@
591 593  
592 594 ide_remove_port_from_hwgroup(hwif);
593 595  
  596 + device_unregister(hwif->portdev);
594 597 device_unregister(&hwif->gendev);
595 598 wait_for_completion(&hwif->gendev_rel_comp);
596 599  
... ... @@ -1590,6 +1593,13 @@
1590 1593  
1591 1594 EXPORT_SYMBOL_GPL(ide_bus_type);
1592 1595  
  1596 +static void ide_port_class_release(struct device *portdev)
  1597 +{
  1598 + ide_hwif_t *hwif = dev_get_drvdata(portdev);
  1599 +
  1600 + put_device(&hwif->gendev);
  1601 +}
  1602 +
1593 1603 /*
1594 1604 * This is gets invoked once during initialization, to set *everything* up
1595 1605 */
1596 1606  
... ... @@ -1610,11 +1620,23 @@
1610 1620 return ret;
1611 1621 }
1612 1622  
  1623 + ide_port_class = class_create(THIS_MODULE, "ide_port");
  1624 + if (IS_ERR(ide_port_class)) {
  1625 + ret = PTR_ERR(ide_port_class);
  1626 + goto out_port_class;
  1627 + }
  1628 + ide_port_class->dev_release = ide_port_class_release;
  1629 +
1613 1630 init_ide_data();
1614 1631  
1615 1632 proc_ide_create();
1616 1633  
1617 1634 return 0;
  1635 +
  1636 +out_port_class:
  1637 + bus_unregister(&ide_bus_type);
  1638 +
  1639 + return ret;
1618 1640 }
1619 1641  
1620 1642 #ifdef MODULE
... ... @@ -1650,6 +1672,8 @@
1650 1672 ide_unregister(index, 0, 0);
1651 1673  
1652 1674 proc_ide_destroy();
  1675 +
  1676 + class_destroy(ide_port_class);
1653 1677  
1654 1678 bus_unregister(&ide_bus_type);
1655 1679 }
... ... @@ -579,7 +579,9 @@
579 579 unsigned mmio : 1; /* host uses MMIO */
580 580 unsigned straight8 : 1; /* Alan's straight 8 check */
581 581  
582   - struct device gendev;
  582 + struct device gendev;
  583 + struct device *portdev;
  584 +
583 585 struct completion gendev_rel_comp; /* To deal with device release() */
584 586  
585 587 void *hwif_data; /* extra hwif data */
... ... @@ -1275,6 +1277,7 @@
1275 1277 #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)
1276 1278  
1277 1279 extern struct bus_type ide_bus_type;
  1280 +extern struct class *ide_port_class;
1278 1281  
1279 1282 /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
1280 1283 #define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000)