diff options
Diffstat (limited to 'drivers/mmc/mmc_sysfs.c')
-rw-r--r-- | drivers/mmc/mmc_sysfs.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 5556cd3b5559..ad8949810fc5 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/idr.h> | ||
15 | 16 | ||
16 | #include <linux/mmc/card.h> | 17 | #include <linux/mmc/card.h> |
17 | #include <linux/mmc/host.h> | 18 | #include <linux/mmc/host.h> |
@@ -20,6 +21,7 @@ | |||
20 | 21 | ||
21 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) | 22 | #define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) |
22 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) | 23 | #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) |
24 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) | ||
23 | 25 | ||
24 | #define MMC_ATTR(name, fmt, args...) \ | 26 | #define MMC_ATTR(name, fmt, args...) \ |
25 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ | 27 | static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ |
@@ -206,7 +208,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) | |||
206 | int mmc_register_card(struct mmc_card *card) | 208 | int mmc_register_card(struct mmc_card *card) |
207 | { | 209 | { |
208 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), | 210 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), |
209 | "%s:%04x", card->host->host_name, card->rca); | 211 | "%s:%04x", mmc_hostname(card->host), card->rca); |
210 | 212 | ||
211 | return device_add(&card->dev); | 213 | return device_add(&card->dev); |
212 | } | 214 | } |
@@ -224,13 +226,97 @@ void mmc_remove_card(struct mmc_card *card) | |||
224 | } | 226 | } |
225 | 227 | ||
226 | 228 | ||
229 | static void mmc_host_classdev_release(struct class_device *dev) | ||
230 | { | ||
231 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | ||
232 | kfree(host); | ||
233 | } | ||
234 | |||
235 | static struct class mmc_host_class = { | ||
236 | .name = "mmc_host", | ||
237 | .release = mmc_host_classdev_release, | ||
238 | }; | ||
239 | |||
240 | static DEFINE_IDR(mmc_host_idr); | ||
241 | static DEFINE_SPINLOCK(mmc_host_lock); | ||
242 | |||
243 | /* | ||
244 | * Internal function. Allocate a new MMC host. | ||
245 | */ | ||
246 | struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) | ||
247 | { | ||
248 | struct mmc_host *host; | ||
249 | |||
250 | host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); | ||
251 | if (host) { | ||
252 | memset(host, 0, sizeof(struct mmc_host) + extra); | ||
253 | |||
254 | host->dev = dev; | ||
255 | host->class_dev.dev = host->dev; | ||
256 | host->class_dev.class = &mmc_host_class; | ||
257 | class_device_initialize(&host->class_dev); | ||
258 | } | ||
259 | |||
260 | return host; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Internal function. Register a new MMC host with the MMC class. | ||
265 | */ | ||
266 | int mmc_add_host_sysfs(struct mmc_host *host) | ||
267 | { | ||
268 | int err; | ||
269 | |||
270 | if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | spin_lock(&mmc_host_lock); | ||
274 | err = idr_get_new(&mmc_host_idr, host, &host->index); | ||
275 | spin_unlock(&mmc_host_lock); | ||
276 | if (err) | ||
277 | return err; | ||
278 | |||
279 | snprintf(host->class_dev.class_id, BUS_ID_SIZE, | ||
280 | "mmc%d", host->index); | ||
281 | |||
282 | return class_device_add(&host->class_dev); | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Internal function. Unregister a MMC host with the MMC class. | ||
287 | */ | ||
288 | void mmc_remove_host_sysfs(struct mmc_host *host) | ||
289 | { | ||
290 | class_device_del(&host->class_dev); | ||
291 | |||
292 | spin_lock(&mmc_host_lock); | ||
293 | idr_remove(&mmc_host_idr, host->index); | ||
294 | spin_unlock(&mmc_host_lock); | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Internal function. Free a MMC host. | ||
299 | */ | ||
300 | void mmc_free_host_sysfs(struct mmc_host *host) | ||
301 | { | ||
302 | class_device_put(&host->class_dev); | ||
303 | } | ||
304 | |||
305 | |||
227 | static int __init mmc_init(void) | 306 | static int __init mmc_init(void) |
228 | { | 307 | { |
229 | return bus_register(&mmc_bus_type); | 308 | int ret = bus_register(&mmc_bus_type); |
309 | if (ret == 0) { | ||
310 | ret = class_register(&mmc_host_class); | ||
311 | if (ret) | ||
312 | bus_unregister(&mmc_bus_type); | ||
313 | } | ||
314 | return ret; | ||
230 | } | 315 | } |
231 | 316 | ||
232 | static void __exit mmc_exit(void) | 317 | static void __exit mmc_exit(void) |
233 | { | 318 | { |
319 | class_unregister(&mmc_host_class); | ||
234 | bus_unregister(&mmc_bus_type); | 320 | bus_unregister(&mmc_bus_type); |
235 | } | 321 | } |
236 | 322 | ||