⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 patch_doc.txt

📁 The sd/mmc driver of linux 2.4.20 , it is much better than the one form samsung (good performance)
💻 TXT
字号:
Date: Thu, 09 Jun 2005 10:52:08 +0300 
From: Jukka Santala <donwulff_at_nic.fi> 
To: kernel-discuss_at_handhelds.org 
Subject: [Kernel-discuss] mmc_samsung.c fixes to MMC hangs/performance 


I have written a couple of fixes for the s3c2410 MMC drivers. I only 
have access to iPAQ h5550 and Transcend 45x 256MB SD card, however, so I 
cannot test whether the fixes work with all combinations. If people with 
different configurations could give it a spin hopefully we can get this 
into the Handhelds kernel soon. It's written against 
handhelds-pxa-2.4.19-rmk6-pxa1-hh37.6-r0 (Familiar 8.2) but should apply 
against any reasonably recent Handhelds kernel. 


There are three fixes in the patch: 
1) On ARM architechture, pending IRQ flags must always be reset, or they 
will keep being sent back for processing. The current driver doesn't 
reset the pending IRQ when getting "ignoring mmc irq with null request" 
error. This causes the device to frequently go into near endless loop 
processing the same empty IRQ. Since interrupts are disabled during the 
interrupt service routine, we can reset the interrupt flags at the 
beginning. 
2) Transcend 45x 256MB SD card specifies TAAC 0x8f, that translates to 
80ms. The Samsung datasheets state "SDI data/busy timer register has 
16-bit counter. In caise of 25MHz operation, the countable maximum is 
2.6ms (40ns * 0x10000). But, some cards have very long access time 
(TAAC), their TAAC are up to 100ms. In this case the SDI generates data 
timeout error state." The timeout error is not currently handled, 
causing the IO operation to hang. Unfortunately the chart provided in 
the datasheet doesn't make much sense, but the concept is simple: If the 
read access times out, temporarily reduce clock to 600kHz and try again. 
This patch does just that, no matter how ugly it is. 
3) Since the two fixes remove the two hangs I've had with the driver, 
I've changed it to use the clock-speed specified by the card directly. 
This works fine for me, but is the main thing that needs testing. If you 
have problems with the patch, check out what /proc/bus/mmc/device says. 
If it works, it should lead to small performance improvements even for 
people who haven't experienced hangs before. Bit suspicious about why 
the clock-speed is hardcoded, currently in two places, though. 


There's still plenty of errors and warnings coming out of the MMC 
driver, but at least with the above changes it works (for me) with good 
performance and stability. 


Patch attached, unless attachments are disabled. 


 -Donwulff 


diff -r -u kernel.org/drivers/mmc/mmc_protocol.c kernel/drivers/mmc/mmc_protocol.c 
--- kernel.org/drivers/mmc/mmc_protocol.c 2004-08-21 21:14:24.000000000 +0300 
+++ kernel/drivers/mmc/mmc_protocol.c 2005-06-09 09:51:01.000000000 +0300 
@@ -65,10 +65,12 @@ 
         /* Fix the clock rate */ 
         rate = mmc_tran_speed(dev->slot[slot].csd.tran_speed); 
         MMC_DEBUG(2,"==> mmc_configure_card (rate= %d) ",rate); 
+ /* Trust the value reported by card 
         if ( rate < MMC_CLOCK_SLOW ) 
                 rate = MMC_CLOCK_SLOW; 
         if ( rate > MMC_CLOCK_FAST ) 
                 rate = MMC_CLOCK_FAST; 
+ */ 
  
         dev->sdrive->set_clock(rate); 
          
diff -r -u kernel.org/drivers/mmc/mmc_samsung.c kernel/drivers/mmc/mmc_samsung.c 
--- kernel.org/drivers/mmc/mmc_samsung.c 2004-06-23 02:12:06.000000000 +0300 
+++ kernel/drivers/mmc/mmc_samsung.c 2005-06-09 10:26:11.000000000 +0300 
@@ -317,10 +317,12 @@ 
         int prescaler = 0; 
  
         /* Does not seem to work consistently if clock rate is above 10000000 */ 
