aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-04-17 18:46:23 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-04-17 18:46:23 -0400
commitf74c91413ec6140ee0553180c5f56fdd27c22a2e (patch)
tree75ba3f7000ba290dc19b1523b12ab95dc5c7b1ea
parent50672e5d7486c9ab312432cbe180ac071f1de8e0 (diff)
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>
-rw-r--r--Documentation/ide/warm-plug-howto.txt13
-rw-r--r--drivers/ide/ide-probe.c71
-rw-r--r--drivers/ide/ide.c24
-rw-r--r--include/linux/ide.h5
4 files changed, 110 insertions, 3 deletions
diff --git a/Documentation/ide/warm-plug-howto.txt b/Documentation/ide/warm-plug-howto.txt
new file mode 100644
index 000000000000..d5885468b072
--- /dev/null
+++ b/Documentation/ide/warm-plug-howto.txt
@@ -0,0 +1,13 @@
1
2IDE warm-plug HOWTO
3===================
4
5To warm-plug devices on a port 'idex':
6
7# echo -n "1" > /sys/class/ide_port/idex/delete_devices
8
9unplug old device(s) and plug new device(s)
10
11# echo -n "1" > /sys/class/ide_port/idex/scan
12
13done
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 468c4ac4181d..510254ab3c9b 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -623,7 +623,7 @@ static void hwif_release_dev (struct device *dev)
623 complete(&hwif->gendev_rel_comp); 623 complete(&hwif->gendev_rel_comp);
624} 624}
625 625
626static void ide_register_port(ide_hwif_t *hwif) 626static int ide_register_port(ide_hwif_t *hwif)
627{ 627{
628 int ret; 628 int ret;
629 629
@@ -639,9 +639,23 @@ static void ide_register_port(ide_hwif_t *hwif)
639 } 639 }
640 hwif->gendev.release = hwif_release_dev; 640 hwif->gendev.release = hwif_release_dev;
641 ret = device_register(&hwif->gendev); 641 ret = device_register(&hwif->gendev);
642 if (ret < 0) 642 if (ret < 0) {
643 printk(KERN_WARNING "IDE: %s: device_register error: %d\n", 643 printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
644 __FUNCTION__, ret); 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);
657out:
658 return ret;
645} 659}
646 660
647/** 661/**
@@ -1378,6 +1392,58 @@ static void ide_port_cable_detect(ide_hwif_t *hwif)
1378 } 1392 }
1379} 1393}
1380 1394
1395static 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
1409static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
1410
1411static 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
1426static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
1427
1428static struct device_attribute *ide_port_attrs[] = {
1429 &dev_attr_delete_devices,
1430 &dev_attr_scan,
1431 NULL
1432};
1433
1434static 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
1381int ide_device_add_all(u8 *idx, const struct ide_port_info *d) 1447int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
1382{ 1448{
1383 ide_hwif_t *hwif, *mate = NULL; 1449 ide_hwif_t *hwif, *mate = NULL;
@@ -1474,6 +1540,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
1474 hwif = &ide_hwifs[idx[i]]; 1540 hwif = &ide_hwifs[idx[i]];
1475 1541
1476 if (hwif->present) { 1542 if (hwif->present) {
1543 ide_sysfs_register_port(hwif);
1477 ide_proc_register_port(hwif); 1544 ide_proc_register_port(hwif);
1478 ide_proc_port_register_devices(hwif); 1545 ide_proc_port_register_devices(hwif);
1479 } 1546 }
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index cb18ba8de22d..d791b1ffb586 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -78,6 +78,8 @@
78/* default maximum number of failures */ 78/* default maximum number of failures */
79#define IDE_DEFAULT_MAX_FAILURES 1 79#define IDE_DEFAULT_MAX_FAILURES 1
80 80
81struct class *ide_port_class;
82
81static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, 83static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
82 IDE2_MAJOR, IDE3_MAJOR, 84 IDE2_MAJOR, IDE3_MAJOR,
83 IDE4_MAJOR, IDE5_MAJOR, 85 IDE4_MAJOR, IDE5_MAJOR,
@@ -591,6 +593,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
591 593
592 ide_remove_port_from_hwgroup(hwif); 594 ide_remove_port_from_hwgroup(hwif);
593 595
596 device_unregister(hwif->portdev);
594 device_unregister(&hwif->gendev); 597 device_unregister(&hwif->gendev);
595 wait_for_completion(&hwif->gendev_rel_comp); 598 wait_for_completion(&hwif->gendev_rel_comp);
596 599
@@ -1590,6 +1593,13 @@ struct bus_type ide_bus_type = {
1590 1593
1591EXPORT_SYMBOL_GPL(ide_bus_type); 1594EXPORT_SYMBOL_GPL(ide_bus_type);
1592 1595
1596static 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 * This is gets invoked once during initialization, to set *everything* up 1604 * This is gets invoked once during initialization, to set *everything* up
1595 */ 1605 */
@@ -1610,11 +1620,23 @@ static int __init ide_init(void)
1610 return ret; 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 init_ide_data(); 1630 init_ide_data();
1614 1631
1615 proc_ide_create(); 1632 proc_ide_create();
1616 1633
1617 return 0; 1634 return 0;
1635
1636out_port_class:
1637 bus_unregister(&ide_bus_type);
1638
1639 return ret;
1618} 1640}
1619 1641
1620#ifdef MODULE 1642#ifdef MODULE
@@ -1651,6 +1673,8 @@ void __exit cleanup_module (void)
1651 1673
1652 proc_ide_destroy(); 1674 proc_ide_destroy();
1653 1675
1676 class_destroy(ide_port_class);
1677
1654 bus_unregister(&ide_bus_type); 1678 bus_unregister(&ide_bus_type);
1655} 1679}
1656 1680
diff --git a/include/linux/ide.h b/include/linux/ide.h
index e43570a19200..9cebf3054080 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -579,7 +579,9 @@ typedef struct hwif_s {
579 unsigned mmio : 1; /* host uses MMIO */ 579 unsigned mmio : 1; /* host uses MMIO */
580 unsigned straight8 : 1; /* Alan's straight 8 check */ 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 struct completion gendev_rel_comp; /* To deal with device release() */ 585 struct completion gendev_rel_comp; /* To deal with device release() */
584 586
585 void *hwif_data; /* extra hwif data */ 587 void *hwif_data; /* extra hwif data */
@@ -1275,6 +1277,7 @@ extern struct mutex ide_cfg_mtx;
1275#define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) 1277#define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)
1276 1278
1277extern struct bus_type ide_bus_type; 1279extern struct bus_type ide_bus_type;
1280extern struct class *ide_port_class;
1278 1281
1279/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ 1282/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
1280#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) 1283#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000)