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

sdio: extend sdio_readsb() and friends to handle any length of buffer

Extend sdio_readsb(), sdio_writesb(), sdio_memcpy_fromio(), and
sdio_memcpy_toio() to handle any length of buffer by splitting the transfer
into several IO_RW_EXTENDED commands. Typically, a transfer would be split
into a single block mode transfer followed by a byte mode transfer for the
remainder but we also handle lack of block mode support and the block size
being greater than 512 (the maximum byte mode transfer size).

host->max_seg_size <= host->max_req_size so there's no need to check both
when determining the maximum data size for a single command.

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
eb659468 9a08f82b

+86 -28
+73 -20
drivers/mmc/core/sdio_io.c
··· 189 189 190 190 EXPORT_SYMBOL_GPL(sdio_set_block_size); 191 191 192 + /* Split an arbitrarily sized data transfer into several 193 + * IO_RW_EXTENDED commands. */ 194 + static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, 195 + unsigned addr, int incr_addr, u8 *buf, unsigned size) 196 + { 197 + unsigned remainder = size; 198 + unsigned max_blocks; 199 + int ret; 200 + 201 + /* Do the bulk of the transfer using block mode (if supported). */ 202 + if (func->card->cccr.multi_block) { 203 + /* Blocks per command is limited by host count, host transfer 204 + * size (we only use a single sg entry) and the maximum for 205 + * IO_RW_EXTENDED of 511 blocks. */ 206 + max_blocks = min(min( 207 + func->card->host->max_blk_count, 208 + func->card->host->max_seg_size / func->cur_blksize), 209 + 511u); 210 + 211 + while (remainder > func->cur_blksize) { 212 + unsigned blocks; 213 + 214 + blocks = remainder / func->cur_blksize; 215 + if (blocks > max_blocks) 216 + blocks = max_blocks; 217 + size = blocks * func->cur_blksize; 218 + 219 + ret = mmc_io_rw_extended(func->card, write, 220 + func->num, addr, incr_addr, buf, 221 + blocks, func->cur_blksize); 222 + if (ret) 223 + return ret; 224 + 225 + remainder -= size; 226 + buf += size; 227 + if (incr_addr) 228 + addr += size; 229 + } 230 + } 231 + 232 + /* Write the remainder using byte mode. */ 233 + while (remainder > 0) { 234 + size = remainder; 235 + if (size > func->cur_blksize) 236 + size = func->cur_blksize; 237 + if (size > 512) 238 + size = 512; /* maximum size for byte mode */ 239 + 240 + ret = mmc_io_rw_extended(func->card, write, func->num, addr, 241 + incr_addr, buf, 1, size); 242 + if (ret) 243 + return ret; 244 + 245 + remainder -= size; 246 + buf += size; 247 + if (incr_addr) 248 + addr += size; 249 + } 250 + return 0; 251 + } 252 + 192 253 /** 193 254 * sdio_readb - read a single byte from a SDIO function 194 255 * @func: SDIO function to access ··· 313 252 * @addr: address to begin reading from 314 253 * @count: number of bytes to read 315 254 * 316 - * Reads up to 512 bytes from the address space of a given SDIO 317 - * function. Return value indicates if the transfer succeeded or 318 - * not. 255 + * Reads from the address space of a given SDIO function. Return 256 + * value indicates if the transfer succeeded or not. 319 257 */ 320 258 int sdio_memcpy_fromio(struct sdio_func *func, void *dst, 321 259 unsigned int addr, int count) 322 260 { 323 - return mmc_io_rw_extended(func->card, 0, func->num, addr, 0, dst, 324 - count); 261 + return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count); 325 262 } 326 263 EXPORT_SYMBOL_GPL(sdio_memcpy_fromio); 327 264 ··· 330 271 * @src: buffer that contains the data to write 331 272 * @count: number of bytes to write 332 273 * 333 - * Writes up to 512 bytes to the address space of a given SDIO 334 - * function. Return value indicates if the transfer succeeded or 335 - * not. 274 + * Writes to the address space of a given SDIO function. Return 275 + * value indicates if the transfer succeeded or not. 336 276 */ 337 277 int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr, 338 278 void *src, int count) 339 279 { 340 - return mmc_io_rw_extended(func->card, 1, func->num, addr, 0, src, 341 - count); 280 + return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count); 342 281 } 343 282 EXPORT_SYMBOL_GPL(sdio_memcpy_toio); 344 283 ··· 347 290 * @addr: address of (single byte) FIFO 348 291 * @count: number of bytes to read 349 292 * 350 - * Reads up to 512 bytes from the specified FIFO of a given SDIO 351 - * function. Return value indicates if the transfer succeeded or 352 - * not. 293 + * Reads from the specified FIFO of a given SDIO function. Return 294 + * value indicates if the transfer succeeded or not. 353 295 */ 354 296 int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr, 355 297 int count) 356 298 { 357 - return mmc_io_rw_extended(func->card, 0, func->num, addr, 1, dst, 358 - count); 299 + return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count); 359 300 } 360 301 361 302 EXPORT_SYMBOL_GPL(sdio_readsb); ··· 365 310 * @src: buffer that contains the data to write 366 311 * @count: number of bytes to write 367 312 * 368 - * Writes up to 512 bytes to the specified FIFO of a given SDIO 369 - * function. Return value indicates if the transfer succeeded or 370 - * not. 313 + * Writes to the specified FIFO of a given SDIO function. Return 314 + * value indicates if the transfer succeeded or not. 371 315 */ 372 316 int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src, 373 317 int count) 374 318 { 375 - return mmc_io_rw_extended(func->card, 1, func->num, addr, 1, src, 376 - count); 319 + return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count); 377 320 } 378 321 EXPORT_SYMBOL_GPL(sdio_writesb); 379 322
+12 -7
drivers/mmc/core/sdio_ops.c
··· 88 88 } 89 89 90 90 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, 91 - unsigned addr, int bang, u8 *buf, unsigned size) 91 + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) 92 92 { 93 93 struct mmc_request mrq; 94 94 struct mmc_command cmd; ··· 97 97 98 98 BUG_ON(!card); 99 99 BUG_ON(fn > 7); 100 - BUG_ON(size > 512); 100 + BUG_ON(blocks == 1 && blksz > 512); 101 + WARN_ON(blocks == 0); 102 + WARN_ON(blksz == 0); 101 103 102 104 memset(&mrq, 0, sizeof(struct mmc_request)); 103 105 memset(&cmd, 0, sizeof(struct mmc_command)); ··· 111 109 cmd.opcode = SD_IO_RW_EXTENDED; 112 110 cmd.arg = write ? 0x80000000 : 0x00000000; 113 111 cmd.arg |= fn << 28; 114 - cmd.arg |= bang ? 0x00000000 : 0x04000000; 112 + cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; 115 113 cmd.arg |= addr << 9; 116 - cmd.arg |= (size == 512) ? 0 : size; 114 + if (blocks == 1 && blksz <= 512) 115 + cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ 116 + else 117 + cmd.arg |= 0x08000000 | blocks; /* block mode */ 117 118 cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC; 118 119 119 - data.blksz = size; 120 - data.blocks = 1; 120 + data.blksz = blksz; 121 + data.blocks = blocks; 121 122 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; 122 123 data.sg = &sg; 123 124 data.sg_len = 1; 124 125 125 - sg_init_one(&sg, buf, size); 126 + sg_init_one(&sg, buf, blksz * blocks); 126 127 127 128 mmc_set_data_timeout(&data, card); 128 129
+1 -1
drivers/mmc/core/sdio_ops.h
··· 16 16 int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, 17 17 unsigned addr, u8 in, u8* out); 18 18 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, 19 - unsigned addr, int bang, u8 *data, unsigned size); 19 + unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); 20 20 21 21 #endif 22 22