+ /* Experimental - trust the value reported by card itself 
         if ( 10000000 < rate ) 
         { 
                 rate = 10000000; 
         } 
+ */ 
         prescaler = (2*PCLK)/(rate) - 1; 
         retval = mmc_s3c_stop_clock(); 
         if ( retval ) return retval; 
@@ -689,6 +691,7 @@ 
 static void mmc_s3c_send_command (struct mmc_request * request) 
 { 
         int retval; 
+ int clock; 
 /* 
         MMC_DEBUG(2," rINTMSK 0x%08X 
                   rINTMOD 0x%08X 
@@ -718,7 +721,16 @@ 
         else { 
                 retval = mmc_s3c_exec_command(request); 
                 MMC_DEBUG(2," retval 0x%08X ",retval); 
- 
+ if(retval == MMC_ERROR_TIMEOUT) { 
+ MMC_DEBUG(2," timed out, trying again at 600kHz"); 
+ request->result = MMC_NO_RESPONSE; 
+ clock = g_s3c_mmc_data.clock; /* Save value */ 
+ mmc_s3c_adjust_clock(600000); 
+ retval = mmc_s3c_exec_command(request); 
+ MMC_DEBUG(2," retval 0x%08X ",retval); 
+ mmc_s3c_adjust_clock(clock); 
+ } 
+ 
 #if 0 
                 if ( retval) { 
           // g_s3c_statistics.mmc_error++; 
@@ -1165,7 +1177,9 @@ 
                 } 
                 /* It is impossible to get both response and data */ 
                 if ( sd->request->nob ) { 
- msk_reg = S3C_RX_FIFO_LAST_DATA_INT_ON | S3C_RX_FIFO_FULL_INT_ON; 
+ msk_reg = S3C_RX_FIFO_LAST_DATA_INT_ON | S3C_RX_FIFO_FULL_INT_ON 
+ |S3C_DATA_TIMEOUT_INT_ON; 
+ 
                         MMC_DEBUG(2,": read SDIIMSK mask=0x%08x",rSDIIMSK); 
                         // mod_timer( &sd->irq_timer, jiffies + MMC_IRQ_TIMEOUT); 
                 // mmc_s3c_start_clock(); /* redundancy ? */ 
@@ -1253,6 +1267,11 @@ 
         MMC_DEBUG(2, " rSDIIMSK 0x%08X cmd 0x%08X data 0x%08X fifo 0x%08X",rSDIIMSK,status[0],status[1],status[2]); 
         MMC_DEBUG(2, " rSDICON 0x%08X CCON 0x%08X DCONdata 0x%08X ",rSDICON,rSDICCON,rSDIDCON); 
  
+ /* Clear the interrupt. Must write a one to the src pending register 
+ then the interrupt pending register. */ 
+ h5400_asic_write_register (H5400_ASIC_IC_SRCPND, _H5400_ASIC_IC_INT_SD); 
+ h5400_asic_write_register (H5400_ASIC_IC_INTPND, _H5400_ASIC_IC_INT_SD); 
+ 
         /* this can happen if there is an old interrupt hanging around when the irq is registered */ 
         if (sd->request == NULL) { 
                 printk ("ignoring mmc irq with null request\n"); 
@@ -1272,11 +1291,6 @@ 
  
         mmc_s3c_split_status( sd, status, 0 ); 
  
- /* Clear the interrupt. Must write a one to the src pending register 
- then the interrupt pending register. */ 
- h5400_asic_write_register (H5400_ASIC_IC_SRCPND, _H5400_ASIC_IC_INT_SD); 
- h5400_asic_write_register (H5400_ASIC_IC_INTPND, _H5400_ASIC_IC_INT_SD); 
- 
         /* Enable the irq */ 
         enable_irq( irq ); 
 } 


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -