Messages in this thread Patch in this message | | | From | David Vrabel <> | Subject | sdio: set the functions' block size | Date | Tue, 31 Jul 2007 16:36:32 +0100 |
| |
Prior to calling the driver's probe(), set the functions' block size to the largest that's supported by both the card and the driver.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
--- commit 6d367fd822cbb2b8089ab7ef83f706f1984ab25b tree 8c9cc84b4c8c1c8f959abe540aa02f14aa95c51d parent 51755c3d59be1ba778bef45888f9f5e341dc4af4 author David Vrabel <david.vrabel@csr.com> Mon, 30 Jul 2007 19:58:54 +0100 committer David Vrabel <dvrabel@cantab.net> Mon, 30 Jul 2007 19:58:54 +0100
drivers/mmc/core/sdio_bus.c | 13 +++++++++++++ drivers/mmc/core/sdio_cis.c | 8 ++++---- drivers/mmc/core/sdio_io.c | 23 +++++++++++++++++++++++ include/linux/mmc/sdio_func.h | 7 +++++++ 4 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index a3ac1aa..f4d40c1 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -127,11 +127,24 @@ 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; + unsigned short block_size; + int ret; id = sdio_match_device(func, drv); if (!id) return -ENODEV; + /* + * Set the function's block size to the largest supported by + * both the function and the driver. + */ + block_size = min(drv->max_block_size, func->max_block_size); + sdio_claim_host(func); + ret = sdio_set_block_size(func, block_size); + 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 8aa4666..c16c536 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -93,9 +93,9 @@ static int cistpl_funce(struct sdio_func *func, unsigned fn, if (size < 0x04 || buf[0] != 0) goto bad; /* TPLFE_FN0_BLK_SIZE */ - val = buf[1] | (buf[2] << 8); + func->max_block_size = buf[1] | (buf[2] << 8); printk(KERN_DEBUG "%s: TPLFE_FN0_BLK_SIZE = %u\n", - sdio_func_id(func), val); + sdio_func_id(func), func->max_block_size); /* TPLFE_MAX_TRAN_SPEED */ val = speed_val[(buf[3] >> 3) & 15] * speed_unit[buf[3] & 7]; printk(KERN_DEBUG "%s: max speed = %u kbps\n", @@ -126,9 +126,9 @@ static int cistpl_funce(struct sdio_func *func, unsigned fn, printk(KERN_DEBUG "%s: TPLFE_CSA_PROPERTY = 0x%02x\n", sdio_func_id(func), val); /* TPLFE_MAX_BLK_SIZE */ - val = buf[12] | (buf[13] << 8); + func->max_block_size = buf[12] | (buf[13] << 8); printk(KERN_DEBUG "%s: TPLFE_MAX_BLK_SIZE = %u\n", - sdio_func_id(func), val); + sdio_func_id(func), func->max_block_size); /* TPLFE_OCR */ val = buf[14] | (buf[15] << 8) | (buf[16] << 16) | (buf[17] << 24); printk(KERN_DEBUG "%s: TPLFE_OCR = 0x%08x\n", diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index cc62ff7..e74e605 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -148,6 +148,29 @@ 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 + */ +int sdio_set_block_size(struct sdio_func *func, unsigned short blksz) +{ + int ret; + + ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_FBR_BLKSIZE(func->num), + blksz & 0xff, NULL); + if (ret) + return ret; + ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_FBR_BLKSIZE(func->num) + 1, + (blksz >> 8) & 0xff, NULL); + if (ret) + return ret; + func->block_size = 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 e34bc96..bfb0432 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -43,6 +43,9 @@ struct sdio_func { unsigned short vendor; /* vendor id */ unsigned short device; /* device id */ + unsigned short max_block_size; /* max block size supported */ + unsigned short block_size; /* current block size */ + unsigned int state; /* function state */ #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ @@ -68,6 +71,8 @@ struct sdio_driver { int (*probe)(struct sdio_func *, const struct sdio_device_id *); void (*remove)(struct sdio_func *); + unsigned short max_block_size; /* max block size supported by driver */ + struct device_driver drv; }; @@ -107,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 short 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 linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |