]> err.no Git - linux-2.6/blobdiff - drivers/mmc/core/sdio_bus.c
Merge branch 'master' of git://git.infradead.org/~dedekind/ubi-2.6
[linux-2.6] / drivers / mmc / core / sdio_bus.c
index c834f515088847c60504c17642b6ff4f8906c779..0713a8c71e54b2980d88127644e14cd9ed87f748 100644 (file)
 #define dev_to_sdio_func(d)    container_of(d, struct sdio_func, dev)
 #define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
 
+/* show configuration fields */
+#define sdio_config_attr(field, format_string)                         \
+static ssize_t                                                         \
+field##_show(struct device *dev, struct device_attribute *attr, char *buf)                             \
+{                                                                      \
+       struct sdio_func *func;                                         \
+                                                                       \
+       func = dev_to_sdio_func (dev);                                  \
+       return sprintf (buf, format_string, func->field);               \
+}
+
+sdio_config_attr(class, "0x%02x\n");
+sdio_config_attr(vendor, "0x%04x\n");
+sdio_config_attr(device, "0x%04x\n");
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct sdio_func *func = dev_to_sdio_func (dev);
+
+       return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
+                       func->class, func->vendor, func->device);
+}
+
+static struct device_attribute sdio_dev_attrs[] = {
+       __ATTR_RO(class),
+       __ATTR_RO(vendor),
+       __ATTR_RO(device),
+       __ATTR_RO(modalias),
+       __ATTR_NULL,
+};
+
 static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
        const struct sdio_device_id *id)
 {
@@ -97,11 +128,20 @@ static int sdio_bus_probe(struct device *dev)
        struct sdio_driver *drv = to_sdio_driver(dev->driver);
        struct sdio_func *func = dev_to_sdio_func(dev);
        const struct sdio_device_id *id;
+       int ret;
 
        id = sdio_match_device(func, drv);
        if (!id)
                return -ENODEV;
 
+       /* Set the default block size so the driver is sure it's something
+        * sensible. */
+       sdio_claim_host(func);
+       ret = sdio_set_block_size(func, 0);
+       sdio_release_host(func);
+       if (ret)
+               return ret;
+
        return drv->probe(func, id);
 }
 
@@ -112,11 +152,20 @@ static int sdio_bus_remove(struct device *dev)
 
        drv->remove(func);
 
+       if (func->irq_handler) {
+               printk(KERN_WARNING "WARNING: driver %s did not remove "
+                       "its interrupt handler!\n", drv->name);
+               sdio_claim_host(func);
+               sdio_release_irq(func);
+               sdio_release_host(func);
+       }
+
        return 0;
 }
 
 static struct bus_type sdio_bus_type = {
        .name           = "sdio",
+       .dev_attrs      = sdio_dev_attrs,
        .match          = sdio_bus_match,
        .uevent         = sdio_bus_uevent,
        .probe          = sdio_bus_probe,
@@ -162,6 +211,9 @@ static void sdio_release_func(struct device *dev)
 
        sdio_free_func_cis(func);
 
+       if (func->info)
+               kfree(func->info);
+
        kfree(func);
 }
 
@@ -172,12 +224,10 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
 {
        struct sdio_func *func;
 
-       func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);
+       func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
        if (!func)
                return ERR_PTR(-ENOMEM);
 
-       memset(func, 0, sizeof(struct sdio_func));
-
        func->card = card;
 
        device_initialize(&func->dev);