Skip site navigation (1)Skip section navigation (2)
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>