diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/Makefile | 3 | ||||
-rw-r--r-- | drivers/mmc/core/bus.c | 253 | ||||
-rw-r--r-- | drivers/mmc/core/bus.h | 22 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 16 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 4 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 59 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 63 | ||||
-rw-r--r-- | drivers/mmc/core/sysfs.c | 228 | ||||
-rw-r--r-- | drivers/mmc/core/sysfs.h | 14 |
9 files changed, 418 insertions, 244 deletions
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 1075b02ae75..54261e3724c 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -7,5 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y) endif obj-$(CONFIG_MMC) += mmc_core.o -mmc_core-y := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o +mmc_core-y := core.o sysfs.o bus.o \ + mmc.o mmc_ops.o sd.o sd_ops.o diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c new file mode 100644 index 00000000000..348b566bf4f --- /dev/null +++ b/drivers/mmc/core/bus.c @@ -0,0 +1,253 @@ +/* + * linux/drivers/mmc/core/bus.c + * + * Copyright (C) 2003 Russell King, All Rights Reserved. + * Copyright (C) 2007 Pierre Ossman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * MMC card bus driver model + */ + +#include <linux/device.h> +#include <linux/err.h> + +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> + +#include "sysfs.h" +#include "core.h" +#include "bus.h" + +#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) +#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) + +static ssize_t mmc_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mmc_card *card = dev_to_mmc_card(dev); + + switch (card->type) { + case MMC_TYPE_MMC: + return sprintf(buf, "MMC\n"); + case MMC_TYPE_SD: + return sprintf(buf, "SD\n"); + default: + return -EFAULT; + } +} + +static struct device_attribute mmc_dev_attrs[] = { + MMC_ATTR_RO(type), + __ATTR_NULL, +}; + +/* + * This currently matches any MMC driver to any MMC card - drivers + * themselves make the decision whether to drive this card in their + * probe method. + */ +static int mmc_bus_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + +static int +mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, + int buf_size) +{ + struct mmc_card *card = dev_to_mmc_card(dev); + int retval = 0, i = 0, length = 0; + +#define add_env(fmt,val) do { \ + retval = add_uevent_var(envp, num_envp, &i, \ + buf, buf_size, &length, \ + fmt, val); \ + if (retval) \ + return retval; \ +} while (0); + + switch (card->type) { + case MMC_TYPE_MMC: + add_env("MMC_TYPE=%s", "MMC"); + break; + case MMC_TYPE_SD: + add_env("MMC_TYPE=%s", "SD"); + break; + } + + add_env("MMC_NAME=%s", mmc_card_name(card)); + +#undef add_env + + envp[i] = NULL; + + return 0; +} + +static int mmc_bus_probe(struct device *dev) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = dev_to_mmc_card(dev); + + return drv->probe(card); +} + +static int mmc_bus_remove(struct device *dev) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = dev_to_mmc_card(dev); + + drv->remove(card); + + return 0; +} + +static int mmc_bus_suspend(struct device *dev, pm_message_t state) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = dev_to_mmc_card(dev); + int ret = 0; + + if (dev->driver && drv->suspend) + ret = drv->suspend(card, state); + return ret; +} + +static int mmc_bus_resume(struct device *dev) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = dev_to_mmc_card(dev); + int ret = 0; + + if (dev->driver && drv->resume) + ret = drv->resume(card); + return ret; +} + +static struct bus_type mmc_bus_type = { + .name = "mmc", + .dev_attrs = mmc_dev_attrs, + .match = mmc_bus_match, + .uevent = mmc_bus_uevent, + .probe = mmc_bus_probe, + .remove = mmc_bus_remove, + .suspend = mmc_bus_suspend, + .resume = mmc_bus_resume, +}; + +int mmc_register_bus(void) +{ + return bus_register(&mmc_bus_type); +} + +void mmc_unregister_bus(void) +{ + bus_unregister(&mmc_bus_type); +} + +/** + * mmc_register_driver - register a media driver + * @drv: MMC media driver + */ +int mmc_register_driver(struct mmc_driver *drv) +{ + drv->drv.bus = &mmc_bus_type; + return driver_register(&drv->drv); +} + +EXPORT_SYMBOL(mmc_register_driver); + +/** + * mmc_unregister_driver - unregister a media driver + * @drv: MMC media driver + */ +void mmc_unregister_driver(struct mmc_driver *drv) +{ + drv->drv.bus = &mmc_bus_type; + driver_unregister(&drv->drv); +} + +EXPORT_SYMBOL(mmc_unregister_driver); + +static void mmc_release_card(struct device *dev) +{ + struct mmc_card *card = dev_to_mmc_card(dev); + + kfree(card); +} + +/* + * Allocate and initialise a new MMC card structure. + */ +struct mmc_card *mmc_alloc_card(struct mmc_host *host) +{ + struct mmc_card *card; + + card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); + if (!card) + return ERR_PTR(-ENOMEM); + + memset(card, 0, sizeof(struct mmc_card)); + + card->host = host; + + device_initialize(&card->dev); + + card->dev.parent = mmc_classdev(host); + card->dev.bus = &mmc_bus_type; + card->dev.release = mmc_release_card; + + return card; +} + +/* + * Register a new MMC card with the driver model. + */ +int mmc_add_card(struct mmc_card *card) +{ + int ret; + + snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), + "%s:%04x", mmc_hostname(card->host), card->rca); + + card->dev.uevent_suppress = 1; + + ret = device_add(&card->dev); + if (ret) + return ret; + + if (card->host->bus_ops->sysfs_add) { + ret = card->host->bus_ops->sysfs_add(card->host, card); + if (ret) { + device_del(&card->dev); + return ret; + } + } + + card->dev.uevent_suppress = 0; + + kobject_uevent(&card->dev.kobj, KOBJ_ADD); + + mmc_card_set_present(card); + + return 0; +} + +/* + * Unregister a new MMC card with the driver model, and + * (eventually) free it. + */ +void mmc_remove_card(struct mmc_card *card) +{ + if (mmc_card_present(card)) { + if (card->host->bus_ops->sysfs_remove) + card->host->bus_ops->sysfs_remove(card->host, card); + device_del(&card->dev); + } + + put_device(&card->dev); +} + diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h new file mode 100644 index 00000000000..4f35431116a --- /dev/null +++ b/drivers/mmc/core/bus.h @@ -0,0 +1,22 @@ +/* + * linux/drivers/mmc/core/bus.h + * + * Copyright (C) 2003 Russell King, All Rights Reserved. + * Copyright 2007 Pierre Ossman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _MMC_CORE_BUS_H +#define _MMC_CORE_BUS_H + +struct mmc_card *mmc_alloc_card(struct mmc_host *host); +int mmc_add_card(struct mmc_card *card); +void mmc_remove_card(struct mmc_card *card); + +int mmc_register_bus(void); +void mmc_unregister_bus(void); + +#endif + diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7385acfa1dd..d876adf4bd4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -369,22 +369,6 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) } /* - * Allocate a new MMC card - */ -struct mmc_card *mmc_alloc_card(struct mmc_host *host) -{ - struct mmc_card *card; - - card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); - if (!card) - return ERR_PTR(-ENOMEM); - - mmc_init_card(card, host); - - return card; -} - -/* * Apply power to the MMC stack. This is a two-stage process. * First, we enable power to the card without the clock running. * We then wait a bit for the power to stabilise. Finally, diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 177264d090a..1be86c792a5 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -18,6 +18,8 @@ struct mmc_bus_ops { void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); + int (*sysfs_add)(struct mmc_host *, struct mmc_card *card); + void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card); void (*suspend)(struct mmc_host *); void (*resume)(struct mmc_host *); }; @@ -54,8 +56,6 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); void mmc_set_timing(struct mmc_host *host, unsigned int timing); -struct mmc_card *mmc_alloc_card(struct mmc_host *host); - static inline void mmc_delay(unsigned int ms) { if (ms < 1000 / HZ) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 42cc2867ed7..e4371555160 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -18,6 +18,7 @@ #include "core.h" #include "sysfs.h" +#include "bus.h" #include "mmc_ops.h" static const unsigned int tran_exp[] = { @@ -413,8 +414,7 @@ static void mmc_detect(struct mmc_host *host) mmc_release_host(host); if (err != MMC_ERR_NONE) { - mmc_remove_card(host->card); - host->card = NULL; + mmc_remove(host); mmc_claim_host(host); mmc_detach_bus(host); @@ -422,6 +422,53 @@ static void mmc_detect(struct mmc_host *host) } } +MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], + card->raw_cid[2], card->raw_cid[3]); +MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], + card->raw_csd[2], card->raw_csd[3]); +MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year); +MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev); +MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev); +MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid); +MMC_ATTR_FN(name, "%s\n", card->cid.prod_name); +MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid); +MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial); + +static struct device_attribute mmc_dev_attrs[] = { + MMC_ATTR_RO(cid), + MMC_ATTR_RO(csd), + MMC_ATTR_RO(date), + MMC_ATTR_RO(fwrev), + MMC_ATTR_RO(hwrev), + MMC_ATTR_RO(manfid), + MMC_ATTR_RO(name), + MMC_ATTR_RO(oemid), + MMC_ATTR_RO(serial), + __ATTR_NULL, +}; + +/* + * Adds sysfs entries as relevant. + */ +static int mmc_sysfs_add(struct mmc_host *host, struct mmc_card *card) +{ + int ret; + + ret = mmc_add_attrs(card, mmc_dev_attrs); + if (ret < 0) + return ret; + + return 0; +} + +/* + * Removes the sysfs entries added by mmc_sysfs_add(). + */ +static void mmc_sysfs_remove(struct mmc_host *host, struct mmc_card *card) +{ + mmc_remove_attrs(card, mmc_dev_attrs); +} + #ifdef CONFIG_MMC_UNSAFE_RESUME /* @@ -455,9 +502,7 @@ static void mmc_resume(struct mmc_host *host) err = mmc_sd_init_card(host, host->ocr, host->card); if (err != MMC_ERR_NONE) { - mmc_remove_card(host->card); - host->card = NULL; - + mmc_remove(host); mmc_detach_bus(host); } @@ -474,6 +519,8 @@ static void mmc_resume(struct mmc_host *host) static const struct mmc_bus_ops mmc_ops = { .remove = mmc_remove, .detect = mmc_detect, + .sysfs_add = mmc_sysfs_add, + .sysfs_remove = mmc_sysfs_remove, .suspend = mmc_suspend, .resume = mmc_resume, }; @@ -518,7 +565,7 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) mmc_release_host(host); - err = mmc_register_card(host->card); + err = mmc_add_card(host->card); if (err) goto reclaim_host; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 918477c490b..1240684083f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -19,11 +19,10 @@ #include "core.h" #include "sysfs.h" +#include "bus.h" #include "mmc_ops.h" #include "sd_ops.h" -#include "core.h" - static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 @@ -487,8 +486,7 @@ static void mmc_sd_detect(struct mmc_host *host) mmc_release_host(host); if (err != MMC_ERR_NONE) { - mmc_remove_card(host->card); - host->card = NULL; + mmc_sd_remove(host); mmc_claim_host(host); mmc_detach_bus(host); @@ -496,6 +494,55 @@ static void mmc_sd_detect(struct mmc_host *host) } } +MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], + card->raw_cid[2], card->raw_cid[3]); +MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], + card->raw_csd[2], card->raw_csd[3]); +MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); +MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year); +MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev); +MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev); +MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid); +MMC_ATTR_FN(name, "%s\n", card->cid.prod_name); +MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid); +MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial); + +static struct device_attribute mmc_sd_dev_attrs[] = { + MMC_ATTR_RO(cid), + MMC_ATTR_RO(csd), + MMC_ATTR_RO(scr), + MMC_ATTR_RO(date), + MMC_ATTR_RO(fwrev), + MMC_ATTR_RO(hwrev), + MMC_ATTR_RO(manfid), + MMC_ATTR_RO(name), + MMC_ATTR_RO(oemid), + MMC_ATTR_RO(serial), + __ATTR_NULL, +}; + +/* + * Adds sysfs entries as relevant. + */ +static int mmc_sd_sysfs_add(struct mmc_host *host, struct mmc_card *card) +{ + int ret; + + ret = mmc_add_attrs(card, mmc_sd_dev_attrs); + if (ret < 0) + return ret; + + return 0; +} + +/* + * Removes the sysfs entries added by mmc_sysfs_add(). + */ +static void mmc_sd_sysfs_remove(struct mmc_host *host, struct mmc_card *card) +{ + mmc_remove_attrs(card, mmc_sd_dev_attrs); +} + #ifdef CONFIG_MMC_UNSAFE_RESUME /* @@ -529,9 +576,7 @@ static void mmc_sd_resume(struct mmc_host *host) err = mmc_sd_init_card(host, host->ocr, host->card); if (err != MMC_ERR_NONE) { - mmc_remove_card(host->card); - host->card = NULL; - + mmc_sd_remove(host); mmc_detach_bus(host); } @@ -548,6 +593,8 @@ static void mmc_sd_resume(struct mmc_host *host) static const struct mmc_bus_ops mmc_sd_ops = { .remove = mmc_sd_remove, .detect = mmc_sd_detect, + .sysfs_add = mmc_sd_sysfs_add, + .sysfs_remove = mmc_sd_sysfs_remove, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, }; @@ -599,7 +646,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) mmc_release_host(host); - err = mmc_register_card(host->card); + err = mmc_add_card(host->card); if (err) goto reclaim_host; diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c index 843b1fbba55..a43a96c2281 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c @@ -2,6 +2,7 @@ * linux/drivers/mmc/core/sysfs.c * * Copyright (C) 2003 Russell King, All Rights Reserved. + * Copyright 2007 Pierre Ossman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,226 +19,37 @@ #include <linux/mmc/card.h> #include <linux/mmc/host.h> +#include "bus.h" #include "sysfs.h" -#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) -#define MMC_ATTR(name, fmt, args...) \ -static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct mmc_card *card = dev_to_mmc_card(dev); \ - return sprintf(buf, fmt, args); \ -} - -MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], - card->raw_cid[2], card->raw_cid[3]); -MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], - card->raw_csd[2], card->raw_csd[3]); -MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); -MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); -MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); -MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); -MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid); -MMC_ATTR(name, "%s\n", card->cid.prod_name); -MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid); -MMC_ATTR(serial, "0x%08x\n", card->cid.serial); - -#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) - -static struct device_attribute mmc_dev_attrs[] = { - MMC_ATTR_RO(cid), - MMC_ATTR_RO(csd), - MMC_ATTR_RO(date), - MMC_ATTR_RO(fwrev), - MMC_ATTR_RO(hwrev), - MMC_ATTR_RO(manfid), - MMC_ATTR_RO(name), - MMC_ATTR_RO(oemid), - MMC_ATTR_RO(serial), - __ATTR_NULL -}; - -static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr); - - -static void mmc_release_card(struct device *dev) +int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) { - struct mmc_card *card = dev_to_mmc_card(dev); - - kfree(card); -} - -/* - * This currently matches any MMC driver to any MMC card - drivers - * themselves make the decision whether to drive this card in their - * probe method. - */ -static int mmc_bus_match(struct device *dev, struct device_driver *drv) -{ - return 1; -} - -static int -mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, - int buf_size) -{ - struct mmc_card *card = dev_to_mmc_card(dev); - char ccc[13]; - int retval = 0, i = 0, length = 0; - -#define add_env(fmt,val) do { \ - retval = add_uevent_var(envp, num_envp, &i, \ - buf, buf_size, &length, \ - fmt, val); \ - if (retval) \ - return retval; \ -} while (0); - - for (i = 0; i < 12; i++) - ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0'; - ccc[12] = '\0'; + int error = 0; + int i; - add_env("MMC_CCC=%s", ccc); - add_env("MMC_MANFID=%06x", card->cid.manfid); - add_env("MMC_NAME=%s", mmc_card_name(card)); - add_env("MMC_OEMID=%04x", card->cid.oemid); -#undef add_env - envp[i] = NULL; - - return 0; -} - -static int mmc_bus_suspend(struct device *dev, pm_message_t state) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); - int ret = 0; - - if (dev->driver && drv->suspend) - ret = drv->suspend(card, state); - return ret; -} - -static int mmc_bus_resume(struct device *dev) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); - int ret = 0; - - if (dev->driver && drv->resume) - ret = drv->resume(card); - return ret; -} - -static int mmc_bus_probe(struct device *dev) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); - - return drv->probe(card); -} - -static int mmc_bus_remove(struct device *dev) -{ - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); - - drv->remove(card); - - return 0; -} - -static struct bus_type mmc_bus_type = { - .name = "mmc", - .dev_attrs = mmc_dev_attrs, - .match = mmc_bus_match, - .uevent = mmc_bus_uevent, - .probe = mmc_bus_probe, - .remove = mmc_bus_remove, - .suspend = mmc_bus_suspend, - .resume = mmc_bus_resume, -}; - -/** - * mmc_register_driver - register a media driver - * @drv: MMC media driver - */ -int mmc_register_driver(struct mmc_driver *drv) -{ - drv->drv.bus = &mmc_bus_type; - return driver_register(&drv->drv); -} - -EXPORT_SYMBOL(mmc_register_driver); - -/** - * mmc_unregister_driver - unregister a media driver - * @drv: MMC media driver - */ -void mmc_unregister_driver(struct mmc_driver *drv) -{ - drv->drv.bus = &mmc_bus_type; - driver_unregister(&drv->drv); -} - -EXPORT_SYMBOL(mmc_unregister_driver); - - -/* - * Internal function. Initialise a MMC card structure. - */ -void mmc_init_card(struct mmc_card *card, struct mmc_host *host) -{ - memset(card, 0, sizeof(struct mmc_card)); - card->host = host; - device_initialize(&card->dev); - card->dev.parent = mmc_classdev(host); - card->dev.bus = &mmc_bus_type; - card->dev.release = mmc_release_card; -} - -/* - * Internal function. Register a new MMC card with the driver model. - */ -int mmc_register_card(struct mmc_card *card) -{ - int ret; - - snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), - "%s:%04x", mmc_hostname(card->host), card->rca); - - ret = device_add(&card->dev); - if (ret == 0) { - if (mmc_card_sd(card)) { - ret = device_create_file(&card->dev, &mmc_dev_attr_scr); - if (ret) - device_del(&card->dev); + for (i = 0; attr_name(attrs[i]); i++) { + error = device_create_file(&card->dev, &attrs[i]); + if (error) { + while (--i >= 0) + device_remove_file(&card->dev, &attrs[i]); + break; } } - if (ret == 0) - mmc_card_set_present(card); - return ret; + + return error; } -/* - * Internal function. Unregister a new MMC card with the - * driver model, and (eventually) free it. - */ -void mmc_remove_card(struct mmc_card *card) +void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs) { - if (mmc_card_present(card)) { - if (mmc_card_sd(card)) - device_remove_file(&card->dev, &mmc_dev_attr_scr); - - device_del(&card->dev); - } + int i; - put_device(&card->dev); + for (i = 0; attr_name(attrs[i]); i++) + device_remove_file(&card->dev, &attrs[i]); } - static void mmc_host_classdev_release(struct device *dev) { struct mmc_host *host = cls_dev_to_mmc_host(dev); @@ -340,11 +152,11 @@ static int __init mmc_init(void) if (!workqueue) return -ENOMEM; - ret = bus_register(&mmc_bus_type); + ret = mmc_register_bus(); if (ret == 0) { ret = class_register(&mmc_host_class); if (ret) - bus_unregister(&mmc_bus_type); + mmc_unregister_bus(); } return ret; } @@ -352,7 +164,7 @@ static int __init mmc_init(void) static void __exit mmc_exit(void) { class_unregister(&mmc_host_class); - bus_unregister(&mmc_bus_type); + mmc_unregister_bus(); destroy_workqueue(workqueue); } diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h index 80e29b35828..2a326a5b83c 100644 --- a/drivers/mmc/core/sysfs.h +++ b/drivers/mmc/core/sysfs.h @@ -11,9 +11,17 @@ #ifndef _MMC_CORE_SYSFS_H #define _MMC_CORE_SYSFS_H -void mmc_init_card(struct mmc_card *card, struct mmc_host *host); -int mmc_register_card(struct mmc_card *card); -void mmc_remove_card(struct mmc_card *card); +#define MMC_ATTR_FN(name, fmt, args...) \ +static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct mmc_card *card = container_of(dev, struct mmc_card, dev);\ + return sprintf(buf, fmt, args); \ +} + +#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) + +int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs); +void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs); struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev); int mmc_add_host_sysfs(struct mmc_host *host); |