Hello,

The following patch is to remove uether(4) dependency of aue(4) and
change logs would be as follows:

  - removes uether module dependency of aue(4) that finally uether
    module would be gone.  The reasons why I'm trying to remove uether
    module are that
      I discussed with USB ethernet maintainers about whether it's
      useful or not.  yongari@ answered that it's not helpful, not
      straight forward to understand and make code complex.
  - adds newly two uether APIs, uether_alloc_unr and uether_free_unr for
    backward compatibility because current interface names for each
    ethernet devices are linux-style `ue[0-9]+'.  The naming rule would
    be kept at STABLE_8 but not sure at STABLE_9.

If no objections I'd like to see this patch at HEAD.

regards,
Weongyo Jeong

Index: usb_ethernet.c
===================================================================
--- usb_ethernet.c      (revision 214568)
+++ usb_ethernet.c      (working copy)
@@ -597,5 +597,19 @@ uether_rxflush(struct usb_ether *ue)
        }
 }
 
+int
+uether_alloc_unr(void)
+{
+
+       return (alloc_unr(ueunit));
+}
+
+void
+uether_free_unr(int unit)
+{
+
+       free_unr(ueunit, unit);
+}
+
 DECLARE_MODULE(uether, uether_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
 MODULE_VERSION(uether, 1);
Index: if_aue.c
===================================================================
--- if_aue.c    (revision 214568)
+++ if_aue.c    (working copy)
@@ -81,6 +81,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/condvar.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
 #include <sys/sysctl.h>
 #include <sys/sx.h>
 #include <sys/unistd.h>
@@ -88,6 +90,19 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/priv.h>
 
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
+#include <net/ethernet.h>
+
+#include "miibus_if.h"
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
@@ -96,6 +111,7 @@ __FBSDID("$FreeBSD$");
 #define        USB_DEBUG_VAR aue_debug
 #include <dev/usb/usb_debug.h>
 #include <dev/usb/usb_process.h>
+#include <dev/usb/usb_sleepout.h>
 
 #include <dev/usb/net/usb_ethernet.h>
 #include <dev/usb/net/if_auereg.h>
@@ -197,14 +213,6 @@ static usb_callback_t aue_intr_callback;
 static usb_callback_t aue_bulk_read_callback;
 static usb_callback_t aue_bulk_write_callback;
 
-static uether_fn_t aue_attach_post;
-static uether_fn_t aue_init;
-static uether_fn_t aue_stop;
-static uether_fn_t aue_start;
-static uether_fn_t aue_tick;
-static uether_fn_t aue_setmulti;
-static uether_fn_t aue_setpromisc;
-
 static uint8_t aue_csr_read_1(struct aue_softc *, uint16_t);
 static uint16_t        aue_csr_read_2(struct aue_softc *, uint16_t);
 static void    aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
@@ -217,6 +225,20 @@ static void        aue_reset_pegasus_II(struct aue_softc
 
 static int     aue_ifmedia_upd(struct ifnet *);
 static void    aue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int     aue_ioctl(struct ifnet *, u_long, caddr_t);
+static void    aue_start(struct ifnet *);
+static void    aue_start_locked(struct ifnet *);
+static void    aue_init(void *);
+static void    aue_stop_locked(struct aue_softc *);
+static void    aue_setmulti(void *, int);
+static void    aue_setmulti_locked(struct aue_softc *);
+static void    aue_rxflush(struct aue_softc *);
+static int     aue_rxbuf(struct aue_softc *, struct usb_page_cache *, 
+                   unsigned int, unsigned int);
+static void    aue_setpromisc(void *, int);
+static void    aue_setpromisc_locked(struct aue_softc *);
+static void    aue_init_locked(struct aue_softc *);
+static void    aue_watchdog(void *);
 
 static const struct usb_config aue_config[AUE_N_TRANSFER] = {
 
@@ -283,24 +305,19 @@ MODULE_DEPEND(aue, ether, 1, 1, 1);
 MODULE_DEPEND(aue, miibus, 1, 1, 1);
 MODULE_VERSION(aue, 1);
 
-static const struct usb_ether_methods aue_ue_methods = {
-       .ue_attach_post = aue_attach_post,
-       .ue_start = aue_start,
-       .ue_init = aue_init,
-       .ue_stop = aue_stop,
-       .ue_tick = aue_tick,
-       .ue_setmulti = aue_setmulti,
-       .ue_setpromisc = aue_setpromisc,
-       .ue_mii_upd = aue_ifmedia_upd,
-       .ue_mii_sts = aue_ifmedia_sts,
-};
-
 #define        AUE_SETBIT(sc, reg, x) \
        aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x))
 
 #define        AUE_CLRBIT(sc, reg, x) \
        aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x))
 
+static void
+aue_pause(struct aue_softc *sc, unsigned int _ticks)
+{
+
+       usb_pause_mtx(&sc->sc_mtx, _ticks);
+}
+
 static uint8_t
 aue_csr_read_1(struct aue_softc *sc, uint16_t reg)
 {
@@ -314,7 +331,8 @@ aue_csr_read_1(struct aue_softc *sc, uint16_t reg)
        USETW(req.wIndex, reg);
        USETW(req.wLength, 1);
 
-       err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
+       err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, &val, 0,
+           NULL, 1000);
        if (err)
                return (0);
        return (val);
@@ -333,7 +351,8 @@ aue_csr_read_2(struct aue_softc *sc, uint16_t reg)
        USETW(req.wIndex, reg);
        USETW(req.wLength, 2);
 
-       err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
+       err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, &val, 0,
+           NULL, 1000);
        if (err)
                return (0);
        return (le16toh(val));
@@ -351,9 +370,9 @@ aue_csr_write_1(struct aue_softc *sc, uint16_t reg
        USETW(req.wIndex, reg);
        USETW(req.wLength, 1);
 
-       if (uether_do_request(&sc->sc_ue, &req, &val, 1000)) {
-               /* error ignored */
-       }
+       /* XXX error ignored */
+       (void)usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, &val, 0,
+           NULL, 1000);
 }
 
 static void
@@ -369,9 +388,9 @@ aue_csr_write_2(struct aue_softc *sc, uint16_t reg
 
        val = htole16(val);
 
-       if (uether_do_request(&sc->sc_ue, &req, &val, 1000)) {
-               /* error ignored */
-       }
+       /* XXX error ignored */
+       (void)usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, &val, 0,
+           NULL, 1000);
 }
 
 /*
@@ -389,12 +408,11 @@ aue_eeprom_getword(struct aue_softc *sc, int addr,
        for (i = 0; i != AUE_TIMEOUT; i++) {
                if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE)
                        break;
-               if (uether_pause(&sc->sc_ue, hz / 100))
-                       break;
+               aue_pause(sc, hz / 100);
        }
 
        if (i == AUE_TIMEOUT)
-               device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
+               device_printf(sc->sc_dev, "EEPROM read timed out\n");
 
        word = aue_csr_read_2(sc, AUE_EE_DATA);
        *dest = word;
@@ -446,12 +464,11 @@ aue_miibus_readreg(device_t dev, int phy, int reg)
        for (i = 0; i != AUE_TIMEOUT; i++) {
                if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE)
                        break;
-               if (uether_pause(&sc->sc_ue, hz / 100))
-                       break;
+               aue_pause(sc, hz / 100);
        }
 
        if (i == AUE_TIMEOUT)
-               device_printf(sc->sc_ue.ue_dev, "MII read timed out\n");
+               device_printf(sc->sc_dev, "MII read timed out\n");
 
        val = aue_csr_read_2(sc, AUE_PHY_DATA);
 
@@ -482,12 +499,11 @@ aue_miibus_writereg(device_t dev, int phy, int reg
        for (i = 0; i != AUE_TIMEOUT; i++) {
                if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE)
                        break;
-               if (uether_pause(&sc->sc_ue, hz / 100))
-                       break;
+               aue_pause(sc, hz / 100);
        }
 
        if (i == AUE_TIMEOUT)
-               device_printf(sc->sc_ue.ue_dev, "MII write timed out\n");
+               device_printf(sc->sc_dev, "MII write timed out\n");
 
        if (!locked)
                AUE_UNLOCK(sc);
@@ -533,12 +549,21 @@ aue_miibus_statchg(device_t dev)
                AUE_UNLOCK(sc);
 }
 
+static void
+aue_setmulti(void *arg, int npending)
+{
+       struct aue_softc *sc = arg;
+
+       AUE_LOCK(sc);
+       aue_setmulti_locked(sc);
+       AUE_UNLOCK(sc);
+}
+
 #define        AUE_BITS        6
 static void
-aue_setmulti(struct usb_ether *ue)
+aue_setmulti_locked(struct aue_softc *sc)
 {
-       struct aue_softc *sc = uether_getsc(ue);
-       struct ifnet *ifp = uether_getifp(ue);
+       struct ifnet *ifp = sc->sc_ifp;
        struct ifmultiaddr *ifma;
        uint32_t h = 0;
        uint32_t i;
@@ -572,6 +597,7 @@ static void
 static void
 aue_reset_pegasus_II(struct aue_softc *sc)
 {
+
        /* Magic constants taken from Linux driver. */
        aue_csr_write_1(sc, AUE_REG_1D, 0);
        aue_csr_write_1(sc, AUE_REG_7B, 2);
@@ -593,12 +619,11 @@ aue_reset(struct aue_softc *sc)
        for (i = 0; i != AUE_TIMEOUT; i++) {
                if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC))
                        break;
-               if (uether_pause(&sc->sc_ue, hz / 100))
-                       break;
+               aue_pause(sc, hz / 100);
        }
 
        if (i == AUE_TIMEOUT)
-               device_printf(sc->sc_ue.ue_dev, "reset failed\n");
+               device_printf(sc->sc_dev, "reset failed\n");
 
        /*
         * The PHY(s) attached to the Pegasus chip may be held
@@ -625,21 +650,9 @@ aue_reset(struct aue_softc *sc)
                aue_reset_pegasus_II(sc);
 
        /* Wait a little while for the chip to get its brains in order: */
-       uether_pause(&sc->sc_ue, hz / 100);
+       aue_pause(sc, hz / 100);
 }
 
-static void
-aue_attach_post(struct usb_ether *ue)
-{
-       struct aue_softc *sc = uether_getsc(ue);
-
-       /* reset the adapter */
-       aue_reset(sc);
-
-       /* get station address from the EEPROM */
-       aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
-}
-
 /*
  * Probe for a Pegasus chip.
  */
@@ -676,7 +689,7 @@ aue_attach(device_t dev)
 {
        struct usb_attach_arg *uaa = device_get_ivars(dev);
        struct aue_softc *sc = device_get_softc(dev);
-       struct usb_ether *ue = &sc->sc_ue;
+       struct ifnet *ifp;
        uint8_t iface_index;
        int error;
 
@@ -688,7 +701,16 @@ aue_attach(device_t dev)
        }
 
        device_set_usb_desc(dev);
+       sc->sc_dev = dev;
+       sc->sc_udev = uaa->device;
+       sc->sc_unit = uether_alloc_unr();
+
        mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+       sx_init(&sc->sc_sx, "aue sxlock");
+       sleepout_create(&sc->sc_sleepout, "aue sleepout");
+       sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0);
+       TASK_INIT(&sc->sc_setmulti, 0, aue_setmulti, sc);
+       TASK_INIT(&sc->sc_setpromisc, 0, aue_setpromisc, sc);
 
        iface_index = AUE_IFACE_IDX;
        error = usbd_transfer_setup(uaa->device, &iface_index,
@@ -699,19 +721,42 @@ aue_attach(device_t dev)
                goto detach;
        }
 
-       ue->ue_sc = sc;
-       ue->ue_dev = dev;
-       ue->ue_udev = uaa->device;
-       ue->ue_mtx = &sc->sc_mtx;
-       ue->ue_methods = &aue_ue_methods;
+       AUE_LOCK(sc);
+       /* reset the adapter */
+       aue_reset(sc);
+       /* get station address from the EEPROM */
+       aue_read_eeprom(sc, sc->sc_eaddr, 0, 3);
+       AUE_UNLOCK(sc);
 
-       error = uether_ifattach(ue);
+       sc->sc_ifp = ifp = if_alloc(IFT_ETHER);
+       if (ifp == NULL) {
+               device_printf(sc->sc_dev, "could not allocate ifnet\n");
+               goto detach;
+       }
+
+       ifp->if_softc = sc;
+       if_initname(ifp, "ue", sc->sc_unit);
+       ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_ioctl = aue_ioctl;
+       ifp->if_start = aue_start;
+       ifp->if_init = aue_init;
+       IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+       ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+       IFQ_SET_READY(&ifp->if_snd);
+
+       error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
+           aue_ifmedia_upd, aue_ifmedia_sts,
+           BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
        if (error) {
-               device_printf(dev, "could not attach interface\n");
+               device_printf(sc->sc_dev, "MII without any PHY\n");
                goto detach;
        }
-       return (0);                     /* success */
 
+       if_printf(ifp, "<USB Ethernet> on %s\n",
+           device_get_nameunit(sc->sc_dev));
+       ether_ifattach(ifp, sc->sc_eaddr);
+       return (0);
 detach:
        aue_detach(dev);
        return (ENXIO);                 /* failure */
@@ -721,11 +766,26 @@ static int
 aue_detach(device_t dev)
 {
        struct aue_softc *sc = device_get_softc(dev);
-       struct usb_ether *ue = &sc->sc_ue;
+       struct ifnet *ifp = sc->sc_ifp;
 
+       sleepout_drain(&sc->sc_watchdog);
+       SLEEPOUT_DRAINTASK(&sc->sc_sleepout, &sc->sc_setpromisc);
+       SLEEPOUT_DRAINTASK(&sc->sc_sleepout, &sc->sc_setmulti);
        usbd_transfer_unsetup(sc->sc_xfer, AUE_N_TRANSFER);
-       uether_ifdetach(ue);
+
+       if (sc->sc_miibus != NULL)
+               device_delete_child(sc->sc_dev, sc->sc_miibus);
+       if (ifp != NULL) {
+               AUE_LOCK(sc);
+               ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+               AUE_UNLOCK(sc);
+               ether_ifdetach(ifp);
+               if_free(ifp);
+       }
+       sleepout_free(&sc->sc_sleepout);
+       sx_destroy(&sc->sc_sx);
        mtx_destroy(&sc->sc_mtx);
+       uether_free_unr(sc->sc_unit);
 
        return (0);
 }
@@ -734,7 +794,7 @@ static void
 aue_intr_callback(struct usb_xfer *xfer, usb_error_t error)
 {
        struct aue_softc *sc = usbd_xfer_softc(xfer);
-       struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+       struct ifnet *ifp = sc->sc_ifp;
        struct aue_intrpkt pkt;
        struct usb_page_cache *pc;
        int actlen;
@@ -743,10 +803,8 @@ aue_intr_callback(struct usb_xfer *xfer, usb_error
 
        switch (USB_GET_STATE(xfer)) {
        case USB_ST_TRANSFERRED:
-
                if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
                    actlen >= sizeof(pkt)) {
-
                        pc = usbd_xfer_get_frame(xfer, 0);
                        usbd_copy_out(pc, 0, &pkt, sizeof(pkt));
 
@@ -762,7 +820,6 @@ tr_setup:
                usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
                usbd_transfer_submit(xfer);
                return;
-
        default:                        /* Error */
                if (error != USB_ERR_CANCELLED) {
                        /* try to clear stall first */
@@ -777,8 +834,7 @@ static void
 aue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
 {
        struct aue_softc *sc = usbd_xfer_softc(xfer);
-       struct usb_ether *ue = &sc->sc_ue;
-       struct ifnet *ifp = uether_getifp(ue);
+       struct ifnet *ifp = sc->sc_ifp;
        struct aue_rxpkt stat;
        struct usb_page_cache *pc;
        int actlen;
@@ -791,13 +847,11 @@ aue_bulk_read_callback(struct usb_xfer *xfer, usb_
                DPRINTFN(11, "received %d bytes\n", actlen);
 
                if (sc->sc_flags & AUE_FLAG_VER_2) {
-
                        if (actlen == 0) {
                                ifp->if_ierrors++;
                                goto tr_setup;
                        }
                } else {
-
                        if (actlen <= sizeof(stat) + ETHER_CRC_LEN) {
                                ifp->if_ierrors++;
                                goto tr_setup;
@@ -817,16 +871,14 @@ aue_bulk_read_callback(struct usb_xfer *xfer, usb_
                        /* No errors; receive the packet. */
                        actlen -= (sizeof(stat) + ETHER_CRC_LEN);
                }
-               uether_rxbuf(ue, pc, 0, actlen);
-
+               aue_rxbuf(sc, pc, 0, actlen);
                /* FALLTHROUGH */
        case USB_ST_SETUP:
 tr_setup:
                usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
                usbd_transfer_submit(xfer);
-               uether_rxflush(ue);
+               aue_rxflush(sc);
                return;
-
        default:                        /* Error */
                DPRINTF("bulk read error, %s\n",
                    usbd_errstr(error));
@@ -844,7 +896,7 @@ static void
 aue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
        struct aue_softc *sc = usbd_xfer_softc(xfer);
-       struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+       struct ifnet *ifp = sc->sc_ifp;
        struct usb_page_cache *pc;
        struct mbuf *m;
        uint8_t buf[2];
@@ -857,7 +909,6 @@ aue_bulk_write_callback(struct usb_xfer *xfer, usb
        case USB_ST_TRANSFERRED:
                DPRINTFN(11, "transfer of %d bytes complete\n", actlen);
                ifp->if_opackets++;
-
                /* FALLTHROUGH */
        case USB_ST_SETUP:
 tr_setup:
@@ -874,13 +925,10 @@ tr_setup:
                if (m->m_pkthdr.len > MCLBYTES)
                        m->m_pkthdr.len = MCLBYTES;
                if (sc->sc_flags & AUE_FLAG_VER_2) {
-
                        usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
 
                        usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
-
                } else {
-
                        usbd_xfer_set_frame_len(xfer, 0, (m->m_pkthdr.len + 2));
 
                        /*
@@ -908,7 +956,6 @@ tr_setup:
 
                usbd_transfer_submit(xfer);
                return;
-
        default:                        /* Error */
                DPRINTFN(11, "transfer error, %s\n",
                    usbd_errstr(error));
@@ -925,9 +972,8 @@ tr_setup:
 }
 
 static void
-aue_tick(struct usb_ether *ue)
+aue_tick(struct aue_softc *sc)
 {
-       struct aue_softc *sc = uether_getsc(ue);
        struct mii_data *mii = GET_MII(sc);
 
        AUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -937,15 +983,27 @@ static void
            && mii->mii_media_status & IFM_ACTIVE &&
            IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
                sc->sc_flags |= AUE_FLAG_LINK;
-               aue_start(ue);
+               aue_start_locked(sc->sc_ifp);
        }
 }
 
 static void
-aue_start(struct usb_ether *ue)
+aue_start(struct ifnet *ifp)
 {
-       struct aue_softc *sc = uether_getsc(ue);
+       struct aue_softc *sc = ifp->if_softc;
 
+       AUE_LOCK(sc);
+       aue_start_locked(ifp);
+       AUE_UNLOCK(sc);
+}
+
+static void
+aue_start_locked(struct ifnet *ifp)
+{
+       struct aue_softc *sc = ifp->if_softc;
+
+       AUE_LOCK_ASSERT(sc, MA_OWNED);
+
        /*
         * start the USB transfers, if not already started:
         */
@@ -955,10 +1013,21 @@ static void
 }
 
 static void
-aue_init(struct usb_ether *ue)
+aue_init(void *arg)
 {
-       struct aue_softc *sc = uether_getsc(ue);
-       struct ifnet *ifp = uether_getifp(ue);
+       struct aue_softc *sc = arg;
+
+       AUE_SXLOCK(sc);
+       AUE_LOCK(sc);
+       aue_init_locked(sc);
+       AUE_UNLOCK(sc);
+       AUE_SXUNLOCK(sc);
+}
+
+static void
+aue_init_locked(struct aue_softc *sc)
+{
+       struct ifnet *ifp = sc->sc_ifp;
        int i;
 
        AUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -973,10 +1042,10 @@ static void
                aue_csr_write_1(sc, AUE_PAR0 + i, IF_LLADDR(ifp)[i]);
 
        /* update promiscuous setting */
-       aue_setpromisc(ue);
+       aue_setpromisc_locked(sc);
 
        /* Load the multicast filter. */
-       aue_setmulti(ue);
+       aue_setmulti_locked(sc);
 
        /* Enable RX and TX */
        aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB);
@@ -986,15 +1055,25 @@ static void
        usbd_xfer_set_stall(sc->sc_xfer[AUE_BULK_DT_WR]);
 
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
-       aue_start(ue);
+       sleepout_reset(&sc->sc_watchdog, hz, aue_watchdog, sc);
+       aue_start_locked(sc->sc_ifp);
 }
 
 static void
-aue_setpromisc(struct usb_ether *ue)
+aue_setpromisc(void *arg, int npending)
 {
-       struct aue_softc *sc = uether_getsc(ue);
-       struct ifnet *ifp = uether_getifp(ue);
+       struct aue_softc *sc = arg;
 
+       AUE_LOCK(sc);
+       aue_setpromisc_locked(sc);
+       AUE_UNLOCK(sc);
+}
+
+static void
+aue_setpromisc_locked(struct aue_softc *sc)
+{
+       struct ifnet *ifp = sc->sc_ifp;
+
        AUE_LOCK_ASSERT(sc, MA_OWNED);
 
        /* if we want promiscuous mode, set the allframes bit: */
@@ -1013,8 +1092,7 @@ aue_ifmedia_upd(struct ifnet *ifp)
        struct aue_softc *sc = ifp->if_softc;
        struct mii_data *mii = GET_MII(sc);
 
-       AUE_LOCK_ASSERT(sc, MA_OWNED);
-
+       AUE_LOCK(sc);
         sc->sc_flags &= ~AUE_FLAG_LINK;
        if (mii->mii_instance) {
                struct mii_softc *miisc;
@@ -1023,6 +1101,7 @@ aue_ifmedia_upd(struct ifnet *ifp)
                        mii_phy_reset(miisc);
        }
        mii_mediachg(mii);
+       AUE_UNLOCK(sc);
        return (0);
 }
 
@@ -1047,11 +1126,21 @@ aue_ifmedia_sts(struct ifnet *ifp, struct ifmediar
  * RX and TX lists.
  */
 static void
-aue_stop(struct usb_ether *ue)
+aue_stop(struct aue_softc *sc)
 {
-       struct aue_softc *sc = uether_getsc(ue);
-       struct ifnet *ifp = uether_getifp(ue);
 
+       AUE_SXLOCK(sc);
+       AUE_LOCK(sc);
+       aue_stop_locked(sc);
+       AUE_UNLOCK(sc);
+       AUE_SXUNLOCK(sc);
+}
+
+static void
+aue_stop_locked(struct aue_softc *sc)
+{
+       struct ifnet *ifp = sc->sc_ifp;
+
        AUE_LOCK_ASSERT(sc, MA_OWNED);
 
        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -1068,3 +1157,125 @@ static void
        aue_csr_write_1(sc, AUE_CTL1, 0);
        aue_reset(sc);
 }
+
+static int
+aue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+       struct aue_softc *sc = ifp->if_softc;
+       struct ifreq *ifr = (struct ifreq *)data;
+       struct mii_data *mii = GET_MII(sc);
+       int error = 0, drv_flags, flags;
+
+       switch (command) {
+       case SIOCSIFFLAGS:
+               /* Avoids race and LOR between mutex and sx lock. */
+               AUE_LOCK(sc);
+               flags = ifp->if_flags;
+               drv_flags = ifp->if_drv_flags;
+               AUE_UNLOCK(sc);
+               /* device up and down is synchronous using sx(9) lock */
+               if (flags & IFF_UP) {
+                       if (drv_flags & IFF_DRV_RUNNING)
+                               SLEEPOUT_RUNTASK(&sc->sc_sleepout,
+                                   &sc->sc_setpromisc);
+                       else
+                               aue_init(sc);
+               } else
+                       aue_stop(sc);
+               break;
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               /* To avoid LOR by in_multi_mtx (netinet/in_mcast.c) */
+               if (ifp->if_flags & IFF_UP &&
+                   ifp->if_drv_flags & IFF_DRV_RUNNING)
+                       SLEEPOUT_RUNTASK(&sc->sc_sleepout, &sc->sc_setmulti);
+               break;
+       case SIOCGIFMEDIA:
+       case SIOCSIFMEDIA:
+               error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+               break;
+       default:
+               error = ether_ioctl(ifp, command, data);
+               break;
+       }
+       return (error);
+}
+
+static void
+aue_rxflush(struct aue_softc *sc)
+{
+       struct ifnet *ifp = sc->sc_ifp;
+       struct mbuf *m;
+
+       AUE_LOCK_ASSERT(sc, MA_OWNED);
+
+       for (;;) {
+               _IF_DEQUEUE(&sc->sc_rxq, m);
+               if (m == NULL)
+                       break;
+
+               /*
+                * The USB xfer has been resubmitted so its safe to unlock now.
+                */
+               AUE_UNLOCK(sc);
+               ifp->if_input(ifp, m);
+               AUE_LOCK(sc);
+       }
+}
+
+static struct mbuf *
+aue_newbuf(void)
+{
+       struct mbuf *m_new;
+
+       m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+       if (m_new == NULL)
+               return (NULL);
+       m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+
+       m_adj(m_new, ETHER_ALIGN);
+       return (m_new);
+}
+
+static int
+aue_rxbuf(struct aue_softc *sc, struct usb_page_cache *pc, 
+    unsigned int offset, unsigned int len)
+{
+       struct ifnet *ifp = sc->sc_ifp;
+       struct mbuf *m;
+
+       AUE_LOCK_ASSERT(sc, MA_OWNED);
+
+       if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN)
+               return (1);
+
+       m = aue_newbuf();
+       if (m == NULL) {
+               ifp->if_ierrors++;
+               return (ENOMEM);
+       }
+
+       usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
+
+       /* finalize mbuf */
+       ifp->if_ipackets++;
+       m->m_pkthdr.rcvif = ifp;
+       m->m_pkthdr.len = m->m_len = len;
+
+       /* enqueue for later when the lock can be released */
+       _IF_ENQUEUE(&sc->sc_rxq, m);
+       return (0);
+}
+
+static void
+aue_watchdog(void *arg)
+{
+       struct aue_softc *sc = arg;
+       struct ifnet *ifp = sc->sc_ifp;
+
+       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+               return;
+
+       aue_tick(sc);
+       sleepout_reset(&sc->sc_watchdog, hz, aue_watchdog, sc);
+}
Index: if_auereg.h
===================================================================
--- if_auereg.h (revision 214568)
+++ if_auereg.h (working copy)
@@ -183,7 +183,7 @@ enum {
 #define        AUE_RXSTAT_DRIBBLE      0x10
 #define        AUE_RXSTAT_MASK         0x1E
 
-#define        GET_MII(sc)             uether_getmii(&(sc)->sc_ue)
+#define        GET_MII(sc)             (device_get_softc(sc->sc_miibus))
 
 struct aue_intrpkt {
        uint8_t aue_txstat0;
@@ -202,10 +202,16 @@ struct aue_rxpkt {
 } __packed;
 
 struct aue_softc {
-       struct usb_ether        sc_ue;
+       struct ifnet            *sc_ifp;
+       device_t                sc_dev;
+       device_t                sc_miibus;
+       struct usb_device       *sc_udev; /* used by uether_do_request() */
+       struct usb_xfer         *sc_xfer[AUE_N_TRANSFER];
        struct mtx              sc_mtx;
-       struct usb_xfer *sc_xfer[AUE_N_TRANSFER];
-
+       struct sx               sc_sx;
+       struct ifqueue          sc_rxq;
+       /* ethernet address from eeprom */
+       uint8_t                 sc_eaddr[ETHER_ADDR_LEN];
        int                     sc_flags;
 #define        AUE_FLAG_LSYS           0x0001  /* use Linksys reset */
 #define        AUE_FLAG_PNA            0x0002  /* has Home PNA */
@@ -213,8 +219,16 @@ struct aue_softc {
 #define        AUE_FLAG_LINK           0x0008  /* wait for link to come up */
 #define        AUE_FLAG_VER_2          0x0200  /* chip is version 2 */
 #define        AUE_FLAG_DUAL_PHY       0x0400  /* chip has two transcivers */
+       int                     sc_unit;
+
+       struct sleepout         sc_sleepout;
+       struct sleepout_task    sc_watchdog;
+       struct task             sc_setmulti;
+       struct task             sc_setpromisc;
 };
 
+#define        AUE_SXLOCK(_sc)         sx_xlock(&(_sc)->sc_sx)
+#define        AUE_SXUNLOCK(_sc)       sx_xunlock(&(_sc)->sc_sx)
 #define        AUE_LOCK(_sc)           mtx_lock(&(_sc)->sc_mtx)
 #define        AUE_UNLOCK(_sc)         mtx_unlock(&(_sc)->sc_mtx)
 #define        AUE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
Index: usb_ethernet.h
===================================================================
--- usb_ethernet.h      (revision 214568)
+++ usb_ethernet.h      (working copy)
@@ -119,4 +119,7 @@ int         uether_rxbuf(struct usb_ether *,
                    unsigned int, unsigned int);
 void           uether_rxflush(struct usb_ether *);
 uint8_t                uether_is_gone(struct usb_ether *);
+int            uether_alloc_unr(void);
+void           uether_free_unr(int);
+
 #endif                                 /* _USB_ETHERNET_H_ */
_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to