Subject: kern/36592: cdce does not work: arpresolve: can't allocate llinfo on cdce0
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <khorben@defora.org>
List: netbsd-bugs
Date: 07/01/2007 23:20:00
>Number: 36592
>Category: kern
>Synopsis: cdce does not work: arpresolve: can't allocate llinfo on cdce0
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jul 01 23:20:00 +0000 2007
>Originator: khorben@defora.org
>Release: NetBSD 4.0_BETA2
>Organization:
khorben
>Environment:
System: NetBSD syn.defora.rom 4.0_BETA2 NetBSD 4.0_BETA2 (GENERIC.MP) #6: Mon Jul 2 02:25:25 CEST 2007 khorben@syn.defora.rom:/usr/obj/sys/arch/amd64/compile/GENERIC.MP amd64
Architecture: x86_64
Machine: amd64
>Description:
Trying to communicate from NetBSD 4.0_BETA2 (amd64) to a Zaurus running
Qtopia through USB does not work. cdce0 shows up normally:
cdce0 at uhub0 port 2 configuration 1 interface 0
cdce0: Sharp SL-C3200, rev 2.00/0.00, addr 2
cdce0: faking address
cdce0: address 2a:9c:1a:00:00:00
but then after giving it directly a correct address:
# ifconfig cdce0 192.168.1.1
(when the remote peer has 192.168.1.2), reaching the Zaurus is
impossible. The kernel keeps saying:
arpresolve: can't allocate llinfo on cdce0 for 192.168.1.2
>How-To-Repeat:
Setup a Zaurus to "USB - TCP/IP (advanced)" mode and try to establish a
link. I do not own any other cdce-compliant device.
>Fix:
Manually merging the changes to if_cdce.c (1.12.10.2 to 1.12.10.3) from
the itohy-usb1 branch makes it work. I have not investigated deeper this
issue.
$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=1.295 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.395 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=1.396 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=1.396 ms
^C
----192.168.1.2 PING Statistics----
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.295/1.370/1.396/0.050 ms
$ telnet 192.168.1.2 4244
Trying 192.168.1.2...
Connected to 192.168.1.2.
Escape character is '^]'.
Index: if_cdce.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_cdce.c,v
retrieving revision 1.12
diff -u -r1.12 if_cdce.c
--- if_cdce.c 16 Nov 2006 01:33:26 -0000 1.12
+++ if_cdce.c 1 Jul 2007 22:35:23 -0000
@@ -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, caddr_t);
-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[] = {
@@ -280,6 +280,8 @@
ifp->if_ioctl = cdce_ioctl;
ifp->if_start = cdce_start;
ifp->if_watchdog = cdce_watchdog;
+ ifp->if_init = cdce_init;
+ ifp->if_stop = cdce_stop;
strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
IFQ_SET_READY(&ifp->if_snd);
@@ -310,7 +312,7 @@
}
if (ifp->if_flags & IFF_RUNNING)
- cdce_stop(sc);
+ cdce_stop(ifp, 1);
ether_ifdetach(ifp);
@@ -376,7 +378,7 @@
m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
err = usbd_transfer(c->cdce_xfer);
if (err != USBD_IN_PROGRESS) {
- cdce_stop(sc);
+ cdce_stop(GET_IFP(sc), 0);
return (EIO);
}
@@ -386,10 +388,10 @@
}
Static void
-cdce_stop(struct cdce_softc *sc)
+cdce_stop(struct ifnet *ifp, int disable)
{
+ struct cdce_softc *sc = ifp->if_softc;
usbd_status err;
- struct ifnet *ifp = GET_IFP(sc);
int i;
ifp->if_timer = 0;
@@ -447,8 +449,6 @@
cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct cdce_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
if (sc->cdce_dying)
@@ -457,42 +457,22 @@
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;
+#if 0 /* no media support */
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ errno = EINVAL;
break;
+#endif
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_flags & IFF_RUNNING))
- cdce_init(sc);
- } else {
+ default:
+ error = ether_ioctl(ifp, command, data);
+ if (error == ENETRESET) {
+#if 0 /* XXX not yet */
if (ifp->if_flags & IFF_RUNNING)
- cdce_stop(sc);
+ cdce_setmulti(sc);
+#endif
+ error = 0;
}
- error = 0;
- break;
-
- default:
- error = EINVAL;
break;
}
@@ -513,30 +493,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 (EIO);
}
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??? */
@@ -547,7 +526,7 @@
printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
usbd_errstr(err));
splx(s);
- return;
+ return (EIO);
}
err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
@@ -556,7 +535,7 @@
printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
usbd_errstr(err));
splx(s);
- return;
+ return (EIO);
}
for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
@@ -571,6 +550,8 @@
ifp->if_flags &= ~IFF_OACTIVE;
splx(s);
+
+ return (0);
}
Static int