About omap2 mmc host close too long irq in irqaction.
Subsystems (2)
Hi all,
Now i worked on omp2 and met a probelm which someplace close_irq for 3.6second.
The kernel version is 2.6.37. I used trace to find in irq_action:omap_hsmmc_irq. This problem occured by removed the sdcard when there are io operations.
I found the read problem is in omap_hsmmc_reset_controller_fsm. In omap_hsmmc_reset_controller_fsm:
Quoted 18 lines
static inline void omap_hsmmc_reset_controller_fsm(struct
omap_hsmmc_host*host,
unsigned long bit){ unsigned long i = 0; unsigned long limit = (loops_per_jiffy * msecs_to_jiffies(MMC_TIMEOUT_MS)); OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | bit); /* * OMAP4 ES2 and greater has an updated reset logic. * Monitor a 0->1 transition first */ if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) && (i++ < limit)) cpu_relax();
} In func, it used loops_per_jiffy in order to avoid do many time exceed MMC_TIMEOUT_MS. In face oops_per_jiify is like: while(i++ < loops_per_jiffy) cpu_relax();
But actually, it used as follow:
Quoted 2 lines
while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
&& (i++ < limit))
it add some operations like: read regisger, &, &&. So the time may exceed MMC_TIMEOUT_MS.
I used those code to test and found it's ok:
for (i = 0 ; i < 10; i++){
if (!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
break;
j = limit/10;
while(j--)
cpu_relax();
}Using this the problom can't occur.
Am i missing something?
Thanks!
Jianpeng Ma
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 64 lines · majianpeng
Quoted 44 lines
Hi all,
Now i worked on omp2 and met a probelm which someplaceclose_irqfor 3.6second.
The kernel version is 2.6.37. I used trace to find in irq_action:omap_hsmmc_irq. This problem occured by removed the sdcard when there are io operations.I found the read problem is in
omap_hsmmc_reset_controller_fsm. Inomap_hsmmc_reset_controller_fsm:Quoted 18 lines
static inline void omap_hsmmc_reset_controller_fsm(struct
omap_hsmmc_host*host,
unsigned long bit){ unsigned long i = 0; unsigned long limit = (loops_per_jiffy * msecs_to_jiffies(MMC_TIMEOUT_MS)); OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | bit); /* * OMAP4 ES2 and greater has an updated reset logic. * Monitor a 0->1 transition first */ if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) && (i++ < limit)) cpu_relax();} In func, it used loops_per_jiffy in order to avoid do many time exceed MMC_TIMEOUT_MS. In face oops_per_jiify is like: while(i++ < loops_per_jiffy) cpu_relax();But actually, it used as follow:
Quoted 2 lines
while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
&& (i++ < limit))it add some operations like: read regisger, &, &&. So the time may exceed
MMC_TIMEOUT_MS.
I used those code to test and found it's ok:for (i = 0 ; i < 10; i++){ if (!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) break; j = limit/10; while(j--) cpu_relax(); }Quoted 5 lines
Using this the problom can't occur.
Am i missing something?Thanks!
Jianpeng MaI do more test and found more interesting things
static inline void omap_hsmmc_reset_controller_fsm(struct
omap_hsmmc_host*host,
unsigned long bit){ /* * OMAP4 ES2 and greater has an updated reset logic. * Monitor a 0->1 transition first */ if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {Quoted 3 lines
while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) && (i++ < limit)) cpu_relax();
Quoted 6 lines
I modify above code as: while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) { i++;cpu_relax(); }When the problem occur, it can't return from while.That's mean the transition was already oocured befroe while.
So it can't monitor a 0->1 transition.
Hi,
Which OMAP SoC are you testing on (OMAP4 ES2+ ? )
Can you try the below inlined patch
drivers/mmc/host/omap_hsmmc.c +6 -7
@@ -973,10 +973,9 @@ static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,static inline void omap_hsmmc_reset_controller_fsm (struct omap_hsmmc_host *host,unsigned long bit) { -unsigned long i =0 ; -unsigned long limit = (loops_per_jiffy * -msecs_to_jiffies (MMC_TIMEOUT_MS )); +unsigned long timeout; + timeout = jiffies +msecs_to_jiffies (MMC_TIMEOUT_MS );OMAP_HSMMC_WRITE (host->base,SYSCTL ,OMAP_HSMMC_READ (host->base,SYSCTL ) | bit);
@@ -985,14 +984,14 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,* Monitor a 0->1 transition first */ if (mmc_slot (host).features &HSMMC_HAS_UPDATED_RESET ) { -while ((!(OMAP_HSMMC_READ (host->base,SYSCTL ) & bit)) - && (i++ < limit)) +while ((!(OMAP_HSMMC_READ (host->base,SYSCTL ) & bit)) && +time_before (jiffies, timeout))cpu_relax (); } - i =0 ; + timeout = jiffies +msecs_to_jiffies (MMC_TIMEOUT_MS );while ((OMAP_HSMMC_READ (host->base,SYSCTL ) & bit) && - (i++ < limit)) +time_before (jiffies, timeout))cpu_relax ();if (OMAP_HSMMC_READ (host->base,SYSCTL ) & bit)
Quoted 4 lines
Thanks!
Jianpeng Ma