All of lore.kernel.org
 help / color / mirror / Atom feed
* MMC performance
@ 2004-10-11 11:05 Pierre Ossman
  2004-10-11 12:19 ` Russell King
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Ossman @ 2004-10-11 11:05 UTC (permalink / raw)
  To: LKML, Russell King

I've added SGIO support to my driver now hoping that it would resolve 
the piss-poor performance I've been getting. Didn't do much difference 
though.

Read operations are fairly fast. It queues 8kB at a time. A bit small 
perhaps, but still decent.

Writing, however, only sends a single sector at a time. The queue 
process eats up half of the CPU time on my machine during a write. And 
since MMC cards have to clear a whole bunch of sectors before a write 
shouldn't you send as many sectors as possible to them?

Since I don't have another controller to compare with I don't really 
know if the problem is in my code, the MMC layer, the block layer or the 
filesystem.

I'm going to dig around a bit more but some pointers are welcome. At 
least which layer I should be looking at.

Rgds
Pierre

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 11:05 MMC performance Pierre Ossman
@ 2004-10-11 12:19 ` Russell King
  2004-10-11 13:18   ` Alan Cox
  2004-10-11 13:49   ` Pierre Ossman
  0 siblings, 2 replies; 7+ messages in thread
From: Russell King @ 2004-10-11 12:19 UTC (permalink / raw)
  To: Pierre Ossman; +Cc: LKML

On Mon, Oct 11, 2004 at 01:05:09PM +0200, Pierre Ossman wrote:
> Writing, however, only sends a single sector at a time. The queue 
> process eats up half of the CPU time on my machine during a write. And 
> since MMC cards have to clear a whole bunch of sectors before a write 
> shouldn't you send as many sectors as possible to them?

Only if you can reliably know how many bytes you've tranferred when
an error occurs.  Without that, the only safe way to do a write is
sector by sector.

And there are MMC controllers which just don't give you that
information, namely those found in Intel chips...

Since I'm having to be compatible with existing drivers, we need to
do this for the time being.  It's a shame we can't tell the BIO layer
about this type of quirk though.  Not that BIO itself understands
"sector by sector" IO at the moment.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 PCMCIA      - http://pcmcia.arm.linux.org.uk/
                 2.6 Serial core

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 12:19 ` Russell King
@ 2004-10-11 13:18   ` Alan Cox
  2004-10-11 15:27     ` Pierre Ossman
  2004-10-11 13:49   ` Pierre Ossman
  1 sibling, 1 reply; 7+ messages in thread
From: Alan Cox @ 2004-10-11 13:18 UTC (permalink / raw)
  To: Russell King; +Cc: Pierre Ossman, LKML

On Llu, 2004-10-11 at 13:19, Russell King wrote:
> Only if you can reliably know how many bytes you've tranferred when
> an error occurs.  Without that, the only safe way to do a write is
> sector by sector.

Only on retries. You can try and blast the lot out the first time then
on retries you write sector by sector.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 12:19 ` Russell King
  2004-10-11 13:18   ` Alan Cox
@ 2004-10-11 13:49   ` Pierre Ossman
  1 sibling, 0 replies; 7+ messages in thread
From: Pierre Ossman @ 2004-10-11 13:49 UTC (permalink / raw)
  To: Russell King; +Cc: LKML

Russell King wrote:

>Only if you can reliably know how many bytes you've tranferred when
>an error occurs.  Without that, the only safe way to do a write is
>sector by sector.
>
>  
>
What would happen if we failed the entire request? Rewriting a few 
sectors is harmless. Or will it break in more exotic ways?

Rgds
Pierre


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 13:18   ` Alan Cox
@ 2004-10-11 15:27     ` Pierre Ossman
  2004-10-11 18:01       ` Pierre Ossman
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Ossman @ 2004-10-11 15:27 UTC (permalink / raw)
  To: Alan Cox; +Cc: Russell King, LKML

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

Alan Cox wrote:

>Only on retries. You can try and blast the lot out the first time then
>on retries you write sector by sector.
>
>  
>
Something like this? Gives more than double throughput here.


