Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <david.vrabel@csr.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>

authored by

David Vrabel and committed by
Pierre Ossman
9a08f82b 7616ee95

+63 -2
+9
drivers/mmc/core/sdio_bus.c
··· 128 128 struct sdio_driver *drv = to_sdio_driver(dev->driver); 129 129 struct sdio_func *func = dev_to_sdio_func(dev); 130 130 const struct sdio_device_id *id; 131 + int ret; 131 132 132 133 id = sdio_match_device(func, drv); 133 134 if (!id) 134 135 return -ENODEV; 136 + 137 + /* Set the default block size so the driver is sure it's something 138 + * sensible. */ 139 + sdio_claim_host(func); 140 + ret = sdio_set_block_size(func, 0); 141 + sdio_release_host(func); 142 + if (ret) 143 + return ret; 135 144 136 145 return drv->probe(func, id); 137 146 }
+1 -1
drivers/mmc/core/sdio_cis.c
··· 79 79 return -EINVAL; 80 80 81 81 /* TPLFE_MAX_BLK_SIZE */ 82 - func->blksize = buf[12] | (buf[13] << 8); 82 + func->max_blksize = buf[12] | (buf[13] << 8); 83 83 84 84 return 0; 85 85 }
+49
drivers/mmc/core/sdio_io.c
··· 141 141 EXPORT_SYMBOL_GPL(sdio_disable_func); 142 142 143 143 /** 144 + * sdio_set_block_size - set the block size of an SDIO function 145 + * @func: SDIO function to change 146 + * @blksz: new block size or 0 to use the default. 147 + * 148 + * The default block size is the largest supported by both the function 149 + * and the host, with a maximum of 512 to ensure that arbitrarily sized 150 + * data transfer use the optimal (least) number of commands. 151 + * 152 + * A driver may call this to override the default block size set by the 153 + * core. This can be used to set a block size greater than the maximum 154 + * that reported by the card; it is the driver's responsibility to ensure 155 + * it uses a value that the card supports. 156 + * 157 + * Returns 0 on success, -EINVAL if the host does not support the 158 + * requested block size, or -EIO (etc.) if one of the resultant FBR block 159 + * size register writes failed. 160 + * 161 + */ 162 + int sdio_set_block_size(struct sdio_func *func, unsigned blksz) 163 + { 164 + int ret; 165 + 166 + if (blksz > func->card->host->max_blk_size) 167 + return -EINVAL; 168 + 169 + if (blksz == 0) { 170 + blksz = min(min( 171 + func->max_blksize, 172 + func->card->host->max_blk_size), 173 + 512u); 174 + } 175 + 176 + ret = mmc_io_rw_direct(func->card, 1, 0, 177 + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE, 178 + blksz & 0xff, NULL); 179 + if (ret) 180 + return ret; 181 + ret = mmc_io_rw_direct(func->card, 1, 0, 182 + SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1, 183 + (blksz >> 8) & 0xff, NULL); 184 + if (ret) 185 + return ret; 186 + func->cur_blksize = blksz; 187 + return 0; 188 + } 189 + 190 + EXPORT_SYMBOL_GPL(sdio_set_block_size); 191 + 192 + /** 144 193 * sdio_readb - read a single byte from a SDIO function 145 194 * @func: SDIO function to access 146 195 * @addr: address to read
+4 -1
include/linux/mmc/sdio_func.h
··· 43 43 unsigned short vendor; /* vendor id */ 44 44 unsigned short device; /* device id */ 45 45 46 - unsigned short blksize; /* maximum block size */ 46 + unsigned max_blksize; /* maximum block size */ 47 + unsigned cur_blksize; /* current block size */ 47 48 48 49 unsigned int state; /* function state */ 49 50 #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ ··· 111 110 112 111 extern int sdio_enable_func(struct sdio_func *func); 113 112 extern int sdio_disable_func(struct sdio_func *func); 113 + 114 + extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz); 114 115 115 116 extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler); 116 117 extern int sdio_release_irq(struct sdio_func *func);