Bug 8279

Summary: PS3: ipv6 causes ethernet hang
Product: Platform Specific/Hardware Reporter: Geoff Levand (geoffrey.levand)
Component: PS3Assignee: Olaf Kirch (okir)
Status: RESOLVED CODE_FIX    
Severity: normal CC: dwmw2, okir
Priority: P2    
Hardware: i386   
OS: Linux   
Kernel Version: 2.6.21-rc5-ps3-linux-dev-g07b2d645 Subsystem:
Regression: --- Bisected commit-id:

Description Geoff Levand 2007-03-28 17:03:25 UTC
Gelic ether driver seems to hang when using ipv6.

<6>NETDEV WATCHDOG: eth0: transmit timed out
Timed out. Restarting...
 -> gelic_net_open:1386
<5>nfs: server 192.168.1.10 OK

Steps to reproduce:

1) On the PS3 'ip -6 addr add fec0::1/64 dev eth0'.

2) On another machine "ip -6 addr add fec0::2/64 dev eth0".
3) On the other machine "ssh fec0::1"
Comment 1 David Woodhouse 2007-03-29 08:45:03 UTC
Note that icmp6 and udp6 seem to work just fine -- it's just tcp6 which kills
it. A checksum problem, perhaps?
Comment 2 Olaf Kirch 2007-04-11 04:51:30 UTC
Likely.

I don't know if this is the latest driver, but the patch I found claims that
the device supports arbitrary checksumming (NETIF_F_HW_CSUM) but really just
supports NETIF_F_IP_CSUM:

+static void
+gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
+			       struct sk_buff *skb, int middle)
+{
+	uint32_t nocs, tcpcs, udpcs;
+
+	if (middle) {
+		nocs =  GELIC_NET_DMAC_CMDSTAT_NOCS;
+		tcpcs = GELIC_NET_DMAC_CMDSTAT_TCPCS;
+		udpcs = GELIC_NET_DMAC_CMDSTAT_UDPCS;
+	}else {
+		nocs =  GELIC_NET_DMAC_CMDSTAT_NOCS  
+			| GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+		tcpcs = GELIC_NET_DMAC_CMDSTAT_TCPCS 
+			| GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+		udpcs = GELIC_NET_DMAC_CMDSTAT_UDPCS 
+			| GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+	}
+
+	if (skb->ip_summed != CHECKSUM_HW) {
+		descr->dmac_cmd_status = nocs;
+	} else {
+		/* is packet ip?
+		 * if yes: tcp? udp? */
+		if (skb->protocol == htons(ETH_P_IP)) {
+			if (skb->nh.iph->protocol == IPPROTO_TCP) {
+				descr->dmac_cmd_status = tcpcs;
+			} else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+				descr->dmac_cmd_status = udpcs;
+			} else { /* the stack should checksum non-tcp and 
non-udp
+				    packets on his own: NETIF_F_IP_CSUM */
+				descr->dmac_cmd_status = nocs;
+			}
+		}
+	}
+}


This means if tx checksums are enabled, and a non-IP packet is sent,
descr->dmac_cmd_status will potentially contain garbage.

Simple fix: s/NETIF_F_HW_CSUM/NETIF_F_IP_CSUM/

If the card indeed supports any kind of checksum, gelic_net_set_txdescr_cmdstat
needs to be fixed to do the right thing.
Comment 3 David Woodhouse 2007-04-13 06:19:39 UTC
 s/NETIF_F_HW_CSUM/NETIF_F_IP_CSUM/ works fine here; thanks.
Comment 4 Olaf Kirch 2007-04-13 06:51:43 UTC
Okay, whom do I talk to to get this patch included? The driver isn't in
mainline.
Comment 5 David Woodhouse 2007-04-13 06:54:24 UTC
They're aware of this issue already but for future reference I suppose
cbe-oss-dev@ozlabs.org
Comment 6 Olaf Kirch 2007-04-13 13:26:57 UTC
Patch submitted to Geoff + cbe-oss-dev@ozlabs.org
Closing as fixed