瀏覽代碼

Merge HEAD from master.kernel.org:/home/rmk/linux-2.6-mmc.git

Linus Torvalds 20 年之前
父節點
當前提交
9ab7486e44
共有 6 個文件被更改,包括 112 次插入22 次删除
  1. 13 16
      drivers/mmc/mmc.c
  2. 5 0
      drivers/mmc/mmc.h
  3. 88 2
      drivers/mmc/mmc_sysfs.c
  4. 2 2
      drivers/mmc/mmci.c
  5. 1 1
      drivers/mmc/wbsd.c
  6. 3 1
      include/linux/mmc/host.h

+ 13 - 16
drivers/mmc/mmc.c

@@ -361,7 +361,7 @@ static void mmc_decode_cid(struct mmc_card *card)
 
 
 	default:
 	default:
 		printk("%s: card has unknown MMCA version %d\n",
 		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);
 		mmc_card_set_bad(card);
 		break;
 		break;
 	}
 	}
@@ -383,7 +383,7 @@ static void mmc_decode_csd(struct mmc_card *card)
 	csd_struct = UNSTUFF_BITS(resp, 126, 2);
 	csd_struct = UNSTUFF_BITS(resp, 126, 2);
 	if (csd_struct != 1 && csd_struct != 2) {
 	if (csd_struct != 1 && csd_struct != 2) {
 		printk("%s: unrecognised CSD structure version %d\n",
 		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);
 		mmc_card_set_bad(card);
 		return;
 		return;
 	}
 	}
@@ -551,7 +551,7 @@ static void mmc_discover_cards(struct mmc_host *host)
 		}
 		}
 		if (err != MMC_ERR_NONE) {
 		if (err != MMC_ERR_NONE) {
 			printk(KERN_ERR "%s: error requesting CID: %d\n",
 			printk(KERN_ERR "%s: error requesting CID: %d\n",
-				host->host_name, err);
+				mmc_hostname(host), err);
 			break;
 			break;
 		}
 		}
 
 
@@ -796,17 +796,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 {
 {
 	struct mmc_host *host;
 	struct mmc_host *host;
 
 
-	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+	host = mmc_alloc_host_sysfs(extra, dev);
 	if (host) {
 	if (host) {
-		memset(host, 0, sizeof(struct mmc_host) + extra);
-
 		spin_lock_init(&host->lock);
 		spin_lock_init(&host->lock);
 		init_waitqueue_head(&host->wq);
 		init_waitqueue_head(&host->wq);
 		INIT_LIST_HEAD(&host->cards);
 		INIT_LIST_HEAD(&host->cards);
 		INIT_WORK(&host->detect, mmc_rescan, host);
 		INIT_WORK(&host->detect, mmc_rescan, host);
 
 
-		host->dev = dev;
-
 		/*
 		/*
 		 * By default, hosts do not support SGIO or large requests.
 		 * By default, hosts do not support SGIO or large requests.
 		 * They have to set these according to their abilities.
 		 * 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)
 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++);
-
-	mmc_power_off(host);
-	mmc_detect_change(host);
+	ret = mmc_add_host_sysfs(host);
+	if (ret == 0) {
+		mmc_power_off(host);
+		mmc_detect_change(host);
+	}
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 EXPORT_SYMBOL(mmc_add_host);
 EXPORT_SYMBOL(mmc_add_host);
@@ -859,6 +855,7 @@ void mmc_remove_host(struct mmc_host *host)
 	}
 	}
 
 
 	mmc_power_off(host);
 	mmc_power_off(host);
+	mmc_remove_host_sysfs(host);
 }
 }
 
 
 EXPORT_SYMBOL(mmc_remove_host);
 EXPORT_SYMBOL(mmc_remove_host);
@@ -872,7 +869,7 @@ EXPORT_SYMBOL(mmc_remove_host);
 void mmc_free_host(struct mmc_host *host)
 void mmc_free_host(struct mmc_host *host)
 {
 {
 	flush_scheduled_work();
 	flush_scheduled_work();
-	kfree(host);
+	mmc_free_host_sysfs(host);
 }
 }
 
 
 EXPORT_SYMBOL(mmc_free_host);
 EXPORT_SYMBOL(mmc_free_host);

+ 5 - 0
drivers/mmc/mmc.h

@@ -13,4 +13,9 @@
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_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
 #endif

+ 88 - 2
drivers/mmc/mmc_sysfs.c

@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/idr.h>
 
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/host.h>
@@ -20,6 +21,7 @@
 
 
 #define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
 #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 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...)					\
 #define MMC_ATTR(name, fmt, args...)					\
 static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
 static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
@@ -206,7 +208,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
 int mmc_register_card(struct mmc_card *card)
 int mmc_register_card(struct mmc_card *card)
 {
 {
 	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
 	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);
 	return device_add(&card->dev);
 }
 }
@@ -224,13 +226,97 @@ 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,
+};
+
+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->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)
+{
+	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->index);
+
+	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);
+
+	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)
+{
+	class_device_put(&host->class_dev);
+}
+
+
 static int __init mmc_init(void)
 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)
 static void __exit mmc_exit(void)
 {
 {
+	class_unregister(&mmc_host_class);
 	bus_unregister(&mmc_bus_type);
 	bus_unregister(&mmc_bus_type);
 }
 }
 
 

+ 2 - 2
drivers/mmc/mmci.c

@@ -34,7 +34,7 @@
 
 
 #ifdef CONFIG_MMC_DEBUG
 #ifdef CONFIG_MMC_DEBUG
 #define DBG(host,fmt,args...)	\
 #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
 #else
 #define DBG(host,fmt,args...)	do { } while (0)
 #define DBG(host,fmt,args...)	do { } while (0)
 #endif
 #endif
@@ -541,7 +541,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
 	mmc_add_host(mmc);
 	mmc_add_host(mmc);
 
 
 	printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n",
 	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]);
 		dev->res.start, dev->irq[0], dev->irq[1]);
 
 
 	init_timer(&host->timer);
 	init_timer(&host->timer);

+ 1 - 1
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);
 	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)
 	if (host->chip_id != 0)
 		printk(" id %x", (int)host->chip_id);
 		printk(" id %x", (int)host->chip_id);
 	printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
 	printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);

+ 3 - 1
include/linux/mmc/host.h

@@ -63,11 +63,12 @@ struct device;
 
 
 struct mmc_host {
 struct mmc_host {
 	struct device		*dev;
 	struct device		*dev;
+	struct class_device	class_dev;
+	int			index;
 	struct mmc_host_ops	*ops;
 	struct mmc_host_ops	*ops;
 	unsigned int		f_min;
 	unsigned int		f_min;
 	unsigned int		f_max;
 	unsigned int		f_max;
 	u32			ocr_avail;
 	u32			ocr_avail;
-	char			host_name[8];
 
 
 	/* host specific block data */
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
@@ -97,6 +98,7 @@ extern void mmc_free_host(struct mmc_host *);
 
 
 #define mmc_priv(x)	((void *)((x) + 1))
 #define mmc_priv(x)	((void *)((x) + 1))
 #define mmc_dev(x)	((x)->dev)
 #define mmc_dev(x)	((x)->dev)
+#define mmc_hostname(x)	((x)->class_dev.class_id)
 
 
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
 extern int mmc_resume_host(struct mmc_host *);
 extern int mmc_resume_host(struct mmc_host *);