[-- Attachment #2: mmc-bulk.patch --]
[-- Type: text/x-patch, Size: 2761 bytes --]

Index: linux-wbsd/drivers/mmc/mmc_block.c
===================================================================
--- linux-wbsd/drivers/mmc/mmc_block.c	(revision 71)
+++ linux-wbsd/drivers/mmc/mmc_block.c	(working copy)
@@ -166,9 +166,20 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	int ret;
+	int failsafe;
 
 	if (mmc_card_claim_host(card))
 		goto cmd_err;
+	
+	/*
+	 * We first try transfering multiple blocks. If this fails
+	 * we fall back to single block transfers.
+	 *
+	 * This gives us good performance when all is well and the
+	 * possibility to determine which sector fails when all
+	 * is not well.
+	 */
+	failsafe = 0;
 
 	do {
 		struct mmc_blk_request brq;
@@ -188,15 +199,24 @@
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B;
+		
+		/*
+		 * A multi-block transfer failed. Falling back to single
+		 * blocks.
+		 */
+		if (failsafe)
+			brq.data.blocks = 1;
+		
+		ret = 1;
 
 		if (rq_data_dir(req) == READ) {
 			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
 			brq.data.flags |= MMC_DATA_READ;
 		} else {
-			brq.cmd.opcode = MMC_WRITE_BLOCK;
+			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_WRITE_MULTIPLE_BLOCK :
+				MMC_WRITE_BLOCK;
 			brq.cmd.flags = MMC_RSP_R1B;
 			brq.data.flags |= MMC_DATA_WRITE;
-			brq.data.blocks = 1;
 		}
 		brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
 
@@ -204,19 +224,34 @@
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
 			       req->rq_disk->disk_name, brq.cmd.error);
-			goto cmd_err;
+			if (failsafe)
+				goto cmd_err;
+			else {
+				failsafe = 1;
+				continue;
+			}
 		}
 
 		if (brq.data.error) {
 			printk(KERN_ERR "%s: error %d transferring data\n",
 			       req->rq_disk->disk_name, brq.data.error);
-			goto cmd_err;
+			if (failsafe)
+				goto cmd_err;
+			else {
+				failsafe = 1;
+				continue;
+			}
 		}
 
 		if (brq.stop.error) {
 			printk(KERN_ERR "%s: error %d sending stop command\n",
 			       req->rq_disk->disk_name, brq.stop.error);
-			goto cmd_err;
+			if (failsafe)
+				goto cmd_err;
+			else {
+				failsafe = 1;
+				continue;
+			}
 		}
 
 		do {
@@ -229,7 +264,12 @@
 			if (err) {
 				printk(KERN_ERR "%s: error %d requesting status\n",
 				       req->rq_disk->disk_name, err);
-				goto cmd_err;
+				if (failsafe)
+					goto cmd_err;
+				else {
+					failsafe = 1;
+					continue;
+				}
 			}
 		} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
 
@@ -255,6 +295,11 @@
 			end_that_request_last(req);
 		}
 		spin_unlock_irq(&md->lock);
+		
+		/*
+		 * Go back to bulk mode if in failsafe mode.
+		 */
+		failsafe = 0;
 	} while (ret);
 
 	mmc_card_release_host(card);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 15:27     ` Pierre Ossman
@ 2004-10-11 18:01       ` Pierre Ossman
  2004-10-18 19:26         ` Pierre Ossman
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Ossman @ 2004-10-11 18:01 UTC (permalink / raw)
  Cc: Alan Cox, Russell King, LKML

Pierre Ossman wrote:
> Alan Cox wrote:
> 
>> Only on retries. You can try and blast the lot out the first time then
>> on retries you write sector by sector.
>>
>>  
>>
> Something like this? Gives more than double throughput here.
> 
> 

*sigh*

I'm starting to think there is a special place in hell reserved for the 
folks at SimpleTech. This card has been giving me all kinds of trouble 
and this patch adds another one. It seems the card completely screws up 
multiple block writes. As little as two blocks at a time causes corrupt 
data on the card.

I've been digging through the specs I have to find some way of detecting 
cards like these but I haven't had any success. Hopefully there aren't 
too many of these out there. If the choice comes down to high speed or 
supporting non-compliant cards, then my vote is for speed.

--
Pierre

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: MMC performance
  2004-10-11 18:01       ` Pierre Ossman
@ 2004-10-18 19:26         ` Pierre Ossman
  0 siblings, 0 replies; 7+ messages in thread
From: Pierre Ossman @ 2004-10-18 19:26 UTC (permalink / raw)
  To: LKML; +Cc: Russell King

I've solved (sort of) the problem with corrupt data when doing multiple 
block writes. It seems the spec I have for the host controller isn't 
quite correct when it comes to clock frequencies.
Copying the value that Windows uses (it doesn't adapt to the card) got 
the card working perfectly. This value is (according to my spec) invalid 
though. I need to hook up an oscilloscope to the device to figure this 
one out.

Russell, the users of my driver have tested the write multiple block 
patch and haven't run into any problems. If you haven't found any issues 
I suggest making it standard.

Rgds
Pierre


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-10-18 19:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-11 11:05 MMC performance Pierre Ossman
2004-10-11 12:19 ` Russell King
2004-10-11 13:18   ` Alan Cox
2004-10-11 15:27     ` Pierre Ossman
2004-10-11 18:01       ` Pierre Ossman
2004-10-18 19:26         ` Pierre Ossman
2004-10-11 13:49   ` Pierre Ossman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.