diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /block/genhd.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'block/genhd.c')
-rw-r--r-- | block/genhd.c | 104 |
1 files changed, 56 insertions, 48 deletions
diff --git a/block/genhd.c b/block/genhd.c index 9a289d7c84b..d3834710b95 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/kmod.h> | 16 | #include <linux/kmod.h> |
17 | #include <linux/kobj_map.h> | 17 | #include <linux/kobj_map.h> |
18 | #include <linux/buffer_head.h> | ||
18 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
19 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
20 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
@@ -35,7 +36,6 @@ static DEFINE_IDR(ext_devt_idr); | |||
35 | 36 | ||
36 | static struct device_type disk_type; | 37 | static struct device_type disk_type; |
37 | 38 | ||
38 | static void disk_alloc_events(struct gendisk *disk); | ||
39 | static void disk_add_events(struct gendisk *disk); | 39 | static void disk_add_events(struct gendisk *disk); |
40 | static void disk_del_events(struct gendisk *disk); | 40 | static void disk_del_events(struct gendisk *disk); |
41 | static void disk_release_events(struct gendisk *disk); | 41 | static void disk_release_events(struct gendisk *disk); |
@@ -154,7 +154,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) | |||
154 | part = rcu_dereference(ptbl->part[piter->idx]); | 154 | part = rcu_dereference(ptbl->part[piter->idx]); |
155 | if (!part) | 155 | if (!part) |
156 | continue; | 156 | continue; |
157 | if (!part_nr_sects_read(part) && | 157 | if (!part->nr_sects && |
158 | !(piter->flags & DISK_PITER_INCL_EMPTY) && | 158 | !(piter->flags & DISK_PITER_INCL_EMPTY) && |
159 | !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && | 159 | !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && |
160 | piter->idx == 0)) | 160 | piter->idx == 0)) |
@@ -191,7 +191,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit); | |||
191 | static inline int sector_in_part(struct hd_struct *part, sector_t sector) | 191 | static inline int sector_in_part(struct hd_struct *part, sector_t sector) |
192 | { | 192 | { |
193 | return part->start_sect <= sector && | 193 | return part->start_sect <= sector && |
194 | sector < part->start_sect + part_nr_sects_read(part); | 194 | sector < part->start_sect + part->nr_sects; |
195 | } | 195 | } |
196 | 196 | ||
197 | /** | 197 | /** |
@@ -507,7 +507,7 @@ static int exact_lock(dev_t devt, void *data) | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static void register_disk(struct gendisk *disk) | 510 | void register_disk(struct gendisk *disk) |
511 | { | 511 | { |
512 | struct device *ddev = disk_to_dev(disk); | 512 | struct device *ddev = disk_to_dev(disk); |
513 | struct block_device *bdev; | 513 | struct block_device *bdev; |
@@ -536,7 +536,7 @@ static void register_disk(struct gendisk *disk) | |||
536 | disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); | 536 | disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); |
537 | 537 | ||
538 | /* No minors to use for partitions */ | 538 | /* No minors to use for partitions */ |
539 | if (!disk_part_scan_enabled(disk)) | 539 | if (!disk_partitionable(disk)) |
540 | goto exit; | 540 | goto exit; |
541 | 541 | ||
542 | /* No such device (e.g., media were just removed) */ | 542 | /* No such device (e.g., media were just removed) */ |
@@ -602,8 +602,6 @@ void add_disk(struct gendisk *disk) | |||
602 | disk->major = MAJOR(devt); | 602 | disk->major = MAJOR(devt); |
603 | disk->first_minor = MINOR(devt); | 603 | disk->first_minor = MINOR(devt); |
604 | 604 | ||
605 | disk_alloc_events(disk); | ||
606 | |||
607 | /* Register BDI before referencing it from bdev */ | 605 | /* Register BDI before referencing it from bdev */ |
608 | bdi = &disk->queue->backing_dev_info; | 606 | bdi = &disk->queue->backing_dev_info; |
609 | bdi_register_dev(bdi, disk_devt(disk)); | 607 | bdi_register_dev(bdi, disk_devt(disk)); |
@@ -617,7 +615,7 @@ void add_disk(struct gendisk *disk) | |||
617 | * Take an extra ref on queue which will be put on disk_release() | 615 | * Take an extra ref on queue which will be put on disk_release() |
618 | * so that it sticks around as long as @disk is there. | 616 | * so that it sticks around as long as @disk is there. |
619 | */ | 617 | */ |
620 | WARN_ON_ONCE(!blk_get_queue(disk->queue)); | 618 | WARN_ON_ONCE(blk_get_queue(disk->queue)); |
621 | 619 | ||
622 | retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj, | 620 | retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj, |
623 | "bdi"); | 621 | "bdi"); |
@@ -743,6 +741,7 @@ void __init printk_all_partitions(void) | |||
743 | struct hd_struct *part; | 741 | struct hd_struct *part; |
744 | char name_buf[BDEVNAME_SIZE]; | 742 | char name_buf[BDEVNAME_SIZE]; |
745 | char devt_buf[BDEVT_SIZE]; | 743 | char devt_buf[BDEVT_SIZE]; |
744 | u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1]; | ||
746 | 745 | ||
747 | /* | 746 | /* |
748 | * Don't show empty devices or things that have been | 747 | * Don't show empty devices or things that have been |
@@ -761,11 +760,14 @@ void __init printk_all_partitions(void) | |||
761 | while ((part = disk_part_iter_next(&piter))) { | 760 | while ((part = disk_part_iter_next(&piter))) { |
762 | bool is_part0 = part == &disk->part0; | 761 | bool is_part0 = part == &disk->part0; |
763 | 762 | ||
763 | uuid[0] = 0; | ||
764 | if (part->info) | ||
765 | part_unpack_uuid(part->info->uuid, uuid); | ||
766 | |||
764 | printk("%s%s %10llu %s %s", is_part0 ? "" : " ", | 767 | printk("%s%s %10llu %s %s", is_part0 ? "" : " ", |
765 | bdevt_str(part_devt(part), devt_buf), | 768 | bdevt_str(part_devt(part), devt_buf), |
766 | (unsigned long long)part_nr_sects_read(part) >> 1 | 769 | (unsigned long long)part->nr_sects >> 1, |
767 | , disk_name(disk, part->partno, name_buf), | 770 | disk_name(disk, part->partno, name_buf), uuid); |
768 | part->info ? part->info->uuid : ""); | ||
769 | if (is_part0) { | 771 | if (is_part0) { |
770 | if (disk->driverfs_dev != NULL && | 772 | if (disk->driverfs_dev != NULL && |
771 | disk->driverfs_dev->driver != NULL) | 773 | disk->driverfs_dev->driver != NULL) |
@@ -829,7 +831,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v) | |||
829 | 831 | ||
830 | static void *show_partition_start(struct seq_file *seqf, loff_t *pos) | 832 | static void *show_partition_start(struct seq_file *seqf, loff_t *pos) |
831 | { | 833 | { |
832 | void *p; | 834 | static void *p; |
833 | 835 | ||
834 | p = disk_seqf_start(seqf, pos); | 836 | p = disk_seqf_start(seqf, pos); |
835 | if (!IS_ERR_OR_NULL(p) && !*pos) | 837 | if (!IS_ERR_OR_NULL(p) && !*pos) |
@@ -845,7 +847,7 @@ static int show_partition(struct seq_file *seqf, void *v) | |||
845 | char buf[BDEVNAME_SIZE]; | 847 | char buf[BDEVNAME_SIZE]; |
846 | 848 | ||
847 | /* Don't show non-partitionable removeable devices or empty devices */ | 849 | /* Don't show non-partitionable removeable devices or empty devices */ |
848 | if (!get_capacity(sgp) || (!disk_max_parts(sgp) && | 850 | if (!get_capacity(sgp) || (!disk_partitionable(sgp) && |
849 | (sgp->flags & GENHD_FL_REMOVABLE))) | 851 | (sgp->flags & GENHD_FL_REMOVABLE))) |
850 | return 0; | 852 | return 0; |
851 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) | 853 | if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) |
@@ -856,7 +858,7 @@ static int show_partition(struct seq_file *seqf, void *v) | |||
856 | while ((part = disk_part_iter_next(&piter))) | 858 | while ((part = disk_part_iter_next(&piter))) |
857 | seq_printf(seqf, "%4d %7d %10llu %s\n", | 859 | seq_printf(seqf, "%4d %7d %10llu %s\n", |
858 | MAJOR(part_devt(part)), MINOR(part_devt(part)), | 860 | MAJOR(part_devt(part)), MINOR(part_devt(part)), |
859 | (unsigned long long)part_nr_sects_read(part) >> 1, | 861 | (unsigned long long)part->nr_sects >> 1, |
860 | disk_name(sgp, part->partno, buf)); | 862 | disk_name(sgp, part->partno, buf)); |
861 | disk_part_iter_exit(&piter); | 863 | disk_part_iter_exit(&piter); |
862 | 864 | ||
@@ -1103,11 +1105,27 @@ static void disk_release(struct device *dev) | |||
1103 | blk_put_queue(disk->queue); | 1105 | blk_put_queue(disk->queue); |
1104 | kfree(disk); | 1106 | kfree(disk); |
1105 | } | 1107 | } |
1108 | |||
1109 | static int disk_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
1110 | { | ||
1111 | struct gendisk *disk = dev_to_disk(dev); | ||
1112 | struct disk_part_iter piter; | ||
1113 | struct hd_struct *part; | ||
1114 | int cnt = 0; | ||
1115 | |||
1116 | disk_part_iter_init(&piter, disk, 0); | ||
1117 | while((part = disk_part_iter_next(&piter))) | ||
1118 | cnt++; | ||
1119 | disk_part_iter_exit(&piter); | ||
1120 | add_uevent_var(env, "NPARTS=%u", cnt); | ||
1121 | return 0; | ||
1122 | } | ||
1123 | |||
1106 | struct class block_class = { | 1124 | struct class block_class = { |
1107 | .name = "block", | 1125 | .name = "block", |
1108 | }; | 1126 | }; |
1109 | 1127 | ||
1110 | static char *block_devnode(struct device *dev, umode_t *mode) | 1128 | static char *block_devnode(struct device *dev, mode_t *mode) |
1111 | { | 1129 | { |
1112 | struct gendisk *disk = dev_to_disk(dev); | 1130 | struct gendisk *disk = dev_to_disk(dev); |
1113 | 1131 | ||
@@ -1121,6 +1139,7 @@ static struct device_type disk_type = { | |||
1121 | .groups = disk_attr_groups, | 1139 | .groups = disk_attr_groups, |
1122 | .release = disk_release, | 1140 | .release = disk_release, |
1123 | .devnode = block_devnode, | 1141 | .devnode = block_devnode, |
1142 | .uevent = disk_uevent, | ||
1124 | }; | 1143 | }; |
1125 | 1144 | ||
1126 | #ifdef CONFIG_PROC_FS | 1145 | #ifdef CONFIG_PROC_FS |
@@ -1239,7 +1258,7 @@ EXPORT_SYMBOL(blk_lookup_devt); | |||
1239 | 1258 | ||
1240 | struct gendisk *alloc_disk(int minors) | 1259 | struct gendisk *alloc_disk(int minors) |
1241 | { | 1260 | { |
1242 | return alloc_disk_node(minors, NUMA_NO_NODE); | 1261 | return alloc_disk_node(minors, -1); |
1243 | } | 1262 | } |
1244 | EXPORT_SYMBOL(alloc_disk); | 1263 | EXPORT_SYMBOL(alloc_disk); |
1245 | 1264 | ||
@@ -1262,16 +1281,6 @@ struct gendisk *alloc_disk_node(int minors, int node_id) | |||
1262 | } | 1281 | } |
1263 | disk->part_tbl->part[0] = &disk->part0; | 1282 | disk->part_tbl->part[0] = &disk->part0; |
1264 | 1283 | ||
1265 | /* | ||
1266 | * set_capacity() and get_capacity() currently don't use | ||
1267 | * seqcounter to read/update the part0->nr_sects. Still init | ||
1268 | * the counter as we can read the sectors in IO submission | ||
1269 | * patch using seqence counters. | ||
1270 | * | ||
1271 | * TODO: Ideally set_capacity() and get_capacity() should be | ||
1272 | * converted to make use of bd_mutex and sequence counters. | ||
1273 | */ | ||
1274 | seqcount_init(&disk->part0.nr_sects_seq); | ||
1275 | hd_ref_init(&disk->part0); | 1284 | hd_ref_init(&disk->part0); |
1276 | 1285 | ||
1277 | disk->minors = minors; | 1286 | disk->minors = minors; |
@@ -1484,9 +1493,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now) | |||
1484 | intv = disk_events_poll_jiffies(disk); | 1493 | intv = disk_events_poll_jiffies(disk); |
1485 | set_timer_slack(&ev->dwork.timer, intv / 4); | 1494 | set_timer_slack(&ev->dwork.timer, intv / 4); |
1486 | if (check_now) | 1495 | if (check_now) |
1487 | queue_delayed_work(system_freezable_wq, &ev->dwork, 0); | 1496 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); |
1488 | else if (intv) | 1497 | else if (intv) |
1489 | queue_delayed_work(system_freezable_wq, &ev->dwork, intv); | 1498 | queue_delayed_work(system_nrt_wq, &ev->dwork, intv); |
1490 | out_unlock: | 1499 | out_unlock: |
1491 | spin_unlock_irqrestore(&ev->lock, flags); | 1500 | spin_unlock_irqrestore(&ev->lock, flags); |
1492 | } | 1501 | } |
@@ -1528,8 +1537,10 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask) | |||
1528 | 1537 | ||
1529 | spin_lock_irq(&ev->lock); | 1538 | spin_lock_irq(&ev->lock); |
1530 | ev->clearing |= mask; | 1539 | ev->clearing |= mask; |
1531 | if (!ev->block) | 1540 | if (!ev->block) { |
1532 | mod_delayed_work(system_freezable_wq, &ev->dwork, 0); | 1541 | cancel_delayed_work(&ev->dwork); |
1542 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); | ||
1543 | } | ||
1533 | spin_unlock_irq(&ev->lock); | 1544 | spin_unlock_irq(&ev->lock); |
1534 | } | 1545 | } |
1535 | 1546 | ||
@@ -1565,7 +1576,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) | |||
1565 | 1576 | ||
1566 | /* uncondtionally schedule event check and wait for it to finish */ | 1577 | /* uncondtionally schedule event check and wait for it to finish */ |
1567 | disk_block_events(disk); | 1578 | disk_block_events(disk); |
1568 | queue_delayed_work(system_freezable_wq, &ev->dwork, 0); | 1579 | queue_delayed_work(system_nrt_wq, &ev->dwork, 0); |
1569 | flush_delayed_work(&ev->dwork); | 1580 | flush_delayed_work(&ev->dwork); |
1570 | __disk_unblock_events(disk, false); | 1581 | __disk_unblock_events(disk, false); |
1571 | 1582 | ||
@@ -1602,7 +1613,7 @@ static void disk_events_workfn(struct work_struct *work) | |||
1602 | 1613 | ||
1603 | intv = disk_events_poll_jiffies(disk); | 1614 | intv = disk_events_poll_jiffies(disk); |
1604 | if (!ev->block && intv) | 1615 | if (!ev->block && intv) |
1605 | queue_delayed_work(system_freezable_wq, &ev->dwork, intv); | 1616 | queue_delayed_work(system_nrt_wq, &ev->dwork, intv); |
1606 | 1617 | ||
1607 | spin_unlock_irq(&ev->lock); | 1618 | spin_unlock_irq(&ev->lock); |
1608 | 1619 | ||
@@ -1740,9 +1751,9 @@ module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops, | |||
1740 | &disk_events_dfl_poll_msecs, 0644); | 1751 | &disk_events_dfl_poll_msecs, 0644); |
1741 | 1752 | ||
1742 | /* | 1753 | /* |
1743 | * disk_{alloc|add|del|release}_events - initialize and destroy disk_events. | 1754 | * disk_{add|del|release}_events - initialize and destroy disk_events. |
1744 | */ | 1755 | */ |
1745 | static void disk_alloc_events(struct gendisk *disk) | 1756 | static void disk_add_events(struct gendisk *disk) |
1746 | { | 1757 | { |
1747 | struct disk_events *ev; | 1758 | struct disk_events *ev; |
1748 | 1759 | ||
@@ -1755,6 +1766,16 @@ static void disk_alloc_events(struct gendisk *disk) | |||
1755 | return; | 1766 | return; |
1756 | } | 1767 | } |
1757 | 1768 | ||
1769 | if (sysfs_create_files(&disk_to_dev(disk)->kobj, | ||
1770 | disk_events_attrs) < 0) { | ||
1771 | pr_warn("%s: failed to create sysfs files for events\n", | ||
1772 | disk->disk_name); | ||
1773 | kfree(ev); | ||
1774 | return; | ||
1775 | } | ||
1776 | |||
1777 | disk->ev = ev; | ||
1778 | |||
1758 | INIT_LIST_HEAD(&ev->node); | 1779 | INIT_LIST_HEAD(&ev->node); |
1759 | ev->disk = disk; | 1780 | ev->disk = disk; |
1760 | spin_lock_init(&ev->lock); | 1781 | spin_lock_init(&ev->lock); |
@@ -1763,21 +1784,8 @@ static void disk_alloc_events(struct gendisk *disk) | |||
1763 | ev->poll_msecs = -1; | 1784 | ev->poll_msecs = -1; |
1764 | INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn); | 1785 | INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn); |
1765 | 1786 | ||
1766 | disk->ev = ev; | ||
1767 | } | ||
1768 | |||
1769 | static void disk_add_events(struct gendisk *disk) | ||
1770 | { | ||
1771 | if (!disk->ev) | ||
1772 | return; | ||
1773 | |||
1774 | /* FIXME: error handling */ | ||
1775 | if (sysfs_create_files(&disk_to_dev(disk)->kobj, disk_events_attrs) < 0) | ||
1776 | pr_warn("%s: failed to create sysfs files for events\n", | ||
1777 | disk->disk_name); | ||
1778 | |||
1779 | mutex_lock(&disk_events_mutex); | 1787 | mutex_lock(&disk_events_mutex); |
1780 | list_add_tail(&disk->ev->node, &disk_events); | 1788 | list_add_tail(&ev->node, &disk_events); |
1781 | mutex_unlock(&disk_events_mutex); | 1789 | mutex_unlock(&disk_events_mutex); |
1782 | 1790 | ||
1783 | /* | 1791 | /* |