Subject: kern/37653: cdce fails with iPaq Linux
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <scotte@warped.com>
List: netbsd-bugs
Date: 12/31/2007 17:40:00
>Number:         37653
>Category:       kern
>Synopsis:       Using cdce to communicate with an iPaq running iPaq Linux (ala Familiar) fails with llinfo allocation error
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Dec 31 17:40:00 +0000 2007
>Originator:     Scott Ellis
>Release:        NetBSD 4.99.44
>Organization:
	
>Environment:
	
	
System: NetBSD intrepid 4.99.44 NetBSD 4.99.44 (INTREPID.P5W) #0: Sat Dec 22 09:15:05 PST 2007 scotte@intrepid:/nbu/source/netbsd/src/obj.amd64/nbu/source/netbsd/src/sys/arch/amd64/compile/INTREPID.P5W amd64
Architecture: x86_64
Machine: amd64
>Description:
	
Attaching an iPaq running the Familiar (handhelds.org) distribution to a NetBSD
system, and attempting to communicate via cdce(4) fails.  First, it fails to
attach cdce to the interface, instead getting ugen.  This is easily correctable.
Next, when doing an 'ifconfig cdce0 up', the system reports it "can't allocate
llinfo on cdce0".  This is less trivial to fix.

The net result is that the device is unable to communicate.

>How-To-Repeat:
	
Connect iPaq Linux based device (using SA1110 peripheral controller) to a
NetBSD system using USB.  Note that cdce is not attached.  Change if_cdce.c to
allow attachment, and re-attach iPaq.  Note that attempting to use the cdce0
device fails with the aforementioned error.
>Fix:
	
A partial fix is listen in kern/36592.  I've updated it for -current, and added
the correct entries so that cdce will match the SA1110 peripheral controller.
The diff against $NetBSD: if_cdce.c,v 1.14 2007/03/13 13:51:54 drochner Exp $
is shown below:

--- /usr/src/sys/dev/usb/if_cdce.c.orig	2007-12-29 09:48:41.000000000 -0800
+++ if_cdce.c.scotte_ipaqlinux	2007-12-29 11:33:03.000000000 -0800
@@ -109,9 +109,9 @@
 Static void	 cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
 Static void	 cdce_start(struct ifnet *);
 Static int	 cdce_ioctl(struct ifnet *, u_long, void *);
-Static void	 cdce_init(void *);
+Static int	 cdce_init(struct ifnet *);
 Static void	 cdce_watchdog(struct ifnet *);
-Static void	 cdce_stop(struct cdce_softc *);
+Static void	 cdce_stop(struct ifnet *, int);
 Static uint32_t	 cdce_crc32(const void *, size_t);
 
 Static const struct cdce_type cdce_devs[] = {
@@ -450,42 +450,11 @@
 	s = splnet();
 
 	switch(command) {
-	case SIOCSIFADDR:
-		ifp->if_flags |= IFF_UP;
-		cdce_init(sc);
-		switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
-		case AF_INET:
-#if defined(__NetBSD__)
-			arp_ifinit(ifp, ifa);
-#else
-			arp_ifinit(&sc->arpcom, ifa);
-#endif
-			break;
-#endif /* INET */
-		}
-		break;
-
-	case SIOCSIFMTU:
-		if (ifr->ifr_mtu > ETHERMTU)
-			error = EINVAL;
-		else
-			ifp->if_mtu = ifr->ifr_mtu;
-		break;
-
-	case SIOCSIFFLAGS:
-		if (ifp->if_flags & IFF_UP) {
-			if (!(ifp->if_flags & IFF_RUNNING))
-				cdce_init(sc);
-		} else {
-			if (ifp->if_flags & IFF_RUNNING)
-				cdce_stop(sc);
-		}
-		error = 0;
-		break;
-
 	default:
-		error = EINVAL;
+			error = ether_ioctl(ifp, command, data);
+			if (error == ENETRESET) {
+			error = 0;
+			}
 		break;
 	}
 
@@ -506,30 +475,29 @@
 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
 }
 
-Static void
-cdce_init(void *xsc)
+Static int
+cdce_init(struct ifnet *ifp)
 {
-	struct cdce_softc	*sc = xsc;
-	struct ifnet		*ifp = GET_IFP(sc);
+	struct cdce_softc	*sc = ifp->if_softc;
 	struct cdce_chain	*c;
 	usbd_status		 err;
 	int			 s, i;
 
 	if (ifp->if_flags & IFF_RUNNING)
-		return;
+		return (EIO);
 
 	s = splnet();
 
 	if (cdce_tx_list_init(sc) == ENOBUFS) {
 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
 		splx(s);
-		return;
+		return (ENOMEM);
 	}
 
 	if (cdce_rx_list_init(sc) == ENOBUFS) {
 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
 		splx(s);
-		return;
+		return (ENOMEM);
 	}
 
 	/* Maybe set multicast / broadcast here??? */
@@ -564,6 +532,8 @@
 	ifp->if_flags &= ~IFF_OACTIVE;
 
 	splx(s);
+
+	return (0);
 }
 
 Static int

>Unformatted: