2 * linux/drivers/mmc/core/sysfs.c
4 * Copyright (C) 2003 Russell King, All Rights Reserved.
5 * Copyright 2007 Pierre Ossman
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.
11 * MMC sysfs/driver model support.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/device.h>
16 #include <linux/idr.h>
17 #include <linux/workqueue.h>
19 #include <linux/mmc/card.h>
20 #include <linux/mmc/host.h>
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)
28 int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
33 for (i = 0; attr_name(attrs[i]); i++) {
34 error = device_create_file(&card->dev, &attrs[i]);
37 device_remove_file(&card->dev, &attrs[i]);
45 void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
49 for (i = 0; attr_name(attrs[i]); i++)
50 device_remove_file(&card->dev, &attrs[i]);
53 static void mmc_host_classdev_release(struct device *dev)
55 struct mmc_host *host = cls_dev_to_mmc_host(dev);
59 static struct class mmc_host_class = {
61 .dev_release = mmc_host_classdev_release,
64 static DEFINE_IDR(mmc_host_idr);
65 static DEFINE_SPINLOCK(mmc_host_lock);
68 * Internal function. Allocate a new MMC host.
70 struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
72 struct mmc_host *host;
74 host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
76 memset(host, 0, sizeof(struct mmc_host) + extra);
79 host->class_dev.parent = dev;
80 host->class_dev.class = &mmc_host_class;
81 device_initialize(&host->class_dev);
88 * Internal function. Register a new MMC host with the MMC class.
90 int mmc_add_host_sysfs(struct mmc_host *host)
94 if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
97 spin_lock(&mmc_host_lock);
98 err = idr_get_new(&mmc_host_idr, host, &host->index);
99 spin_unlock(&mmc_host_lock);
103 snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
104 "mmc%d", host->index);
106 return device_add(&host->class_dev);
110 * Internal function. Unregister a MMC host with the MMC class.
112 void mmc_remove_host_sysfs(struct mmc_host *host)
114 device_del(&host->class_dev);
116 spin_lock(&mmc_host_lock);
117 idr_remove(&mmc_host_idr, host->index);
118 spin_unlock(&mmc_host_lock);
122 * Internal function. Free a MMC host.
124 void mmc_free_host_sysfs(struct mmc_host *host)
126 put_device(&host->class_dev);
129 static struct workqueue_struct *workqueue;
132 * Internal function. Schedule delayed work in the MMC work queue.
134 int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
136 return queue_delayed_work(workqueue, work, delay);
140 * Internal function. Flush all scheduled work from the MMC work queue.
142 void mmc_flush_scheduled_work(void)
144 flush_workqueue(workqueue);
147 static int __init mmc_init(void)
151 workqueue = create_singlethread_workqueue("kmmcd");
155 ret = mmc_register_bus();
157 ret = class_register(&mmc_host_class);
159 mmc_unregister_bus();
164 static void __exit mmc_exit(void)
166 class_unregister(&mmc_host_class);
167 mmc_unregister_bus();
168 destroy_workqueue(workqueue);
171 module_init(mmc_init);
172 module_exit(mmc_exit);