diff options
Diffstat (limited to 'drivers/mmc')
-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 54261e3724c..3fdd08c7f14 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -7,6 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y) endif obj-$(CONFIG_MMC) += mmc_core.o -mmc_core-y := core.o sysfs.o bus.o \ +mmc_core-y := core.o sysfs.o bus.o host.o \ mmc.o mmc_ops.o sd.o sd_ops.o diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d876adf4bd4..66e463d100c 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) EXPORT_SYMBOL(mmc_detect_change); -static void mmc_rescan(struct work_struct *work) +void mmc_rescan(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, detect.work); @@ -545,69 +545,13 @@ static void mmc_rescan(struct work_struct *work) } } - -/** - * mmc_alloc_host - initialise the per-host structure. - * @extra: sizeof private data structure - * @dev: pointer to host device model structure - * - * Initialise the per-host structure. - */ -struct mmc_host *mmc_alloc_host(int extra, struct device *dev) -{ - struct mmc_host *host; - - host = mmc_alloc_host_sysfs(extra, dev); - if (host) { - spin_lock_init(&host->lock); - init_waitqueue_head(&host->wq); - INIT_DELAYED_WORK(&host->detect, mmc_rescan); - - /* - * By default, hosts do not support SGIO or large requests. - * They have to set these according to their abilities. - */ - host->max_hw_segs = 1; - host->max_phys_segs = 1; - host->max_seg_size = PAGE_CACHE_SIZE; - - host->max_req_size = PAGE_CACHE_SIZE; - host->max_blk_size = 512; - host->max_blk_count = PAGE_CACHE_SIZE / 512; - } - - return host; -} - -EXPORT_SYMBOL(mmc_alloc_host); - -/** - * mmc_add_host - initialise host hardware - * @host: mmc host - */ -int mmc_add_host(struct mmc_host *host) +void mmc_start_host(struct mmc_host *host) { - int ret; - - ret = mmc_add_host_sysfs(host); - if (ret == 0) { - mmc_power_off(host); - mmc_detect_change(host, 0); - } - - return ret; + mmc_power_off(host); + mmc_detect_change(host, 0); } -EXPORT_SYMBOL(mmc_add_host); - -/** - * mmc_remove_host - remove host hardware - * @host: mmc host - * - * Unregister and remove all cards associated with this host, - * and power down the MMC bus. - */ -void mmc_remove_host(struct mmc_host *host) +void mmc_stop_host(struct mmc_host *host) { #ifdef CONFIG_MMC_DEBUG unsigned long flags; @@ -632,24 +576,8 @@ void mmc_remove_host(struct mmc_host *host) BUG_ON(host->card); mmc_power_off(host); - mmc_remove_host_sysfs(host); } -EXPORT_SYMBOL(mmc_remove_host); - -/** - * mmc_free_host - free the host structure - * @host: mmc host - * - * Free the host once all references to it have been dropped. - */ -void mmc_free_host(struct mmc_host *host) -{ - mmc_free_host_sysfs(host); -} - -EXPORT_SYMBOL(mmc_free_host); - #ifdef CONFIG_PM /** diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 1be86c792a5..ae006b30dd8 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) } } +void mmc_rescan(struct work_struct *work); +void mmc_start_host(struct mmc_host *host); +void mmc_stop_host(struct mmc_host *host); + #endif diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c new file mode 100644 index 00000000000..1433d95c40b --- /dev/null +++ b/drivers/mmc/core/host.c @@ -0,0 +1,156 @@ +/* + * linux/drivers/mmc/core/host.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 host class device management + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/idr.h> +#include <linux/pagemap.h> + +#include <linux/mmc/host.h> + +#include "core.h" +#include "host.h" + +#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) + +static void mmc_host_classdev_release(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + kfree(host); +} + +static struct class mmc_host_class = { + .name = "mmc_host", + .dev_release = mmc_host_classdev_release, +}; + +int mmc_register_host_class(void) +{ + return class_register(&mmc_host_class); +} + +void mmc_unregister_host_class(void) +{ + class_unregister(&mmc_host_class); +} + +static DEFINE_IDR(mmc_host_idr); +static DEFINE_SPINLOCK(mmc_host_lock); + +/** + * mmc_alloc_host - initialise the per-host structure. + * @extra: sizeof private data structure + * @dev: pointer to host device model structure + * + * Initialise the per-host structure. + */ +struct mmc_host *mmc_alloc_host(int extra, struct device *dev) +{ + struct mmc_host *host; + + host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); + if (!host) + return NULL; + + memset(host, 0, sizeof(struct mmc_host) + extra); + + host->parent = dev; + host->class_dev.parent = dev; + host->class_dev.class = &mmc_host_class; + device_initialize(&host->class_dev); + + spin_lock_init(&host->lock); + init_waitqueue_head(&host->wq); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); + + /* + * By default, hosts do not support SGIO or large requests. + * They have to set these according to their abilities. + */ + host->max_hw_segs = 1; + host->max_phys_segs = 1; + host->max_seg_size = PAGE_CACHE_SIZE; + + host->max_req_size = PAGE_CACHE_SIZE; + host->max_blk_size = 512; + host->max_blk_count = PAGE_CACHE_SIZE / 512; + + return host; +} + +EXPORT_SYMBOL(mmc_alloc_host); + +/** + * mmc_add_host - initialise host hardware + * @host: mmc host + */ +int mmc_add_host(struct mmc_host *host) +{ + int err; + + if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) + return -ENOMEM; + + spin_lock(&mmc_host_lock); + err = idr_get_new(&mmc_host_idr, host, &host->index); + spin_unlock(&mmc_host_lock); + if (err) + return err; + + snprintf(host->class_dev.bus_id, BUS_ID_SIZE, + "mmc%d", host->index); + + err = device_add(&host->class_dev); + if (err) + return err; + + mmc_start_host(host); + + return 0; +} + +EXPORT_SYMBOL(mmc_add_host); + +/** + * mmc_remove_host - remove host hardware + * @host: mmc host + * + * Unregister and remove all cards associated with this host, + * and power down the MMC bus. + */ +void mmc_remove_host(struct mmc_host *host) +{ + mmc_stop_host(host); + + device_del(&host->class_dev); + + spin_lock(&mmc_host_lock); + idr_remove(&mmc_host_idr, host->index); + spin_unlock(&mmc_host_lock); +} + +EXPORT_SYMBOL(mmc_remove_host); + +/** + * mmc_free_host - free the host structure + * @host: mmc host + * + * Free the host once all references to it have been dropped. + */ +void mmc_free_host(struct mmc_host *host) +{ + put_device(&host->class_dev); +} + +EXPORT_SYMBOL(mmc_free_host); + diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h new file mode 100644 index 00000000000..c2dc3d2d9f9 --- /dev/null +++ b/drivers/mmc/core/host.h @@ -0,0 +1,18 @@ +/* + * linux/drivers/mmc/core/host.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_HOST_H +#define _MMC_CORE_HOST_H + +int mmc_register_host_class(void); +void mmc_unregister_host_class(void); + +#endif + diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c index a43a96c2281..fbf99f9a0b8 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c @@ -20,11 +20,9 @@ #include <linux/mmc/host.h> #include "bus.h" +#include "host.h" #include "sysfs.h" -#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) - int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) { int error = 0; @@ -50,82 +48,6 @@ void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs) 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); - kfree(host); -} - -static struct class mmc_host_class = { - .name = "mmc_host", - .dev_release = mmc_host_classdev_release, -}; - -static DEFINE_IDR(mmc_host_idr); -static DEFINE_SPINLOCK(mmc_host_lock); - -/* - * Internal function. Allocate a new MMC host. - */ -struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) -{ - struct mmc_host *host; - - host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); - if (host) { - memset(host, 0, sizeof(struct mmc_host) + extra); - - host->parent = dev; - host->class_dev.parent = dev; - host->class_dev.class = &mmc_host_class; - device_initialize(&host->class_dev); - } - - return host; -} - -/* - * Internal function. Register a new MMC host with the MMC class. - */ -int mmc_add_host_sysfs(struct mmc_host *host) -{ - int err; - - if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) - return -ENOMEM; - - spin_lock(&mmc_host_lock); - err = idr_get_new(&mmc_host_idr, host, &host->index); - spin_unlock(&mmc_host_lock); - if (err) - return err; - - snprintf(host->class_dev.bus_id, BUS_ID_SIZE, - "mmc%d", host->index); - - return device_add(&host->class_dev); -} - -/* - * Internal function. Unregister a MMC host with the MMC class. - */ -void mmc_remove_host_sysfs(struct mmc_host *host) -{ - device_del(&host->class_dev); - - spin_lock(&mmc_host_lock); - idr_remove(&mmc_host_idr, host->index); - spin_unlock(&mmc_host_lock); -} - -/* - * Internal function. Free a MMC host. - */ -void mmc_free_host_sysfs(struct mmc_host *host) -{ - put_device(&host->class_dev); -} - static struct workqueue_struct *workqueue; /* @@ -154,7 +76,7 @@ static int __init mmc_init(void) ret = mmc_register_bus(); if (ret == 0) { - ret = class_register(&mmc_host_class); + ret = mmc_register_host_class(); if (ret) mmc_unregister_bus(); } @@ -163,7 +85,7 @@ static int __init mmc_init(void) static void __exit mmc_exit(void) { - class_unregister(&mmc_host_class); + mmc_unregister_host_class(); mmc_unregister_bus(); destroy_workqueue(workqueue); } diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h index 2a326a5b83c..2f60c79b203 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 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); -void mmc_remove_host_sysfs(struct mmc_host *host); -void mmc_free_host_sysfs(struct mmc_host *host); - int mmc_schedule_work(struct work_struct *work); int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); void mmc_flush_scheduled_work(void); |