Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] Re: Busy waiting in i2c_busy_rise_and_fall (was: Re: Re: full featured card without signal and required video memory investigation)



On Sunday 13 July 2003 08:53, Robert Schlabbach wrote:
> From: "Oliver Endriss" <o.endriss@gmx.de>
>
> > Well, I found the reason for the high cpu load:
> > i2c_busy_rise_and_fall (saa7146.c) uses mdelay calls, i.e.
> > busy-waiting. Normally this is no problem, but it consumes 30% of
> > the cpu power when the frontend thread is unable to tune...
>
> Hmm, I had mentioned this before. Try replacing the wait for the rise
> with an empty read of IICSTA. In my experience, only the first read
> of IICSTA will sometimes not indicate the correct busy states, but
> the second one is always correct.
>
> As to waiting for the transfer to complete, try increasing the I2C
> bus clock rate, 275kHz should work for all components and decrease
> the wait significantly. Then try if you can do entirely _without_ any
> delay or scheduler calls, i.e. a fully busy loop. This is preferrable
> for cases in which greater amounts of data need to be transferred.
> Such a case is e.g. the TDA10045H DSP firmware code upload, which
> takes only about 1 second when fully exploiting the 275kHz clock, but
> can take over a minute when scheduler calls are inserted...
>
> Aside from that, with a 275kHz clock a transfer finishes so fast that
> the overhead from rescheduling to other tasks might exceed the CPU
> load from the busy wait loop...

Thanks for your explanations. I modified the source code accordingly:

--- saa7146.c.org	Mon Nov 18 22:18:46 2002
+++ saa7146.c	Sun Jul 13 17:56:24 2003
@@ -1271,6 +1271,7 @@ int i2c_busy_rise_and_fall(struct saa714
 {
 	int i = 0;
 	u32 status = 0;
+	u32 endjiff;
 		
 	hprintk("saa7146: ==> i2c_busy_rise_and_fall\n");
 
@@ -1284,11 +1285,9 @@ int i2c_busy_rise_and_fall(struct saa714
 		/* check busy flag */
 		if ( 0 != (status & SAA7146_I2C_BUSY))
 			break;
-
-		/* see if anything can be done while we're waiting */
-		cond_resched ();
-		mdelay(1);
 	}
+	if (i == 0)
+		printk ("saa7146: i2c_busy_rise_and_fall: no busy flag!\n");
 
 	/* we don't check the i-value, since it does not matter
 	   if we missed the rise of the busy flag or the fall or
@@ -1296,9 +1295,9 @@ int i2c_busy_rise_and_fall(struct saa714
 	   after an i2c-command has been written out */	
 	
 	/* wait until busy-flag is inactive or error is reported */
-	for (i = timeout; i > 0; i--) {
+	for (endjiff = jiffies+timeout/10; jiffies <= endjiff; ) {
 	
-		hprintk("saa7146: i2c_busy_rise_and_fall; fall wait %d\n",i);
+		hprintk("saa7146: i2c_busy_rise_and_fall; fall wait\n");
 
 		status = i2c_status_check(saa);
 
@@ -1309,15 +1308,10 @@ int i2c_busy_rise_and_fall(struct saa714
 		/* check error flag */
 		if ( 0 != (status & SAA7146_I2C_ERR))
 			break;
-
-		/* see if anything can be done while we're waiting */
-		cond_resched ();
-
-		mdelay(1);
 	}
 	
 	/* did a timeout occur ? */
-	if ( 0 == i ) {
+	if (jiffies > endjiff) {
 		hprintk("saa7146: i2c_busy_rise_and_fall: timeout #2\n");
 		return -1;
 	}
--- saa7146_core.c.org	Sat Jun 28 01:42:53 2003
+++ saa7146_core.c	Sun Jul 13 17:54:36 2003
@@ -82,7 +82,7 @@ static struct saa7146_extension* saa7146
 #define SAA7146_I2C_TIMEOUT  100   /* in ms */
 #define SAA7146_I2C_RETRIES  6
 
-static u32 SAA7146_I2C_BBR = SAA7146_I2C_BUS_BIT_RATE_3200;
+static u32 SAA7146_I2C_BBR = SAA7146_I2C_BUS_BIT_RATE_120; /* 275 kHz */
 
 #define	__COMPILE_SAA7146_I2C__
 #define	__COMPILE_SAA7146_DEBI__


A quick test showed very nice results:
- cpu usage of the frontend process is almost zero if there is no signal.
- Tuning seems to be faster than before.

@all:
Please test and report if you encounter any problems with this patch.

Oliver



-- 
Info:
To unsubscribe send a mail to ecartis@linuxtv.org with "unsubscribe linux-dvb" as subject.



Home | Main Index | Thread Index