From 4101c16a910b15afd190c6bc7d45864461cf5c25 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 19 May 2007 13:39:01 +0200 Subject: 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 --- drivers/mmc/core/sysfs.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/core/sysfs.h') diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h index 80e29b358282..2a326a5b83c6 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); -- cgit v1.2.3 From b93931a61a119575f84c33af2438b9384fde9eb7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 19 May 2007 14:06:24 +0200 Subject: mmc: refactor host class handling Move basic host class device handling to its own file for clarity. Signed-off-by: Pierre Ossman --- drivers/mmc/core/Makefile | 2 +- drivers/mmc/core/core.c | 82 ++---------------------- drivers/mmc/core/core.h | 4 ++ drivers/mmc/core/host.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/host.h | 18 ++++++ drivers/mmc/core/sysfs.c | 84 +------------------------ drivers/mmc/core/sysfs.h | 5 -- 7 files changed, 187 insertions(+), 164 deletions(-) create mode 100644 drivers/mmc/core/host.c create mode 100644 drivers/mmc/core/host.h (limited to 'drivers/mmc/core/sysfs.h') diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 54261e3724c4..3fdd08c7f143 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 d876adf4bd4e..66e463d100c5 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 1be86c792a52..ae006b30dd86 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 000000000000..1433d95c40bb --- /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 +#include +#include +#include + +#include + +#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 000000000000..c2dc3d2d9f9a --- /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 a43a96c22811..fbf99f9a0b83 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c @@ -20,11 +20,9 @@ #include #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 2a326a5b83c6..2f60c79b203b 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); -- cgit v1.2.3 From ffce2e7e7060c949ccd703dacc9b3dd81b377373 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 19 May 2007 14:32:22 +0200 Subject: mmc: move layer init and workqueue to core file Signed-off-by: Pierre Ossman --- drivers/mmc/core/core.c | 49 +++++++++++++++++++++++++++++++++++++++++++++- drivers/mmc/core/sysfs.c | 51 ------------------------------------------------ drivers/mmc/core/sysfs.h | 4 ---- 3 files changed, 48 insertions(+), 56 deletions(-) (limited to 'drivers/mmc/core/sysfs.h') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 66e463d100c5..b5d8a6d90cca 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -27,7 +27,8 @@ #include #include "core.h" -#include "sysfs.h" +#include "bus.h" +#include "host.h" #include "mmc_ops.h" #include "sd_ops.h" @@ -35,6 +36,25 @@ extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr); extern int mmc_attach_sd(struct mmc_host *host, u32 ocr); +static struct workqueue_struct *workqueue; + +/* + * Internal function. Schedule delayed work in the MMC work queue. + */ +static int mmc_schedule_delayed_work(struct delayed_work *work, + unsigned long delay) +{ + return queue_delayed_work(workqueue, work, delay); +} + +/* + * Internal function. Flush all scheduled work from the MMC work queue. + */ +static void mmc_flush_scheduled_work(void) +{ + flush_workqueue(workqueue); +} + /** * mmc_request_done - finish processing an MMC request * @host: MMC host which completed request @@ -638,4 +658,31 @@ EXPORT_SYMBOL(mmc_resume_host); #endif +static int __init mmc_init(void) +{ + int ret; + + workqueue = create_singlethread_workqueue("kmmcd"); + if (!workqueue) + return -ENOMEM; + + ret = mmc_register_bus(); + if (ret == 0) { + ret = mmc_register_host_class(); + if (ret) + mmc_unregister_bus(); + } + return ret; +} + +static void __exit mmc_exit(void) +{ + mmc_unregister_host_class(); + mmc_unregister_bus(); + destroy_workqueue(workqueue); +} + +module_init(mmc_init); +module_exit(mmc_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c index fbf99f9a0b83..00a97e70f914 100644 --- a/drivers/mmc/core/sysfs.c +++ b/drivers/mmc/core/sysfs.c @@ -10,17 +10,10 @@ * * MMC sysfs/driver model support. */ -#include -#include #include -#include -#include #include -#include -#include "bus.h" -#include "host.h" #include "sysfs.h" int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) @@ -48,47 +41,3 @@ void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs) device_remove_file(&card->dev, &attrs[i]); } -static struct workqueue_struct *workqueue; - -/* - * Internal function. Schedule delayed work in the MMC work queue. - */ -int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) -{ - return queue_delayed_work(workqueue, work, delay); -} - -/* - * Internal function. Flush all scheduled work from the MMC work queue. - */ -void mmc_flush_scheduled_work(void) -{ - flush_workqueue(workqueue); -} - -static int __init mmc_init(void) -{ - int ret; - - workqueue = create_singlethread_workqueue("kmmcd"); - if (!workqueue) - return -ENOMEM; - - ret = mmc_register_bus(); - if (ret == 0) { - ret = mmc_register_host_class(); - if (ret) - mmc_unregister_bus(); - } - return ret; -} - -static void __exit mmc_exit(void) -{ - mmc_unregister_host_class(); - mmc_unregister_bus(); - destroy_workqueue(workqueue); -} - -module_init(mmc_init); -module_exit(mmc_exit); diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h index 2f60c79b203b..4b8f670bd10f 100644 --- a/drivers/mmc/core/sysfs.h +++ b/drivers/mmc/core/sysfs.h @@ -23,8 +23,4 @@ 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); -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); - #endif -- cgit v1.2.3