Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9a08f82b3cc522f727ace580a2aaee5402435bc8
Commit:     9a08f82b3cc522f727ace580a2aaee5402435bc8
Parent:     7616ee95f27a04fd5a6434e9ef4a82cec4b2807c
Author:     David Vrabel <[EMAIL PROTECTED]>
AuthorDate: Wed Aug 8 14:23:48 2007 +0100
Committer:  Pierre Ossman <[EMAIL PROTECTED]>
CommitDate: Sun Sep 23 21:19:26 2007 +0200

    sdio: set the functions' block size
    
    Before a driver is probed, set the function's block size to the default so 
the
    driver is sure the block size is something sensible and it needn't 
explicitly
    set it.
    
    The default block size is the largest that's supported by both the card and
    the host, with a maximum of 512 to ensure aribitrarily sized transfer use 
the
    optimal (least) number of commands.
    
    See http://lkml.org/lkml/2007/8/7/150 for reasons for the block size choice.
    
    Signed-off-by: David Vrabel <[EMAIL PROTECTED]>
    Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
---
 drivers/mmc/core/sdio_bus.c   |    9 +++++++
 drivers/mmc/core/sdio_cis.c   |    2 +-
 drivers/mmc/core/sdio_io.c    |   49 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/sdio_func.h |    5 +++-
 4 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d229020..fcb13fb 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -128,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);
 }
 
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index d050c40..1d03f12 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -79,7 +79,7 @@ static int cistpl_funce_func(struct sdio_func *func,
                return -EINVAL;
 
        /* TPLFE_MAX_BLK_SIZE */
-       func->blksize = buf[12] | (buf[13] << 8);
+       func->max_blksize = buf[12] | (buf[13] << 8);
 
        return 0;
 }
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index ecdb772..c2bad11 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -141,6 +141,55 @@ err:
 EXPORT_SYMBOL_GPL(sdio_disable_func);
 
 /**
+ *     sdio_set_block_size - set the block size of an SDIO function
+ *     @func: SDIO function to change
+ *     @blksz: new block size or 0 to use the default.
+ *
+ *     The default block size is the largest supported by both the function
+ *     and the host, with a maximum of 512 to ensure that arbitrarily sized
+ *     data transfer use the optimal (least) number of commands.
+ *
+ *     A driver may call this to override the default block size set by the
+ *     core. This can be used to set a block size greater than the maximum
+ *     that reported by the card; it is the driver's responsibility to ensure
+ *     it uses a value that the card supports.
+ *
+ *     Returns 0 on success, -EINVAL if the host does not support the
+ *     requested block size, or -EIO (etc.) if one of the resultant FBR block
+ *     size register writes failed.
+ *
+ */
+int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
+{
+       int ret;
+
+       if (blksz > func->card->host->max_blk_size)
+               return -EINVAL;
+
+       if (blksz == 0) {
+               blksz = min(min(
+                       func->max_blksize,
+                       func->card->host->max_blk_size),
+                       512u);
+       }
+
+       ret = mmc_io_rw_direct(func->card, 1, 0,
+               SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
+               blksz & 0xff, NULL);
+       if (ret)
+               return ret;
+       ret = mmc_io_rw_direct(func->card, 1, 0,
+               SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
+               (blksz >> 8) & 0xff, NULL);
+       if (ret)
+               return ret;
+       func->cur_blksize = blksz;
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(sdio_set_block_size);
+
+/**
  *     sdio_readb - read a single byte from a SDIO function
  *     @func: SDIO function to access
  *     @addr: address to read
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index af813ff..f057579 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -43,7 +43,8 @@ struct sdio_func {
        unsigned short          vendor;         /* vendor id */
        unsigned short          device;         /* device id */
 
-       unsigned short          blksize;        /* maximum block size */
+       unsigned                max_blksize;    /* maximum block size */
+       unsigned                cur_blksize;    /* current block size */
 
        unsigned int            state;          /* function state */
 #define SDIO_STATE_PRESENT     (1<<0)          /* present in sysfs */
@@ -111,6 +112,8 @@ extern void sdio_release_host(struct sdio_func *func);
 extern int sdio_enable_func(struct sdio_func *func);
 extern int sdio_disable_func(struct sdio_func *func);
 
+extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz);
+
 extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler);
 extern int sdio_release_irq(struct sdio_func *func);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to