From d366b6436386875b1310ce8f70e3f9dea4647bac Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 19 Aug 2005 09:40:08 +0100 Subject: [PATCH 1/4] [MMC] Add mmc_hostname() macro mmc_hostname() returns a pointer to the hostname for the mmc_host. Signed-off-by: Russell King --- drivers/mmc/mmc.c | 6 +++--- drivers/mmc/mmc_sysfs.c | 2 +- drivers/mmc/mmci.c | 4 ++-- drivers/mmc/wbsd.c | 2 +- include/linux/mmc/host.h | 1 + 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index eeb9f6668e69..e02e5df80be9 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -361,7 +361,7 @@ static void mmc_decode_cid(struct mmc_card *card) default: printk("%s: card has unknown MMCA version %d\n", - card->host->host_name, card->csd.mmca_vsn); + mmc_hostname(card->host), card->csd.mmca_vsn); mmc_card_set_bad(card); break; } @@ -383,7 +383,7 @@ static void mmc_decode_csd(struct mmc_card *card) csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 1 && csd_struct != 2) { printk("%s: unrecognised CSD structure version %d\n", - card->host->host_name, csd_struct); + mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } @@ -551,7 +551,7 @@ static void mmc_discover_cards(struct mmc_host *host) } if (err != MMC_ERR_NONE) { printk(KERN_ERR "%s: error requesting CID: %d\n", - host->host_name, err); + mmc_hostname(host), err); break; } diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 5556cd3b5559..3a6b325a9149 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -206,7 +206,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) int mmc_register_card(struct mmc_card *card) { snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), - "%s:%04x", card->host->host_name, card->rca); + "%s:%04x", mmc_hostname(card->host), card->rca); return device_add(&card->dev); } diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 7a42966d755b..716c4ef4faf6 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -34,7 +34,7 @@ #ifdef CONFIG_MMC_DEBUG #define DBG(host,fmt,args...) \ - pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args) + pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) #else #define DBG(host,fmt,args...) do { } while (0) #endif @@ -541,7 +541,7 @@ static int mmci_probe(struct amba_device *dev, void *id) mmc_add_host(mmc); printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n", - mmc->host_name, amba_rev(dev), amba_config(dev), + mmc_hostname(mmc), amba_rev(dev), amba_config(dev), dev->res.start, dev->irq[0], dev->irq[1]); init_timer(&host->timer); diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 974f2f36bdbe..402c2d661fb2 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1796,7 +1796,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, mmc_add_host(mmc); - printk(KERN_INFO "%s: W83L51xD", mmc->host_name); + printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc)); if (host->chip_id != 0) printk(" id %x", (int)host->chip_id); printk(" at 0x%x irq %d", (int)host->base, (int)host->irq); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index f90f674eb3b0..307862308596 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -97,6 +97,7 @@ extern void mmc_free_host(struct mmc_host *); #define mmc_priv(x) ((void *)((x) + 1)) #define mmc_dev(x) ((x)->dev) +#define mmc_hostname(x) ((x)->host_name) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_resume_host(struct mmc_host *); From 00b137cfda5276b3d2c87d44236fe4c5ee68b405 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 19 Aug 2005 09:41:24 +0100 Subject: [PATCH 2/4] [MMC] Add MMC class devices Create a mmc_host class to allow enumeration of MMC host controllers even though they have no card(s) inserted. Patch based on work by Pierre Ossman. Signed-off-by: Russell King --- drivers/mmc/mmc.c | 23 ++++++------- drivers/mmc/mmc.h | 5 +++ drivers/mmc/mmc_sysfs.c | 72 +++++++++++++++++++++++++++++++++++++++- include/linux/mmc/host.h | 1 + 4 files changed, 87 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index e02e5df80be9..3c5904834fe8 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -796,17 +796,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { struct mmc_host *host; - host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); + host = mmc_alloc_host_sysfs(extra, dev); if (host) { - memset(host, 0, sizeof(struct mmc_host) + extra); - spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_LIST_HEAD(&host->cards); INIT_WORK(&host->detect, mmc_rescan, host); - host->dev = dev; - /* * By default, hosts do not support SGIO or large requests. * They have to set these according to their abilities. @@ -828,15 +824,15 @@ EXPORT_SYMBOL(mmc_alloc_host); */ int mmc_add_host(struct mmc_host *host) { - static unsigned int host_num; + int ret; - snprintf(host->host_name, sizeof(host->host_name), - "mmc%d", host_num++); + ret = mmc_add_host_sysfs(host); + if (ret == 0) { + mmc_power_off(host); + mmc_detect_change(host); + } - mmc_power_off(host); - mmc_detect_change(host); - - return 0; + return ret; } EXPORT_SYMBOL(mmc_add_host); @@ -859,6 +855,7 @@ void mmc_remove_host(struct mmc_host *host) } mmc_power_off(host); + mmc_remove_host_sysfs(host); } EXPORT_SYMBOL(mmc_remove_host); @@ -872,7 +869,7 @@ EXPORT_SYMBOL(mmc_remove_host); void mmc_free_host(struct mmc_host *host) { flush_scheduled_work(); - kfree(host); + mmc_free_host_sysfs(host); } EXPORT_SYMBOL(mmc_free_host); diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h index b498dffe0b11..97bae00292fa 100644 --- a/drivers/mmc/mmc.h +++ b/drivers/mmc/mmc.h @@ -13,4 +13,9 @@ 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); + +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); #endif diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 3a6b325a9149..96c192057df3 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -20,6 +20,7 @@ #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) \ @@ -224,13 +225,82 @@ void mmc_remove_card(struct mmc_card *card) } +static void mmc_host_classdev_release(struct class_device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + kfree(host); +} + +static struct class mmc_host_class = { + .name = "mmc_host", + .release = mmc_host_classdev_release, +}; + +/* + * 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->dev = dev; + host->class_dev.dev = host->dev; + host->class_dev.class = &mmc_host_class; + 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) +{ + static unsigned int host_num; + + snprintf(host->host_name, sizeof(host->host_name), + "mmc%d", host_num++); + + strlcpy(host->class_dev.class_id, host->host_name, BUS_ID_SIZE); + return class_device_add(&host->class_dev); +} + +/* + * Internal function. Unregister a MMC host with the MMC class. + */ +void mmc_remove_host_sysfs(struct mmc_host *host) +{ + class_device_del(&host->class_dev); +} + +/* + * Internal function. Free a MMC host. + */ +void mmc_free_host_sysfs(struct mmc_host *host) +{ + class_device_put(&host->class_dev); +} + + static int __init mmc_init(void) { - return bus_register(&mmc_bus_type); + int ret = bus_register(&mmc_bus_type); + if (ret == 0) { + ret = class_register(&mmc_host_class); + if (ret) + bus_unregister(&mmc_bus_type); + } + return ret; } static void __exit mmc_exit(void) { + class_unregister(&mmc_host_class); bus_unregister(&mmc_bus_type); } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 307862308596..a74a810a1302 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -63,6 +63,7 @@ struct device; struct mmc_host { struct device *dev; + struct class_device class_dev; struct mmc_host_ops *ops; unsigned int f_min; unsigned int f_max; From 1ad434d7cf5f490c71cfbbb2fb91076c01c8704e Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 19 Aug 2005 09:42:21 +0100 Subject: [PATCH 3/4] [MMC] Use class device name for mmc host name There's no point in having the host name duplicated between the mmc_host structure and the encapsulated class device structure. Signed-off-by: Russell King --- drivers/mmc/mmc_sysfs.c | 3 +-- include/linux/mmc/host.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 96c192057df3..34fa4a3a02d5 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -263,10 +263,9 @@ int mmc_add_host_sysfs(struct mmc_host *host) { static unsigned int host_num; - snprintf(host->host_name, sizeof(host->host_name), + snprintf(host->class_dev.class_id, BUS_ID_SIZE, "mmc%d", host_num++); - strlcpy(host->class_dev.class_id, host->host_name, BUS_ID_SIZE); return class_device_add(&host->class_dev); } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index a74a810a1302..113cc27865f0 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -68,7 +68,6 @@ struct mmc_host { unsigned int f_min; unsigned int f_max; u32 ocr_avail; - char host_name[8]; /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ @@ -98,7 +97,7 @@ extern void mmc_free_host(struct mmc_host *); #define mmc_priv(x) ((void *)((x) + 1)) #define mmc_dev(x) ((x)->dev) -#define mmc_hostname(x) ((x)->host_name) +#define mmc_hostname(x) ((x)->class_dev.class_id) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_resume_host(struct mmc_host *); From dce773771834221817e2d359a7e07a618ba08807 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 19 Aug 2005 09:42:52 +0100 Subject: [PATCH 4/4] [MMC] Use an IDR for host name indicies Signed-off-by: Russell King --- drivers/mmc/mmc_sysfs.c | 21 +++++++++++++++++++-- include/linux/mmc/host.h | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 34fa4a3a02d5..ad8949810fc5 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -236,6 +237,9 @@ static struct class mmc_host_class = { .release = mmc_host_classdev_release, }; +static DEFINE_IDR(mmc_host_idr); +static DEFINE_SPINLOCK(mmc_host_lock); + /* * Internal function. Allocate a new MMC host. */ @@ -261,10 +265,19 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) */ int mmc_add_host_sysfs(struct mmc_host *host) { - static unsigned int host_num; + 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.class_id, BUS_ID_SIZE, - "mmc%d", host_num++); + "mmc%d", host->index); return class_device_add(&host->class_dev); } @@ -275,6 +288,10 @@ int mmc_add_host_sysfs(struct mmc_host *host) void mmc_remove_host_sysfs(struct mmc_host *host) { class_device_del(&host->class_dev); + + spin_lock(&mmc_host_lock); + idr_remove(&mmc_host_idr, host->index); + spin_unlock(&mmc_host_lock); } /* diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 113cc27865f0..9a0893f3249e 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -64,6 +64,7 @@ struct device; struct mmc_host { struct device *dev; struct class_device class_dev; + int index; struct mmc_host_ops *ops; unsigned int f_min; unsigned int f_max;