Date: Wed, 7 Jul 2004 17:46:30 +0000 (UTC) From: Bill Paul <wpaul@FreeBSD.org> To: src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org Subject: cvs commit: src/sys/compat/ndis ndis_var.h subr_ndis.c src/sys/dev/if_ndis if_ndis.c if_ndisvar.h Message-ID: <200407071746.i67HkUSQ075464@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
wpaul 2004-07-07 17:46:30 UTC FreeBSD src repository Modified files: sys/compat/ndis ndis_var.h subr_ndis.c sys/dev/if_ndis if_ndis.c if_ndisvar.h Log: Fix two problems: - In subr_ndis.c:ndis_allocate_sharemem(), create the busdma tags used for shared memory allocations with a lowaddr of 0x3E7FFFFF. This forces the buffers to be mapped to physical/bus addresses within the first 1GB of physical memory. It seems that at least one card (Linksys Instant Wireless PCI V2.7) depends on this behavior. I don't know if this is a hardware restriction, or if the NDIS driver for this card is truncating the addresses itself, but using physical/bus addresses beyong the 1GB limit causes initialization failures. - Create am NDIS_INITIALIZED() macro in if_ndisvar.h and use it in if_ndis.c to test whether the device has been initialized rather than checking for the presence of the IFF_UP flag in if_flags. While debugging the previous problem, I noticed that bringing up the device would always produce failures from ndis_setmulti(). It turns out that the following steps now occur during device initialization: - IFF_UP flag is set in if_flags - ifp->if_ioctl() called with SIOCSIFADDR (which we don't handle) - ifp->if_ioctl() called with SIOCADDMULTI - ifp->if_ioctl() called with SIOCADDMULTI (again) - ifp->if_ioctl() called with SIOCADDMULTI (yet again) - ifp->if_ioctl() called with SIOCSIFFLAGS Setting the receive filter and multicast filters can only be done when the underlying NDIS driver has been initialized, which is done by ifp->if_init(). However, we don't call ifp->if_init() until ifp->if_ioctl() is called with SIOCSIFFLAGS and IFF_UP has been set. It appears that now, the network stack tries to add multicast addresses to interface's filter before those steps occur. Normally, ndis_setmulti() would trap this condition by checking for the IFF_UP flag, but the network code has in fact set this flag already, so ndis_setmulti() is fooled into thinking the interface has been initialized when it really hasn't. It turns out this is usually harmless because the ifp->if_init() routine (in this case ndis_init()) will set up the multicast filter when it initializes the hardware anyway, and the underlying routines (ndis_get_info()/ndis_set_info()) know that the driver/NIC haven't been initialized yet, but you end up spurious error messages on the console all the time. Something tells me this new behavior isn't really correct. I think the intention was to fix it so that ifp->if_init() is only called once when we ifconfig an interface up, but the end result seems a little bogus: the change of the IFF_UP flag should be propagated down to the driver before calling any other ioctl() that might actually require the hardware to be up and running. Revision Changes Path 1.26 +2 -0 src/sys/compat/ndis/ndis_var.h 1.61 +15 -1 src/sys/compat/ndis/subr_ndis.c 1.65 +11 -12 src/sys/dev/if_ndis/if_ndis.c 1.14 +2 -1 src/sys/dev/if_ndis/if_ndisvar.h
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407071746.i67HkUSQ075464>