Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+110 -3
+13
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
+69 -2
drivers/ide/ide-probe.c
··· 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 ··· 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 /** ··· 1392 1378 } 1393 1379 } 1394 1380 1381 + static ssize_t store_delete_devices(struct device *portdev, 1382 + struct device_attribute *attr, 1383 + const char *buf, size_t n) 1384 + { 1385 + ide_hwif_t *hwif = dev_get_drvdata(portdev); 1386 + 1387 + if (strncmp(buf, "1", n)) 1388 + return -EINVAL; 1389 + 1390 + ide_port_unregister_devices(hwif); 1391 + 1392 + return n; 1393 + }; 1394 + 1395 + static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); 1396 + 1397 + static ssize_t store_scan(struct device *portdev, 1398 + struct device_attribute *attr, 1399 + const char *buf, size_t n) 1400 + { 1401 + ide_hwif_t *hwif = dev_get_drvdata(portdev); 1402 + 1403 + if (strncmp(buf, "1", n)) 1404 + return -EINVAL; 1405 + 1406 + ide_port_unregister_devices(hwif); 1407 + ide_port_scan(hwif); 1408 + 1409 + return n; 1410 + }; 1411 + 1412 + static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); 1413 + 1414 + static struct device_attribute *ide_port_attrs[] = { 1415 + &dev_attr_delete_devices, 1416 + &dev_attr_scan, 1417 + NULL 1418 + }; 1419 + 1420 + static int ide_sysfs_register_port(ide_hwif_t *hwif) 1421 + { 1422 + int i, rc; 1423 + 1424 + for (i = 0; ide_port_attrs[i]; i++) { 1425 + rc = device_create_file(hwif->portdev, ide_port_attrs[i]); 1426 + if (rc) 1427 + break; 1428 + } 1429 + 1430 + return rc; 1431 + } 1432 + 1395 1433 int ide_device_add_all(u8 *idx, const struct ide_port_info *d) 1396 1434 { 1397 1435 ide_hwif_t *hwif, *mate = NULL; ··· 1540 1474 hwif = &ide_hwifs[idx[i]]; 1541 1475 1542 1476 if (hwif->present) { 1477 + ide_sysfs_register_port(hwif); 1543 1478 ide_proc_register_port(hwif); 1544 1479 ide_proc_port_register_devices(hwif); 1545 1480 }
+24
drivers/ide/ide.c
··· 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, ··· 593 591 594 592 ide_remove_port_from_hwgroup(hwif); 595 593 594 + device_unregister(hwif->portdev); 596 595 device_unregister(&hwif->gendev); 597 596 wait_for_completion(&hwif->gendev_rel_comp); 598 597 ··· 1593 1590 1594 1591 EXPORT_SYMBOL_GPL(ide_bus_type); 1595 1592 1593 + static void ide_port_class_release(struct device *portdev) 1594 + { 1595 + ide_hwif_t *hwif = dev_get_drvdata(portdev); 1596 + 1597 + put_device(&hwif->gendev); 1598 + } 1599 + 1596 1600 /* 1597 1601 * This is gets invoked once during initialization, to set *everything* up 1598 1602 */ ··· 1620 1610 return ret; 1621 1611 } 1622 1612 1613 + ide_port_class = class_create(THIS_MODULE, "ide_port"); 1614 + if (IS_ERR(ide_port_class)) { 1615 + ret = PTR_ERR(ide_port_class); 1616 + goto out_port_class; 1617 + } 1618 + ide_port_class->dev_release = ide_port_class_release; 1619 + 1623 1620 init_ide_data(); 1624 1621 1625 1622 proc_ide_create(); 1626 1623 1627 1624 return 0; 1625 + 1626 + out_port_class: 1627 + bus_unregister(&ide_bus_type); 1628 + 1629 + return ret; 1628 1630 } 1629 1631 1630 1632 #ifdef MODULE ··· 1672 1650 ide_unregister(index, 0, 0); 1673 1651 1674 1652 proc_ide_destroy(); 1653 + 1654 + class_destroy(ide_port_class); 1675 1655 1676 1656 bus_unregister(&ide_bus_type); 1677 1657 }
+4 -1
include/linux/ide.h
··· 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 */ ··· 1277 1275 #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) 1278 1276 1279 1277 extern struct bus_type ide_bus_type; 1278 + extern struct class *ide_port_class; 1280 1279 1281 1280 /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ 1282 1281 #define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000)