diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2007-05-19 08:06:24 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-07-09 15:28:01 -0400 |
commit | b93931a61a119575f84c33af2438b9384fde9eb7 (patch) | |
tree | f424d886c1ef255bfa3d3ca60ae245491e7f9432 /drivers | |
parent | 4101c16a910b15afd190c6bc7d45864461cf5c25 (diff) |
mmc: refactor host class handling
Move basic host class device handling to its own file for clarity.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 82 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 4 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 156 | ||||
-rw-r--r-- | drivers/mmc/core/host.h | 18 | ||||
-rw-r--r-- | drivers/mmc/core/sysfs.c | 84 | ||||
-rw-r--r-- | drivers/mmc/core/sysfs.h | 5 |
7 files changed, 187 insertions, 164 deletions
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 54261e3724c4..3fdd08c7f143 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile | |||
@@ -7,6 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y) | |||
7 | endif | 7 | endif |
8 | 8 | ||
9 | obj-$(CONFIG_MMC) += mmc_core.o | 9 | obj-$(CONFIG_MMC) += mmc_core.o |
10 | mmc_core-y := core.o sysfs.o bus.o \ | 10 | mmc_core-y := core.o sysfs.o bus.o host.o \ |
11 | mmc.o mmc_ops.o sd.o sd_ops.o | 11 | mmc.o mmc_ops.o sd.o sd_ops.o |
12 | 12 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d876adf4bd4e..66e463d100c5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -496,7 +496,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) | |||
496 | EXPORT_SYMBOL(mmc_detect_change); | 496 | EXPORT_SYMBOL(mmc_detect_change); |
497 | 497 | ||
498 | 498 | ||
499 | static void mmc_rescan(struct work_struct *work) | 499 | void mmc_rescan(struct work_struct *work) |
500 | { | 500 | { |
501 | struct mmc_host *host = | 501 | struct mmc_host *host = |
502 | container_of(work, struct mmc_host, detect.work); | 502 | container_of(work, struct mmc_host, detect.work); |
@@ -545,69 +545,13 @@ static void mmc_rescan(struct work_struct *work) | |||
545 | } | 545 | } |
546 | } | 546 | } |
547 | 547 | ||
548 | 548 | void mmc_start_host(struct mmc_host *host) | |
549 | /** | ||
550 | * mmc_alloc_host - initialise the per-host structure. | ||
551 | * @extra: sizeof private data structure | ||
552 | * @dev: pointer to host device model structure | ||
553 | * | ||
554 | * Initialise the per-host structure. | ||
555 | */ | ||
556 | struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | ||
557 | { | ||
558 | struct mmc_host *host; | ||
559 | |||
560 | host = mmc_alloc_host_sysfs(extra, dev); | ||
561 | if (host) { | ||
562 | spin_lock_init(&host->lock); | ||
563 | init_waitqueue_head(&host->wq); | ||
564 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); | ||
565 | |||
566 | /* | ||
567 | * By default, hosts do not support SGIO or large requests. | ||
568 | * They have to set these according to their abilities. | ||
569 | */ | ||
570 | host->max_hw_segs = 1; | ||
571 | host->max_phys_segs = 1; | ||
572 | host->max_seg_size = PAGE_CACHE_SIZE; | ||
573 | |||
574 | host->max_req_size = PAGE_CACHE_SIZE; | ||
575 | host->max_blk_size = 512; | ||
576 | host->max_blk_count = PAGE_CACHE_SIZE / 512; | ||
577 | } | ||
578 | |||
579 | return host; | ||
580 | } | ||
581 | |||
582 | EXPORT_SYMBOL(mmc_alloc_host); | ||
583 | |||
584 | /** | ||
585 | * mmc_add_host - initialise host hardware | ||
586 | * @host: mmc host | ||
587 | */ | ||
588 | int mmc_add_host(struct mmc_host *host) | ||
589 | { | 549 | { |
590 | int ret; | 550 | mmc_power_off(host); |
591 | 551 | mmc_detect_change(host, 0); | |
592 | ret = mmc_add_host_sysfs(host); | ||
593 | if (ret == 0) { | ||
594 | mmc_power_off(host); | ||
595 | mmc_detect_change(host, 0); | ||
596 | } | ||
597 | |||
598 | return ret; | ||
599 | } | 552 | } |
600 | 553 | ||
601 | EXPORT_SYMBOL(mmc_add_host); | 554 | void mmc_stop_host(struct mmc_host *host) |
602 | |||
603 | /** | ||
604 | * mmc_remove_host - remove host hardware | ||
605 | * @host: mmc host | ||
606 | * | ||
607 | * Unregister and remove all cards associated with this host, | ||
608 | * and power down the MMC bus. | ||
609 | */ | ||
610 | void mmc_remove_host(struct mmc_host *host) | ||
611 | { | 555 | { |
612 | #ifdef CONFIG_MMC_DEBUG | 556 | #ifdef CONFIG_MMC_DEBUG |
613 | unsigned long flags; | 557 | unsigned long flags; |
@@ -632,24 +576,8 @@ void mmc_remove_host(struct mmc_host *host) | |||
632 | BUG_ON(host->card); | 576 | BUG_ON(host->card); |
633 | 577 | ||
634 | mmc_power_off(host); | 578 | mmc_power_off(host); |
635 | mmc_remove_host_sysfs(host); | ||
636 | } | 579 | } |
637 | 580 | ||
638 | EXPORT_SYMBOL(mmc_remove_host); | ||
639 | |||
640 | /** | ||
641 | * mmc_free_host - free the host structure | ||
642 | * @host: mmc host | ||
643 | * | ||
644 | * Free the host once all references to it have been dropped. | ||
645 | */ | ||
646 | void mmc_free_host(struct mmc_host *host) | ||
647 | { | ||
648 | mmc_free_host_sysfs(host); | ||
649 | } | ||
650 | |||
651 | EXPORT_SYMBOL(mmc_free_host); | ||
652 | |||
653 | #ifdef CONFIG_PM | 581 | #ifdef CONFIG_PM |
654 | 582 | ||
655 | /** | 583 | /** |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 1be86c792a52..ae006b30dd86 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -66,5 +66,9 @@ static inline void mmc_delay(unsigned int ms) | |||
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | void mmc_rescan(struct work_struct *work); | ||
70 | void mmc_start_host(struct mmc_host *host); | ||
71 | void mmc_stop_host(struct mmc_host *host); | ||
72 | |||
69 | #endif | 73 | #endif |
70 | 74 | ||
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c new file mode 100644 index 000000000000..1433d95c40bb --- /dev/null +++ b/drivers/mmc/core/host.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/core/host.c | ||
3 | * | ||
4 | * Copyright (C) 2003 Russell King, All Rights Reserved. | ||
5 | * Copyright (C) 2007 Pierre Ossman | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * MMC host class device management | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/idr.h> | ||
17 | #include <linux/pagemap.h> | ||
18 | |||
19 | #include <linux/mmc/host.h> | ||
20 | |||
21 | #include "core.h" | ||
22 | #include "host.h" | ||
23 | |||
24 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) | ||
25 | |||
26 | static void mmc_host_classdev_release(struct device *dev) | ||
27 | { | ||
28 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | ||
29 | kfree(host); | ||
30 | } | ||
31 | |||
32 | static struct class mmc_host_class = { | ||
33 | .name = "mmc_host", | ||
34 | .dev_release = mmc_host_classdev_release, | ||
35 | }; | ||
36 | |||
37 | int mmc_register_host_class(void) | ||
38 | { | ||
39 | return class_register(&mmc_host_class); | ||
40 | } | ||
41 | |||
42 | void mmc_unregister_host_class(void) | ||
43 | { | ||
44 | class_unregister(&mmc_host_class); | ||
45 | } | ||
46 | |||
47 | static DEFINE_IDR(mmc_host_idr); | ||
48 | static DEFINE_SPINLOCK(mmc_host_lock); | ||
49 | |||
50 | /** | ||
51 | * mmc_alloc_host - initialise the per-host structure. | ||
52 | * @extra: sizeof private data structure | ||
53 | * @dev: pointer to host device model structure | ||
54 | * | ||
55 | * Initialise the per-host structure. | ||
56 | */ | ||
57 | struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | ||
58 | { | ||
59 | struct mmc_host *host; | ||
60 | |||
61 | host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); | ||
62 | if (!host) | ||
63 | return NULL; | ||
64 | |||
65 | memset(host, 0, sizeof(struct mmc_host) + extra); | ||
66 | |||
67 | host->parent = dev; | ||
68 | host->class_dev.parent = dev; | ||
69 | host->class_dev.class = &mmc_host_class; | ||
70 | device_initialize(&host->class_dev); | ||
71 | |||
72 | spin_lock_init(&host->lock); | ||
73 | init_waitqueue_head(&host->wq); | ||
74 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); | ||
75 | |||
76 | /* | ||
77 | * By default, hosts do not support SGIO or large requests. | ||
78 | * They have to set these according to their abilities. | ||
79 | */ | ||
80 | host->max_hw_segs = 1; | ||
81 | host->max_phys_segs = 1; | ||
82 | host->max_seg_size = PAGE_CACHE_SIZE; | ||
83 | |||
84 | host->max_req_size = PAGE_CACHE_SIZE; | ||
85 | host->max_blk_size = 512; | ||
86 | host->max_blk_count = PAGE_CACHE_SIZE / 512; | ||
87 | |||
88 | return host; | ||
89 | } | ||
90 | |||
91 | EXPORT_SYMBOL(mmc_alloc_host); | ||
92 | |||
93 | /** | ||
94 | * mmc_add_host - initialise host hardware | ||
95 | * @host: mmc host | ||
96 | */ | ||
97 | int mmc_add_host(struct mmc_host *host) | ||
98 | { | ||
99 | int err; | ||
100 | |||
101 | if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | spin_lock(&mmc_host_lock); | ||
105 | err = idr_get_new(&mmc_host_idr, host, &host->index); | ||
106 | spin_unlock(&mmc_host_lock); | ||
107 | if (err) | ||
108 | return err; | ||
109 | |||
110 | snprintf(host->class_dev.bus_id, BUS_ID_SIZE, | ||
111 | "mmc%d", host->index); | ||
112 | |||
113 | err = device_add(&host->class_dev); | ||
114 | if (err) | ||
115 | return err; | ||
116 | |||
117 | mmc_start_host(host); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | EXPORT_SYMBOL(mmc_add_host); | ||
123 | |||
124 | /** | ||
125 | * mmc_remove_host - remove host hardware | ||
126 | * @host: mmc host | ||
127 | * | ||
128 | * Unregister and remove all cards associated with this host, | ||
129 | * and power down the MMC bus. | ||
130 | */ | ||
131 | void mmc_remove_host(struct mmc_host *host) | ||
132 | { | ||
133 | mmc_stop_host(host); | ||
134 | |||
135 | device_del(&host->class_dev); | ||
136 | |||
137 | spin_lock(&mmc_host_lock); | ||
138 | idr_remove(&mmc_host_idr, host->index); | ||
139 | spin_unlock(&mmc_host_lock); | ||
140 | } | ||
141 | |||
142 | EXPORT_SYMBOL(mmc_remove_host); | ||
143 | |||
144 | /** | ||
145 | * mmc_free_host - free the host structure | ||
146 | * @host: mmc host | ||
147 | * | ||
148 | * Free the host once all references to it have been dropped. | ||
149 | */ | ||
150 | void mmc_free_host(struct mmc_host *host) | ||
151 | { | ||
152 | put_device(&host->class_dev); | ||
153 | } | ||
154 | |||
155 | EXPORT_SYMBOL(mmc_free_host); | ||
156 | |||
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h new file mode 100644 index 000000000000..c2dc3d2d9f9a --- /dev/null +++ b/drivers/mmc/core/host.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/core/host.h | ||
3 | * | ||
4 | * Copyright (C) 2003 Russell King, All Rights Reserved. | ||
5 | * Copyright 2007 Pierre Ossman | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #ifndef _MMC_CORE_HOST_H | ||
12 | #define _MMC_CORE_HOST_H | ||
13 | |||
14 | int mmc_register_host_class(void); | ||
15 | void mmc_unregister_host_class(void); | ||
16 | |||
17 | #endif | ||
18 | |||
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c index a43a96c22811..fbf99f9a0b83 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c | |||
@@ -20,11 +20,9 @@ | |||
20 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
21 | 21 | ||
22 | #include "bus.h" | 22 | #include "bus.h" |
23 | #include "host.h" | ||
23 | #include "sysfs.h" | 24 | #include "sysfs.h" |
24 | 25 | ||
25 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | ||
26 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) | ||
27 | |||
28 | int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) | 26 | int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) |
29 | { | 27 | { |
30 | int error = 0; | 28 | int error = 0; |
@@ -50,82 +48,6 @@ void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs) | |||
50 | device_remove_file(&card->dev, &attrs[i]); | 48 | device_remove_file(&card->dev, &attrs[i]); |
51 | } | 49 | } |
52 | 50 | ||
53 | static void mmc_host_classdev_release(struct device *dev) | ||
54 | { | ||
55 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | ||
56 | kfree(host); | ||
57 | } | ||
58 | |||
59 | static struct class mmc_host_class = { | ||
60 | .name = "mmc_host", | ||
61 | .dev_release = mmc_host_classdev_release, | ||
62 | }; | ||
63 | |||
64 | static DEFINE_IDR(mmc_host_idr); | ||
65 | static DEFINE_SPINLOCK(mmc_host_lock); | ||
66 | |||
67 | /* | ||
68 | * Internal function. Allocate a new MMC host. | ||
69 | */ | ||
70 | struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) | ||
71 | { | ||
72 | struct mmc_host *host; | ||
73 | |||
74 | host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); | ||
75 | if (host) { | ||
76 | memset(host, 0, sizeof(struct mmc_host) + extra); | ||
77 | |||
78 | host->parent = dev; | ||
79 | host->class_dev.parent = dev; | ||
80 | host->class_dev.class = &mmc_host_class; | ||
81 | device_initialize(&host->class_dev); | ||
82 | } | ||
83 | |||
84 | return host; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Internal function. Register a new MMC host with the MMC class. | ||
89 | */ | ||
90 | int mmc_add_host_sysfs(struct mmc_host *host) | ||
91 | { | ||
92 | int err; | ||
93 | |||
94 | if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) | ||
95 | return -ENOMEM; | ||
96 | |||
97 | spin_lock(&mmc_host_lock); | ||
98 | err = idr_get_new(&mmc_host_idr, host, &host->index); | ||
99 | spin_unlock(&mmc_host_lock); | ||
100 | if (err) | ||
101 | return err; | ||
102 | |||
103 | snprintf(host->class_dev.bus_id, BUS_ID_SIZE, | ||
104 | "mmc%d", host->index); | ||
105 | |||
106 | return device_add(&host->class_dev); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Internal function. Unregister a MMC host with the MMC class. | ||
111 | */ | ||
112 | void mmc_remove_host_sysfs(struct mmc_host *host) | ||
113 | { | ||
114 | device_del(&host->class_dev); | ||
115 | |||
116 | spin_lock(&mmc_host_lock); | ||
117 | idr_remove(&mmc_host_idr, host->index); | ||
118 | spin_unlock(&mmc_host_lock); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Internal function. Free a MMC host. | ||
123 | */ | ||
124 | void mmc_free_host_sysfs(struct mmc_host *host) | ||
125 | { | ||
126 | put_device(&host->class_dev); | ||
127 | } | ||
128 | |||
129 | static struct workqueue_struct *workqueue; | 51 | static struct workqueue_struct *workqueue; |
130 | 52 | ||
131 | /* | 53 | /* |
@@ -154,7 +76,7 @@ static int __init mmc_init(void) | |||
154 | 76 | ||
155 | ret = mmc_register_bus(); | 77 | ret = mmc_register_bus(); |
156 | if (ret == 0) { | 78 | if (ret == 0) { |
157 | ret = class_register(&mmc_host_class); | 79 | ret = mmc_register_host_class(); |
158 | if (ret) | 80 | if (ret) |
159 | mmc_unregister_bus(); | 81 | mmc_unregister_bus(); |
160 | } | 82 | } |
@@ -163,7 +85,7 @@ static int __init mmc_init(void) | |||
163 | 85 | ||
164 | static void __exit mmc_exit(void) | 86 | static void __exit mmc_exit(void) |
165 | { | 87 | { |
166 | class_unregister(&mmc_host_class); | 88 | mmc_unregister_host_class(); |
167 | mmc_unregister_bus(); | 89 | mmc_unregister_bus(); |
168 | destroy_workqueue(workqueue); | 90 | destroy_workqueue(workqueue); |
169 | } | 91 | } |
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h index 2a326a5b83c6..2f60c79b203b 100644 --- a/drivers/mmc/core/sysfs.h +++ b/drivers/mmc/core/sysfs.h | |||
@@ -23,11 +23,6 @@ static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *a | |||
23 | int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs); | 23 | int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs); |
24 | void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs); | 24 | void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs); |
25 | 25 | ||
26 | struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev); | ||
27 | int mmc_add_host_sysfs(struct mmc_host *host); | ||
28 | void mmc_remove_host_sysfs(struct mmc_host *host); | ||
29 | void mmc_free_host_sysfs(struct mmc_host *host); | ||
30 | |||
31 | int mmc_schedule_work(struct work_struct *work); | 26 | int mmc_schedule_work(struct work_struct *work); |
32 | int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); | 27 | int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); |
33 | void mmc_flush_scheduled_work(void); | 28 | void mmc_flush_scheduled_work(void); |