diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2007-05-19 07:39:01 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-07-09 15:27:56 -0400 |
commit | 4101c16a910b15afd190c6bc7d45864461cf5c25 (patch) | |
tree | 76d88e3bfd6723fc86c13c635b3c2b73c73c6978 /drivers/mmc/core/sysfs.c | |
parent | 7de064ebc67d9baf6c933d3a7046feb9b4eced05 (diff) |
mmc: refactor bus operations
Move bus operations to its own file for the sake of clarity. Also
delegate sysfs attributes to bus handlers in preparation for other
more exotic types.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/core/sysfs.c')
-rw-r--r-- | drivers/mmc/core/sysfs.c | 228 |
1 files changed, 20 insertions, 208 deletions
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c index 843b1fbba557..a43a96c22811 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * linux/drivers/mmc/core/sysfs.c | 2 | * linux/drivers/mmc/core/sysfs.c |
3 | * | 3 | * |
4 | * Copyright (C) 2003 Russell King, All Rights Reserved. | 4 | * Copyright (C) 2003 Russell King, All Rights Reserved. |
5 | * Copyright 2007 Pierre Ossman | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -18,226 +19,37 @@ | |||
18 | #include <linux/mmc/card.h> | 19 | #include <linux/mmc/card.h> |
19 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
20 | 21 | ||
22 | #include "bus.h" | ||
21 | #include "sysfs.h" | 23 | #include "sysfs.h" |
22 | 24 | ||
23 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) | ||
24 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | 25 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) |
25 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) | 26 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) |
26 | 27 | ||
27 | #define MMC_ATTR(name, fmt, args...) \ | 28 | int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) |
28 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
29 | { \ | ||
30 | struct mmc_card *card = dev_to_mmc_card(dev); \ | ||
31 | return sprintf(buf, fmt, args); \ | ||
32 | } | ||
33 | |||
34 | MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | ||
35 | card->raw_cid[2], card->raw_cid[3]); | ||
36 | MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | ||
37 | card->raw_csd[2], card->raw_csd[3]); | ||
38 | MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); | ||
39 | MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | ||
40 | MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | ||
41 | MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | ||
42 | MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid); | ||
43 | MMC_ATTR(name, "%s\n", card->cid.prod_name); | ||
44 | MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid); | ||
45 | MMC_ATTR(serial, "0x%08x\n", card->cid.serial); | ||
46 | |||
47 | #define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) | ||
48 | |||
49 | static struct device_attribute mmc_dev_attrs[] = { | ||
50 | MMC_ATTR_RO(cid), | ||
51 | MMC_ATTR_RO(csd), | ||
52 | MMC_ATTR_RO(date), | ||
53 | MMC_ATTR_RO(fwrev), | ||
54 | MMC_ATTR_RO(hwrev), | ||
55 | MMC_ATTR_RO(manfid), | ||
56 | MMC_ATTR_RO(name), | ||
57 | MMC_ATTR_RO(oemid), | ||
58 | MMC_ATTR_RO(serial), | ||
59 | __ATTR_NULL | ||
60 | }; | ||
61 | |||
62 | static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr); | ||
63 | |||
64 | |||
65 | static void mmc_release_card(struct device *dev) | ||
66 | { | 29 | { |
67 | struct mmc_card *card = dev_to_mmc_card(dev); | 30 | int error = 0; |
68 | 31 | int i; | |
69 | kfree(card); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * This currently matches any MMC driver to any MMC card - drivers | ||
74 | * themselves make the decision whether to drive this card in their | ||
75 | * probe method. | ||
76 | */ | ||
77 | static int mmc_bus_match(struct device *dev, struct device_driver *drv) | ||
78 | { | ||
79 | return 1; | ||
80 | } | ||
81 | |||
82 | static int | ||
83 | mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, | ||
84 | int buf_size) | ||
85 | { | ||
86 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
87 | char ccc[13]; | ||
88 | int retval = 0, i = 0, length = 0; | ||
89 | |||
90 | #define add_env(fmt,val) do { \ | ||
91 | retval = add_uevent_var(envp, num_envp, &i, \ | ||
92 | buf, buf_size, &length, \ | ||
93 | fmt, val); \ | ||
94 | if (retval) \ | ||
95 | return retval; \ | ||
96 | } while (0); | ||
97 | |||
98 | for (i = 0; i < 12; i++) | ||
99 | ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; | ||
100 | ccc[12] = '\0'; | ||
101 | 32 | ||
102 | add_env("MMC_CCC=%s", ccc); | 33 | for (i = 0; attr_name(attrs[i]); i++) { |
103 | add_env("MMC_MANFID=%06x", card->cid.manfid); | 34 | error = device_create_file(&card->dev, &attrs[i]); |
104 | add_env("MMC_NAME=%s", mmc_card_name(card)); | 35 | if (error) { |
105 | add_env("MMC_OEMID=%04x", card->cid.oemid); | 36 | while (--i >= 0) |
106 | #undef add_env | 37 | device_remove_file(&card->dev, &attrs[i]); |
107 | envp[i] = NULL; | 38 | break; |
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int mmc_bus_suspend(struct device *dev, pm_message_t state) | ||
113 | { | ||
114 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
115 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
116 | int ret = 0; | ||
117 | |||
118 | if (dev->driver && drv->suspend) | ||
119 | ret = drv->suspend(card, state); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int mmc_bus_resume(struct device *dev) | ||
124 | { | ||
125 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
126 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
127 | int ret = 0; | ||
128 | |||
129 | if (dev->driver && drv->resume) | ||
130 | ret = drv->resume(card); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static int mmc_bus_probe(struct device *dev) | ||
135 | { | ||
136 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
137 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
138 | |||
139 | return drv->probe(card); | ||
140 | } | ||
141 | |||
142 | static int mmc_bus_remove(struct device *dev) | ||
143 | { | ||
144 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
145 | struct mmc_card *card = dev_to_mmc_card(dev); | ||
146 | |||
147 | drv->remove(card); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static struct bus_type mmc_bus_type = { | ||
153 | .name = "mmc", | ||
154 | .dev_attrs = mmc_dev_attrs, | ||
155 | .match = mmc_bus_match, | ||
156 | .uevent = mmc_bus_uevent, | ||
157 | .probe = mmc_bus_probe, | ||
158 | .remove = mmc_bus_remove, | ||
159 | .suspend = mmc_bus_suspend, | ||
160 | .resume = mmc_bus_resume, | ||
161 | }; | ||
162 | |||
163 | /** | ||
164 | * mmc_register_driver - register a media driver | ||
165 | * @drv: MMC media driver | ||
166 | */ | ||
167 | int mmc_register_driver(struct mmc_driver *drv) | ||
168 | { | ||
169 | drv->drv.bus = &mmc_bus_type; | ||
170 | return driver_register(&drv->drv); | ||
171 | } | ||
172 | |||
173 | EXPORT_SYMBOL(mmc_register_driver); | ||
174 | |||
175 | /** | ||
176 | * mmc_unregister_driver - unregister a media driver | ||
177 | * @drv: MMC media driver | ||
178 | */ | ||
179 | void mmc_unregister_driver(struct mmc_driver *drv) | ||
180 | { | ||
181 | drv->drv.bus = &mmc_bus_type; | ||
182 | driver_unregister(&drv->drv); | ||
183 | } | ||
184 | |||
185 | EXPORT_SYMBOL(mmc_unregister_driver); | ||
186 | |||
187 | |||
188 | /* | ||
189 | * Internal function. Initialise a MMC card structure. | ||
190 | */ | ||
191 | void mmc_init_card(struct mmc_card *card, struct mmc_host *host) | ||
192 | { | ||
193 | memset(card, 0, sizeof(struct mmc_card)); | ||
194 | card->host = host; | ||
195 | device_initialize(&card->dev); | ||
196 | card->dev.parent = mmc_classdev(host); | ||
197 | card->dev.bus = &mmc_bus_type; | ||
198 | card->dev.release = mmc_release_card; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Internal function. Register a new MMC card with the driver model. | ||
203 | */ | ||
204 | int mmc_register_card(struct mmc_card *card) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), | ||
209 | "%s:%04x", mmc_hostname(card->host), card->rca); | ||
210 | |||
211 | ret = device_add(&card->dev); | ||
212 | if (ret == 0) { | ||
213 | if (mmc_card_sd(card)) { | ||
214 | ret = device_create_file(&card->dev, &mmc_dev_attr_scr); | ||
215 | if (ret) | ||
216 | device_del(&card->dev); | ||
217 | } | 39 | } |
218 | } | 40 | } |
219 | if (ret == 0) | 41 | |
220 | mmc_card_set_present(card); | 42 | return error; |
221 | return ret; | ||
222 | } | 43 | } |
223 | 44 | ||
224 | /* | 45 | void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs) |
225 | * Internal function. Unregister a new MMC card with the | ||
226 | * driver model, and (eventually) free it. | ||
227 | */ | ||
228 | void mmc_remove_card(struct mmc_card *card) | ||
229 | { | 46 | { |
230 | if (mmc_card_present(card)) { | 47 | int i; |
231 | if (mmc_card_sd(card)) | ||
232 | device_remove_file(&card->dev, &mmc_dev_attr_scr); | ||
233 | |||
234 | device_del(&card->dev); | ||
235 | } | ||
236 | 48 | ||
237 | put_device(&card->dev); | 49 | for (i = 0; attr_name(attrs[i]); i++) |
50 | device_remove_file(&card->dev, &attrs[i]); | ||
238 | } | 51 | } |
239 | 52 | ||
240 | |||
241 | static void mmc_host_classdev_release(struct device *dev) | 53 | static void mmc_host_classdev_release(struct device *dev) |
242 | { | 54 | { |
243 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | 55 | struct mmc_host *host = cls_dev_to_mmc_host(dev); |
@@ -340,11 +152,11 @@ static int __init mmc_init(void) | |||
340 | if (!workqueue) | 152 | if (!workqueue) |
341 | return -ENOMEM; | 153 | return -ENOMEM; |
342 | 154 | ||
343 | ret = bus_register(&mmc_bus_type); | 155 | ret = mmc_register_bus(); |
344 | if (ret == 0) { | 156 | if (ret == 0) { |
345 | ret = class_register(&mmc_host_class); | 157 | ret = class_register(&mmc_host_class); |
346 | if (ret) | 158 | if (ret) |
347 | bus_unregister(&mmc_bus_type); | 159 | mmc_unregister_bus(); |
348 | } | 160 | } |
349 | return ret; | 161 | return ret; |
350 | } | 162 | } |
@@ -352,7 +164,7 @@ static int __init mmc_init(void) | |||
352 | static void __exit mmc_exit(void) | 164 | static void __exit mmc_exit(void) |
353 | { | 165 | { |
354 | class_unregister(&mmc_host_class); | 166 | class_unregister(&mmc_host_class); |
355 | bus_unregister(&mmc_bus_type); | 167 | mmc_unregister_bus(); |
356 | destroy_workqueue(workqueue); | 168 | destroy_workqueue(workqueue); |
357 | } | 169 | } |
358 | 170 | ||