linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* TQM5200 problems (kernel 2.4)
@ 2007-07-04 14:51 Kimmo Surakka
  2007-07-05  6:54 ` Domen Puncer
  2007-07-05 22:13 ` Wolfgang Denk
  0 siblings, 2 replies; 6+ messages in thread
From: Kimmo Surakka @ 2007-07-04 14:51 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hello all,

I've been playing with a TQM5200 card and trying to make its I2C
communications even relatively reliable. To communicate with the card,
I use PPP over RS-232 (on port PSC0), baud rate 115200. All the files
are stored on the card's own 32 MB flash.

On my tests, I've met three problems: PPP connection unreliability,
I2C unreliability, and flash unreliability. I anybody has any ideas on
what could be causing these, I'd be happy to hear. Also, I've put
together two patches that help a bit, so if somebody else is
struggling with the same problems, feel free to test these patches.

Problem #1: PPP unreliability. If I just fetch the latest 2.4 kernel
from http://www.denx.de/cgi-bin/gitweb.cgi?p=linuxppc_2_4_devel.git;a=summary
and build it with a pretty minimal configuration file, PPP connection
is really unreliable. I've set the MTS to be 576 bytes, because on a
continuous transfer from TQM I get CRC error about once every ten
seconds. This triggers TCP CRC recalculation code from git commits
e3145f7943db03e3808e493555b28e7696e8f408
and 8bab0e983d5fc1ad53c34c0cc68a07d9339a7148. As a result, my dmesg
log gets filled with lines like:

tcp_recheck_csum: seq 0x1e9a515 retransmit, csum 0x4bb2 OK?
tcp_recheck_csum: seq 0x1e9ad75 retransmit, csum 0x32fe OK?
tcp_recheck_csum: seq 0x1e9ad75 retransmit, csum 0x32fe OK?
tcp_recheck_csum: seq 0x1e9ad75 retransmit, csum 0x32fe OK?
tcp_recheck_csum: seq 0x1e9af8d retransmit, csum 0xc296 OK?
tcp_recheck_csum: seq 0x1e9af8d retransmit, csum 0xc272 OK?

All PPP transmission also stalls. Data just won't arrive anymore.

I put together a patch that undoes the TCP/IP workaround patches. When
I apply the patch to the latest git commit, the errors seem to go
away. PPP connection now works even though there are the occational
CRC errors due to unreliable serial line. My conclusion:
the TCP/IP workaround is somehow broken. I'm not sure what bug it was
meant to work around, but while doing that it caused serious problems
with PPP communication.

Problem #2: I2C unreliability. My test setup has two slaves connected
on the TQM5200 I2C bus #1. On default setup this bus is disabled, so I
needed to edit file drivers/i2c/i2c-tqm5200.c and changethe value of
MPC5xxx_I2C1_ENABLE. After this change, the bus gets initialised.
However, it's not reliable. I send smbus_read_word and
smbus_write_word commands to the slaves every few milliseconds. Sooner
or later the bus gets stuck, apparently forever. I found an old I2c
patch for mpc5200 and modified it a bit. With the patch applied, the
kernel tries to detect bus lock-ups and reset the bus. This helps a
lot: now the lock-ups are only temporary. However, the dmesg log gets
polluted with lines like

Warning: kfree_skb on hard IRQ c008ecfc
Warning: kfree_skb on hard IRQ c008ecfc
Warning: kfree_skb on hard IRQ c008ecfc
Warning: kfree_skb on hard IRQ c008ecfc
Warning: kfree_skb on hard IRQ c008ecfc
Warning: kfree_skb on hard IRQ c008ecfc

(always the same IRQ). The seem to come from net/core/skbuff.c, and
caused by kfree_skb being called while in_irq().

Problem #3: flash unreliability. After some time (weeks or so) the
system's flash filesystem (JFFS2) starts to misbehave. On every boot I
see lines like

jffs2_scan_eraseblock(): Node at 0x000bce2c {0x1985, 0x0000,
0x00000000) has invalid CRC 0x6ca60000 (calculated 0xbe76ea63)
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce34:
0x6ca6 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce48:
0x0019 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce4c:
0x42c6 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce50:
0x42c6 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce54:
0x42c6 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce58:
0x0019 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x000bce64:
0x0600 instead

After a number of boots the system finally fails to boot at all. The
errors go away by erasing the flash and recreating the filesystem, but
the come back again at some point. Actually, I'm not sure if this
error still exists on the latest kernel sources. Before this, I've
been using the sources from snapshot
ftp://ftp.denx.de/pub/linux/linuxppc_2_4_devel-2005-10-25-1440.tar.bz2,
but since the code starts to be pretty old, I switched to using the
git repository. I'll continue tests with the latest code and see if
the problem still exists.



