sdio: add new function for RAW (Read after Write) operation
[safe/jmp/linux-2.6] / drivers / mmc / core / bus.c
index fe0e785..49d9dca 100644 (file)
 
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include "sysfs.h"
 #include "core.h"
+#include "sdio_cis.h"
 #include "bus.h"
 
 #define dev_to_mmc_card(d)     container_of(d, struct mmc_card, dev)
@@ -34,13 +35,15 @@ static ssize_t mmc_type_show(struct device *dev,
                return sprintf(buf, "MMC\n");
        case MMC_TYPE_SD:
                return sprintf(buf, "SD\n");
+       case MMC_TYPE_SDIO:
+               return sprintf(buf, "SDIO\n");
        default:
                return -EFAULT;
        }
 }
 
 static struct device_attribute mmc_dev_attrs[] = {
-       MMC_ATTR_RO(type),
+       __ATTR(type, S_IRUGO, mmc_type_show, NULL),
        __ATTR_NULL,
 };
 
@@ -55,36 +58,43 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 }
 
 static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
-               int buf_size)
+mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        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);
+       const char *type;
+       int retval = 0;
 
        switch (card->type) {
        case MMC_TYPE_MMC:
-               add_env("MMC_TYPE=%s", "MMC");
+               type = "MMC";
                break;
        case MMC_TYPE_SD:
-               add_env("MMC_TYPE=%s", "SD");
+               type = "SD";
+               break;
+       case MMC_TYPE_SDIO:
+               type = "SDIO";
                break;
+       default:
+               type = NULL;
        }
 
-       add_env("MMC_NAME=%s", mmc_card_name(card));
+       if (type) {
+               retval = add_uevent_var(env, "MMC_TYPE=%s", type);
+               if (retval)
+                       return retval;
+       }
 
-#undef add_env
+       retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
+       if (retval)
+               return retval;
 
-       envp[i] = NULL;
+       /*
+        * Request the mmc_block device.  Note: that this is a direct request
+        * for the module it carries no information as to what is inserted.
+        */
+       retval = add_uevent_var(env, "MODALIAS=mmc:block");
 
-       return 0;
+       return retval;
 }
 
 static int mmc_bus_probe(struct device *dev)
@@ -176,22 +186,25 @@ static void mmc_release_card(struct device *dev)
 {
        struct mmc_card *card = dev_to_mmc_card(dev);
 
+       sdio_free_common_cis(card);
+
+       if (card->info)
+               kfree(card->info);
+
        kfree(card);
 }
 
 /*
  * Allocate and initialise a new MMC card structure.
  */
-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
 {
        struct mmc_card *card;
 
-       card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+       card = kzalloc(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);
@@ -199,6 +212,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host)
        card->dev.parent = mmc_classdev(host);
        card->dev.bus = &mmc_bus_type;
        card->dev.release = mmc_release_card;
+       card->dev.type = type;
 
        return card;
 }
@@ -211,8 +225,7 @@ int mmc_add_card(struct mmc_card *card)
        int ret;
        const char *type;
 
-       snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-                "%s:%04x", mmc_hostname(card->host), card->rca);
+       dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
 
        switch (card->type) {
        case MMC_TYPE_MMC:
@@ -223,33 +236,33 @@ int mmc_add_card(struct mmc_card *card)
                if (mmc_card_blockaddr(card))
                        type = "SDHC";
                break;
+       case MMC_TYPE_SDIO:
+               type = "SDIO";
+               break;
        default:
                type = "?";
                break;
        }
 
-       printk(KERN_INFO "%s: new %s%s card at address %04x\n",
-               mmc_hostname(card->host),
-               mmc_card_highspeed(card) ? "high speed " : "",
-               type, card->rca);
-
-       card->dev.uevent_suppress = 1;
+       if (mmc_host_is_spi(card->host)) {
+               printk(KERN_INFO "%s: new %s%s card on SPI\n",
+                       mmc_hostname(card->host),
+                       mmc_card_highspeed(card) ? "high speed " : "",
+                       type);
+       } else {
+               printk(KERN_INFO "%s: new %s%s card at address %04x\n",
+                       mmc_hostname(card->host),
+                       mmc_card_highspeed(card) ? "high speed " : "",
+                       type, card->rca);
+       }
 
        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);
+#ifdef CONFIG_DEBUG_FS
+       mmc_add_card_debugfs(card);
+#endif
 
        mmc_card_set_present(card);
 
@@ -262,12 +275,18 @@ int mmc_add_card(struct mmc_card *card)
  */
 void mmc_remove_card(struct mmc_card *card)
 {
-       if (mmc_card_present(card)) {
-               printk(KERN_INFO "%s: card %04x removed\n",
-                       mmc_hostname(card->host), card->rca);
+#ifdef CONFIG_DEBUG_FS
+       mmc_remove_card_debugfs(card);
+#endif
 
-               if (card->host->bus_ops->sysfs_remove)
-                       card->host->bus_ops->sysfs_remove(card->host, card);
+       if (mmc_card_present(card)) {
+               if (mmc_host_is_spi(card->host)) {
+                       printk(KERN_INFO "%s: SPI card removed\n",
+                               mmc_hostname(card->host));
+               } else {
+                       printk(KERN_INFO "%s: card %04x removed\n",
+                               mmc_hostname(card->host), card->rca);
+               }
                device_del(&card->dev);
        }