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

s3cmci: fix continual accesses to host->pio_ptr

The s3cmci driver uses the host->pio_ptr field to
point to the current position into the buffer for data
transfer. During the transfers it does the following:

while (fifo_words--)
*(host->pio_ptr++) = readl(from_ptr);

This is inefficent, as host->pio_ptr is not used in any
other part of the transfer but the compiler emits code
which does the following:

while (fifo_words--) {
u32 *ptr = host->pio_ptr;
*ptr = readl(from_ptr);
ptr++;
host->pio_ptr = ptr;
}

This is obviously a waste of a load and store each time
around the loop, which could be up to 16 times depending
on how much needs to be transfered.

Move the ptr accesses to outside the while loop so that
we do not end up reloading/re-writing the pointer.

Note, this seems to make the code 16 bytes larger.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>

authored by

ben@fluff.org.uk and committed by
Pierre Ossman
18280fff 088a78af

+8 -2
+8 -2
drivers/mmc/host/s3cmci.c
··· 238 238 { 239 239 int res; 240 240 u32 fifo; 241 + u32 *ptr; 241 242 u32 fifo_words; 242 243 void __iomem *from_ptr; 243 244 ··· 284 283 host->pio_count += fifo; 285 284 286 285 fifo_words = fifo >> 2; 286 + ptr = host->pio_ptr; 287 287 while (fifo_words--) 288 - *(host->pio_ptr++) = readl(from_ptr); 288 + *ptr++ = readl(from_ptr); 289 + host->pio_ptr = ptr; 289 290 290 291 if (fifo & 3) { 291 292 u32 n = fifo & 3; ··· 322 319 void __iomem *to_ptr; 323 320 int res; 324 321 u32 fifo; 322 + u32 *ptr; 325 323 326 324 to_ptr = host->base + host->sdidata; 327 325 ··· 357 353 host->pio_count += fifo; 358 354 359 355 fifo = (fifo + 3) >> 2; 356 + ptr = host->pio_ptr; 360 357 while (fifo--) 361 - writel(*(host->pio_ptr++), to_ptr); 358 + writel(*ptr++, to_ptr); 359 + host->pio_ptr = ptr; 362 360 } 363 361 364 362 enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);