-- 
Kimmo Surakka <kusti@iki.fi>
http://www.iki.fi/kusti

[-- Attachment #2: undo-tcpip-workaround.patch --]
[-- Type: text/x-patch, Size: 8149 bytes --]

This patch undoes the git commits e3145f7943db03e3808e493555b28e7696e8f408
and 8bab0e983d5fc1ad53c34c0cc68a07d9339a7148,
"Work-around for TCP/IP errors"

diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index f198de4..4951e67 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -8,7 +8,7 @@ O_TARGET		:= lib.o
 
 export-objs		:= dec_and_lock.o
 
-obj-y			:= checksum.o string.o strcase.o dec_and_lock.o div64.o checksum_alt.o
+obj-y			:= checksum.o string.o strcase.o dec_and_lock.o div64.o
 
 obj-$(CONFIG_SMP)	+= locks.o
 
diff --git a/arch/ppc/lib/checksum_alt.c b/arch/ppc/lib/checksum_alt.c
deleted file mode 100644
index 820cb28..0000000
--- a/arch/ppc/lib/checksum_alt.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IP/TCP/UDP checksumming routines
- *
- * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
- *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		Tom May, <ftom@netcom.com>
- *		Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * 03/02/96	Jes Sorensen, Andreas Schwab, Roman Hodek:
- *		Fixed some nasty bugs, causing some horrible crashes.
- *		A: At some points, the sum (%0) was used as
- *		length-counter instead of the length counter
- *		(%1). Thanks to Roman Hodek for pointing this out.
- *		B: GCC seems to mess up if one uses too many
- *		data-registers to hold input values and one tries to
- *		specify d0 and d1 as scratch registers. Letting gcc choose these
- *      registers itself solves the problem.
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-  
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
-   of the assembly has to go. */
-
-static inline unsigned short from32to16(unsigned long x)
-{
-	/* add up 16-bit and 16-bit for 16+c bit */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static unsigned long do_csum(const unsigned char * buff, int len)
-{
-	int odd, count;
-	unsigned long result = 0;
-
-	if (len <= 0)
-		goto out;
-	odd = 1 & (unsigned long) buff;
-	if (odd) {
-		result = *buff;
-		len--;
-		buff++;
-	}
-	count = len >> 1;		/* nr of 16-bit words.. */
-	if (count) {
-		if (2 & (unsigned long) buff) {
-			result += *(unsigned short *) buff;
-			count--;
-			len -= 2;
-			buff += 2;
-		}
-		count >>= 1;		/* nr of 32-bit words.. */
-		if (count) {
-		        unsigned long carry = 0;
-			do {
-				unsigned long w = *(unsigned long *) buff;
-				count--;
-				buff += 4;
-				result += carry;
-				result += w;
-				carry = (w > result);
-			} while (count);
-			result += carry;
-			result = (result & 0xffff) + (result >> 16);
-		}
-		if (len & 2) {
-			result += *(unsigned short *) buff;
-			buff += 2;
-		}
-	}
-	if (len & 1)
-		result += (*buff << 8);
-	result = from32to16(result);
-	if (odd)
-		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-	return result;
-}
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-unsigned int csum_partial_alt(const unsigned char *buff, int len, unsigned int sum)
-{
-	unsigned int result = do_csum(buff, len);
-
-	/* add in old sum, and carry.. */
-	result += sum;
-	if(sum > result)
-		result += 1;
-	return result;
-}
diff --git a/include/net/tcp.h b/include/net/tcp.h
index de9dad9..b584b85 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -24,8 +24,6 @@
 /* Cancel timers, when they are not required. */
 #undef TCP_CLEAR_TIMERS
 
-#define CONFIG_TCP_CS_RECHECK 1
-
 #include <linux/config.h>
 #include <linux/tcp.h>
 #include <linux/slab.h>
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 2931ef0..b4cd6b7 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1129,82 +1129,6 @@ out:
 	sock_put(sk);
 }
 
-#ifdef CONFIG_TCP_CS_RECHECK /* Re-check the TCP header checksum */
-static u32 csum_tcpudp_nofold_alt(u32 saddr,
-                                     u32 daddr,
-                                     unsigned short len,
-                                     unsigned short proto,
-                                     unsigned int sum)
-{
-	unsigned long long s = sum;
-
-	s += saddr;
-	s += daddr;
-
-	s += (proto << 16) + ntohs(len); /*be*/
-	/*	s += (ntohs(len)<<16)+proto*256;*/ /*le*/
-	s += (s >> 32);
-
-	return (u32) s;
-}
-
-static unsigned int csum_fold_alt(unsigned int sum)
-{
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return ~sum;
-}
-
-static inline unsigned short int
-csum_tcpudp_magic_alt(unsigned long saddr, unsigned long daddr, unsigned short len,
-		   unsigned short proto, unsigned int sum)
-{
-
-	return csum_fold_alt (csum_tcpudp_nofold_alt (saddr, daddr, len, proto, sum));
-}
-
-static u16 tcp_v4_check_alt(struct tcphdr *th, int len,
-				   unsigned long saddr, unsigned long daddr, 
-				   unsigned long base)
-{
-	u16 ret;
-
-	ret = csum_tcpudp_magic_alt(saddr,daddr,len,IPPROTO_TCP,base);
-	return ret;
-}
-
-static void tcp_recheck_csum(struct tcphdr *th, int len,
-							unsigned long saddr, unsigned long daddr, 
-							int len2, unsigned int sum)
-{
-	extern int do_recheck;
-	int savedcs, altcs;
-
-	if (!do_recheck)
-		return;
-
-	savedcs = th->check;
-	th->check = 0;
-	altcs = tcp_v4_check_alt(th, len, saddr, daddr,
-			  csum_partial_alt((char *)th, len2, sum));
-	if (altcs != savedcs) {
-		printk("%s: seq %d: csum mismatch: %#x, alt %#x\n", __FUNCTION__,
-			   ntohl(th->seq), ntohs(savedcs), ntohs(altcs));
-		th->check = altcs;
-		/* Check for memory corruption */
-		__asm__("sync" ::: "memory");
-		if (*(volatile ushort *)&(th->check) != altcs) {
-			printk("%s: in mem %#x (@%#x), in reg %#x ?\n", __FUNCTION__,
-				   ntohs(th->check), &th->check, ntohs(altcs));
-		}
-	} else {
-		printk("%s: seq %#x retransmit, csum %#x OK?\n", __FUNCTION__,
-			   ntohl(th->seq), ntohs(savedcs));
-		th->check = savedcs;
-	}
-}
-#endif
-
 /* This routine computes an IPv4 TCP checksum. */
 void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, 
 		       struct sk_buff *skb)
@@ -1215,9 +1139,6 @@ void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
 	} else {
 		th->check = tcp_v4_check(th, len, sk->saddr, sk->daddr,
 					 csum_partial((char *)th, th->doff<<2, skb->csum));
-#ifdef CONFIG_TCP_CS_RECHECK
-		tcp_recheck_csum(th, len, sk->saddr, sk->daddr, th->doff<<2, skb->csum);
-#endif
 	}
 }
 
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a13b106..39c12d6 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -809,9 +809,6 @@ void tcp_simple_retransmit(struct sock *sk)
  * state updates are done by the caller.  Returns non-zero if an
  * error occurred which prevented the send.
  */
-#ifdef CONFIG_TCP_CS_RECHECK
-int do_recheck;
-#endif
 int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
@@ -872,17 +869,9 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 	 */
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
-#ifdef CONFIG_TCP_CS_RECHECK
-	do_recheck = 1;
 	err = tcp_transmit_skb(sk, (skb_cloned(skb) ?
 				    pskb_copy(skb, GFP_ATOMIC):
 				    skb_clone(skb, GFP_ATOMIC)));
-	do_recheck = 0;
-#else
-	err = tcp_transmit_skb(sk, (skb_cloned(skb) ?
-				    pskb_copy(skb, GFP_ATOMIC):
-				    skb_clone(skb, GFP_ATOMIC)));
-#endif
 
 	if (err == 0) {
 		/* Update global TCP statistics. */

[-- Attachment #3: i2c-fix-test.patch --]
[-- Type: text/x-patch, Size: 6393 bytes --]

diff --git a/drivers/i2c/i2c-algo-mpc5xxx.c b/drivers/i2c/i2c-algo-mpc5xxx.c
index 26292c7..4130aae 100644
--- a/drivers/i2c/i2c-algo-mpc5xxx.c
+++ b/drivers/i2c/i2c-algo-mpc5xxx.c
@@ -24,13 +24,20 @@
 #include <linux/i2c-algo-ppc_5xxx.h>
 
 /* #define MPC5xxx_SCAN	1 */
-#define MPC5xxx_TIMEOUT	100
+#define MPC5xxx_TIMEOUT	1000
 #define MPC5xxx_RETRIES	3
+#define MPC5xxx_SPEED_KBPS 25
 
-static int speed = 100;
+#define DEB(x) if (dlevel>=1) x;
+#define DEB2(x) if (dlevel>=2) x;
 
-MODULE_PARM(speed, "i");
+static int speed = MPC5xxx_SPEED_KBPS;   /* kbps */
+static int dlevel = 1;
 
+MODULE_PARM(speed, "i");
+MODULE_PARM_DESC(speed, "bus clock (kbps)");
+MODULE_PARM(dlevel, "i");
+MODULE_PARM_DESC(dlevel, "debug level");
 
 #ifdef CONFIG_MPC5xxx_I2C_INT
 DECLARE_WAIT_QUEUE_HEAD(i2c1_if_wq);
@@ -48,6 +55,8 @@ static int i2c2_status = 0;
 static volatile u32 *micr = (u32 *)(MPC5xxx_I2C_MICR);
 #endif
 
+static void mpc5xxx_init(struct i2c_algo_mpc5xxx_data *algo_data);
+
 static int mpc5xxx_in(volatile u32 *reg)
 {
 	return in_be32(reg) >> 24;
@@ -75,6 +84,9 @@ static void i2c_start(struct i2c_algo_mpc5xxx_data *algo_data)
 
 	mpc5xxx_out(&regs->mcr, MPC5xxx_I2C_STA, MPC5xxx_I2C_STA);
 
+        /* clear pending interrupts */
+        mpc5xxx_out(&regs->msr, 0, MPC5xxx_I2C_IF);
+
 	return;
 }
 
@@ -140,6 +152,22 @@ static void i2c2_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
 }
 #endif
 
+static void i2c_reset(struct i2c_algo_mpc5xxx_data *algo_data)
+{
+	struct mpc5xxx_i2c	*regs = algo_data->regs;
+
+        DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: resetting bus\n"));
+
+        /* Clear status, go slave */
+	mpc5xxx_out(&regs->msr, 0, 0);
+        i2c_stop(algo_data);
+
+        udelay(10000 / speed);          /* 0,1 ms @ 100 kbs */
+        mpc5xxx_init(algo_data);
+
+	return;
+}
+
 static int wait_for_bb(struct i2c_algo_mpc5xxx_data *algo_data)
 {
 	struct mpc5xxx_i2c	*regs	= algo_data->regs;
@@ -177,7 +205,15 @@ static int wait_for_bb(struct i2c_algo_mpc5xxx_data *algo_data)
 	*pstat = 0;
 #else	
 	status = mpc5xxx_in(&regs->msr);
+
+        if(status & MPC5xxx_I2C_AL) {
+            DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: AL set in wait_for_bb, status=0x%x\n", status));
+            i2c_reset(algo_data);
+            return -1;
+        }
+
 	while ((time_before(jiffies,timeout)) && (status & MPC5xxx_I2C_BB)) {
+   		udelay(10);
 		status = mpc5xxx_in(&regs->msr);
 	}
 #endif
@@ -220,13 +256,17 @@ static int wait_for_pin(struct i2c_algo_mpc5xxx_data	*algo_data,
 	*status = mpc5xxx_in(&regs->msr);
 
 	while ((time_before(jiffies,timeout)) && !(*status & MPC5xxx_I2C_IF)) {
+   		udelay(10);
 		*status = mpc5xxx_in(&regs->msr);
 	}
 #endif
 
-	if (!(*status & MPC5xxx_I2C_IF)) {
-		return -1;
-	}
+	if (!(*status & MPC5xxx_I2C_IF) || *status & MPC5xxx_I2C_AL) {
+                DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: wait_for_pin: status=0x%x\n",
+                           *status));
+                i2c_reset(algo_data);
+                return -1;
+        }
 
 	mpc5xxx_out(&regs->msr, 0, MPC5xxx_I2C_IF);
 
@@ -247,7 +287,8 @@ static int mpc5xxx_get_fdr(void)
 	ulong ipb = CONFIG_PPC_5xxx_IPBFREQ;
 #endif
 	ulong bestmatch = 0xffffffffUL;
-	int best_i = 0, best_j = 0, i, j;
+	int best_i = 3, best_j = 7;   /* values for the slowest bus */
+        int i, j;
 	int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
 	struct {int scl2tap, tap2tap; } scltap[] = {
 		{4, 1},
@@ -275,7 +316,7 @@ static int mpc5xxx_get_fdr(void)
 		}
 	}
 
-	divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+	divider = (best_i & 3) | ((best_i & 4) << 5) | (best_j << 2);
 
 	return divider;
 }
@@ -373,12 +414,9 @@ static int mpc5xxx_sendbytes(struct i2c_adapter	*adap,
 	for (wrcount = 0; wrcount < count; ++wrcount) {
 		mpc5xxx_out(&regs->mdr, buf[wrcount], 0);
 
-		if (wait_for_pin(algo_data, &status)) {
-			i2c_stop(algo_data);
-			return -EREMOTEIO;
-		}
-
-		if (status & MPC5xxx_I2C_RXAK) {
+		if (wait_for_pin(algo_data, &status) || 
+                    (status & MPC5xxx_I2C_RXAK) ) {
+                        DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: error in mpc5xxx_sendbytes, status=0x%x\n", status));
 			i2c_stop(algo_data);
 			return -EREMOTEIO;
 		}
@@ -394,36 +432,33 @@ static int mpc5xxx_readbytes(struct i2c_adapter	*adap,
 	struct i2c_algo_mpc5xxx_data	*algo_data	= adap->algo_data;
 	struct mpc5xxx_i2c		*regs		= algo_data->regs;
 	int				rdcount		= 0;
-	int				dummy		= 1;
 	int				status;
-	int				i;
 
 	mpc5xxx_out(&regs->mcr, 0, MPC5xxx_I2C_TX);
-	mpc5xxx_out(&regs->mcr, 0, MPC5xxx_I2C_TXAK);
-
-	for (i = 0; i < count; ++i) {
-		buf[rdcount] = mpc5xxx_in(&regs->mdr);
-
-		if (dummy) {
-			dummy = 0;
-		} else {
-			rdcount++;
-		}
 
-		if (i == count - 1)
-			mpc5xxx_out(&regs->mcr, MPC5xxx_I2C_TXAK, MPC5xxx_I2C_TXAK);
+	if(count > 1) {
+		mpc5xxx_out(&regs->mcr, 0, MPC5xxx_I2C_TXAK);
+	} else {
+		mpc5xxx_out(&regs->mcr, ~0, MPC5xxx_I2C_TXAK);
+	}
 
+	if(count > 0) {
+		mpc5xxx_in(&regs->mdr);
+	}
+ 
+	for (rdcount = 0; rdcount < count; ++rdcount) {
 		if (wait_for_pin(algo_data, &status)) {
 			i2c_stop(algo_data);
 			return -EREMOTEIO;
 		}
-	}
-
-	buf[rdcount++] = mpc5xxx_in(&regs->mdr);
 
-	if (wait_for_pin(algo_data, &status)) {
-		i2c_stop(algo_data);
-		return -EREMOTEIO;
+		if (rdcount == count - 1) {
+			mpc5xxx_out(&regs->mcr, ~0, MPC5xxx_I2C_TX);
+		} 
+		else if (rdcount == count - 2) {
+			mpc5xxx_out(&regs->mcr, ~0, MPC5xxx_I2C_TXAK);
+		}
+		buf[rdcount] = mpc5xxx_in(&regs->mdr);
 	}
 
 	return rdcount;
@@ -464,18 +499,23 @@ static int mpc5xxx_xfer(struct i2c_adapter	*adap,
 	for (i = 0; i < num; i++) {
 		pmsg = &msgs[i];
 
-		if (wait_for_bb(algo_data))
+		if (wait_for_bb(algo_data)) {
+			DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: wait_for_bb failed in mpc5xxx_xfer\n"));
+			i2c_reset(algo_data);
 			return -EREMOTEIO;
+		}
 
 		i2c_start(algo_data);
   		mpc5xxx_do_address(algo_data, pmsg, adap->retries);
 
 		if (wait_for_pin(algo_data, &status)) {
+			DEB(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: wait_for_pin failed in mpc5xxx_xfer, status=0x%x\n", status));
 			i2c_stop(algo_data);
 			return -EREMOTEIO;
 		}
 
-   		if (status & MPC5xxx_I2C_RXAK) {
+		if (status & MPC5xxx_I2C_RXAK) {
+			DEB2(printk(KERN_DEBUG "i2c-algo-mpc5xxx.o: RXAK set in mpc5xxx_xfer, status=0x%x\n", status));
 			i2c_stop(algo_data);
 			return -EREMOTEIO;
 		}

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

end of thread, other threads:[~2007-08-02  9:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-04 14:51 TQM5200 problems (kernel 2.4) Kimmo Surakka
2007-07-05  6:54 ` Domen Puncer
2007-07-06  6:21   ` Kimmo Surakka
2007-07-05 22:13 ` Wolfgang Denk
2007-07-06  6:25   ` Kimmo Surakka
2007-08-02  9:17     ` Kimmo Surakka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).