Date: Thu, 9 Sep 2010 20:11:41 +0000 (UTC) From: Weongyo Jeong <weongyo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r212377 - user/weongyo/usb/sys/dev/usb/net Message-ID: <201009092011.o89KBfdV027242@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: weongyo Date: Thu Sep 9 20:11:41 2010 New Revision: 212377 URL: http://svn.freebsd.org/changeset/base/212377 Log: rue(4) don't depend on uether module anymore that it's not tested due to lack of H/W. Modified: user/weongyo/usb/sys/dev/usb/net/if_rue.c user/weongyo/usb/sys/dev/usb/net/if_ruereg.h Modified: user/weongyo/usb/sys/dev/usb/net/if_rue.c ============================================================================== --- user/weongyo/usb/sys/dev/usb/net/if_rue.c Thu Sep 9 20:07:40 2010 (r212376) +++ user/weongyo/usb/sys/dev/usb/net/if_rue.c Thu Sep 9 20:11:41 2010 (r212377) @@ -78,6 +78,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> @@ -85,6 +87,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> @@ -92,9 +107,8 @@ __FBSDID("$FreeBSD$"); #define USB_DEBUG_VAR rue_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_ruereg.h> #ifdef USB_DEBUG @@ -129,14 +143,6 @@ static usb_callback_t rue_intr_callback; static usb_callback_t rue_bulk_read_callback; static usb_callback_t rue_bulk_write_callback; -static uether_fn_t rue_attach_post; -static uether_fn_t rue_init; -static uether_fn_t rue_stop; -static uether_fn_t rue_start; -static uether_fn_t rue_tick; -static uether_fn_t rue_setmulti; -static uether_fn_t rue_setpromisc; - static int rue_read_mem(struct rue_softc *, uint16_t, void *, int); static int rue_write_mem(struct rue_softc *, uint16_t, void *, int); static uint8_t rue_csr_read_1(struct rue_softc *, uint16_t); @@ -144,10 +150,15 @@ static uint16_t rue_csr_read_2(struct ru static int rue_csr_write_1(struct rue_softc *, uint16_t, uint8_t); static int rue_csr_write_2(struct rue_softc *, uint16_t, uint16_t); static int rue_csr_write_4(struct rue_softc *, int, uint32_t); - static void rue_reset(struct rue_softc *); static int rue_ifmedia_upd(struct ifnet *); static void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *); +static void rue_init(void *); +static void rue_init_locked(struct rue_softc *); +static int rue_ioctl(struct ifnet *, u_long, caddr_t); +static void rue_start(struct ifnet *); +static void rue_stop(struct rue_softc *); +static void rue_watchdog(void *); static const struct usb_config rue_config[RUE_N_TRANSFER] = { @@ -209,24 +220,11 @@ static devclass_t rue_devclass; DRIVER_MODULE(rue, uhub, rue_driver, rue_devclass, NULL, 0); DRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, 0, 0); -MODULE_DEPEND(rue, uether, 1, 1, 1); MODULE_DEPEND(rue, usb, 1, 1, 1); MODULE_DEPEND(rue, ether, 1, 1, 1); MODULE_DEPEND(rue, miibus, 1, 1, 1); MODULE_VERSION(rue, 1); -static const struct usb_ether_methods rue_ue_methods = { - .ue_attach_post = rue_attach_post, - .ue_start = rue_start, - .ue_init = rue_init, - .ue_stop = rue_stop, - .ue_tick = rue_tick, - .ue_setmulti = rue_setmulti, - .ue_setpromisc = rue_setpromisc, - .ue_mii_upd = rue_ifmedia_upd, - .ue_mii_sts = rue_ifmedia_sts, -}; - #define RUE_SETBIT(sc, reg, x) \ rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x)) @@ -244,7 +242,8 @@ rue_read_mem(struct rue_softc *sc, uint1 USETW(req.wIndex, 0); USETW(req.wLength, len); - return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); + return (usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, buf, + 0, NULL, 1000)); } static int @@ -258,7 +257,8 @@ rue_write_mem(struct rue_softc *sc, uint USETW(req.wIndex, 0); USETW(req.wLength, len); - return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); + return (usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, &req, buf, + 0, NULL, 1000)); } static uint8_t @@ -343,7 +343,7 @@ rue_miibus_readreg(device_t dev, int phy rval = rue_csr_read_1(sc, reg); goto done; } - device_printf(sc->sc_ue.ue_dev, "bad phy register\n"); + device_printf(sc->sc_dev, "bad phy register\n"); rval = 0; goto done; } @@ -393,7 +393,7 @@ rue_miibus_writereg(device_t dev, int ph rue_csr_write_1(sc, reg, data); goto done; } - device_printf(sc->sc_ue.ue_dev, " bad phy register\n"); + device_printf(sc->sc_dev, " bad phy register\n"); goto done; } rue_csr_write_2(sc, ruereg, data); @@ -450,10 +450,9 @@ rue_miibus_statchg(device_t dev) } static void -rue_setpromisc(struct usb_ether *ue) +rue_setpromisc(struct rue_softc *sc) { - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; RUE_LOCK_ASSERT(sc, MA_OWNED); @@ -468,10 +467,10 @@ rue_setpromisc(struct usb_ether *ue) * Program the 64-bit multicast hash filter. */ static void -rue_setmulti(struct usb_ether *ue) +rue_setmulti(void *arg, int npending) { - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct rue_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; uint16_t rxcfg; int h = 0; uint32_t hashes[2] = { 0, 0 }; @@ -531,27 +530,25 @@ rue_reset(struct rue_softc *sc) rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST); for (i = 0; i != RUE_TIMEOUT; i++) { - if (uether_pause(&sc->sc_ue, hz / 1000)) - break; if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST)) break; + usb_pause_mtx(&sc->sc_mtx, hz / 1000); } if (i == RUE_TIMEOUT) - device_printf(sc->sc_ue.ue_dev, "reset never completed\n"); + device_printf(sc->sc_dev, "reset never completed\n"); - uether_pause(&sc->sc_ue, hz / 100); + usb_pause_mtx(&sc->sc_mtx, hz / 100); } static void -rue_attach_post(struct usb_ether *ue) +rue_attach_post(struct rue_softc *sc) { - struct rue_softc *sc = uether_getsc(ue); /* reset the adapter */ rue_reset(sc); /* get station address from the EEPROM */ - rue_read_mem(sc, RUE_EEPROM_IDR0, ue->ue_eaddr, ETHER_ADDR_LEN); + rue_read_mem(sc, RUE_EEPROM_IDR0, sc->sc_eaddr, ETHER_ADDR_LEN); } /* @@ -581,12 +578,17 @@ rue_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct rue_softc *sc = device_get_softc(dev); - struct usb_ether *ue = &sc->sc_ue; + struct ifnet *ifp; uint8_t iface_index; int error; device_set_usb_desc(dev); + sc->sc_dev = dev; + sc->sc_udev = uaa->device; mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + sleepout_create(&sc->sc_sleepout, "rue sleepout"); + sleepout_init_mtx(&sc->sc_sleepout, &sc->sc_watchdog, &sc->sc_mtx, 0); + TASK_INIT(&sc->sc_setmulti, 0, rue_setmulti, sc); iface_index = RUE_IFACE_IDX; error = usbd_transfer_setup(uaa->device, &iface_index, @@ -597,19 +599,39 @@ rue_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 = &rue_ue_methods; + RUE_LOCK(sc); + rue_attach_post(sc); + RUE_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, device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev)); + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = rue_ioctl; + ifp->if_start = rue_start; + ifp->if_init = rue_init; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; + IFQ_SET_READY(&ifp->if_snd); + + error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, + rue_ifmedia_upd, rue_ifmedia_sts); 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: rue_detach(dev); return (ENXIO); /* failure */ @@ -619,12 +641,22 @@ static int rue_detach(device_t dev) { struct rue_softc *sc = device_get_softc(dev); - struct usb_ether *ue = &sc->sc_ue; + struct ifnet *ifp = sc->sc_ifp; + sleepout_drain(&sc->sc_watchdog); + taskqueue_drain(sc->sc_sleepout.s_taskqueue, &sc->sc_setmulti); usbd_transfer_unsetup(sc->sc_xfer, RUE_N_TRANSFER); - uether_ifdetach(ue); + if (sc->sc_miibus != NULL) + device_delete_child(sc->sc_dev, sc->sc_miibus); + if (ifp != NULL) { + RUE_LOCK(sc); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + RUE_UNLOCK(sc); + ether_ifdetach(ifp); + if_free(ifp); + } + sleepout_free(&sc->sc_sleepout); mtx_destroy(&sc->sc_mtx); - return (0); } @@ -632,7 +664,7 @@ static void rue_intr_callback(struct usb_xfer *xfer, usb_error_t error) { struct rue_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = uether_getifp(&sc->sc_ue); + struct ifnet *ifp = sc->sc_ifp; struct rue_intrpkt pkt; struct usb_page_cache *pc; int actlen; @@ -670,11 +702,76 @@ tr_setup: } static void +rue_rxflush(struct rue_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + + RUE_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. + */ + RUE_UNLOCK(sc); + ifp->if_input(ifp, m); + RUE_LOCK(sc); + } +} + +static struct mbuf * +rue_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 +rue_rxbuf(struct rue_softc *sc, struct usb_page_cache *pc, + unsigned int offset, unsigned int len) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + + RUE_LOCK_ASSERT(sc, MA_OWNED); + + if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) + return (1); + + m = rue_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 rue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct rue_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 usb_page_cache *pc; uint16_t status; int actlen; @@ -698,13 +795,13 @@ rue_bulk_read_callback(struct usb_xfer * ifp->if_ierrors++; goto tr_setup; } - uether_rxbuf(ue, pc, 0, actlen); + rue_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); + rue_rxflush(sc); return; default: /* Error */ @@ -724,7 +821,7 @@ static void rue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct rue_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; int temp_len; @@ -794,9 +891,8 @@ tr_setup: } static void -rue_tick(struct usb_ether *ue) +rue_tick(struct rue_softc *sc) { - struct rue_softc *sc = uether_getsc(ue); struct mii_data *mii = GET_MII(sc); RUE_LOCK_ASSERT(sc, MA_OWNED); @@ -806,14 +902,14 @@ rue_tick(struct usb_ether *ue) && mii->mii_media_status & IFM_ACTIVE && IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->sc_flags |= RUE_FLAG_LINK; - rue_start(ue); + rue_start(sc->sc_ifp); } } static void -rue_start(struct usb_ether *ue) +rue_start(struct ifnet *ifp) { - struct rue_softc *sc = uether_getsc(ue); + struct rue_softc *sc = ifp->if_softc; /* * start the USB transfers, if not already started: @@ -824,10 +920,19 @@ rue_start(struct usb_ether *ue) } static void -rue_init(struct usb_ether *ue) +rue_init(void *arg) +{ + struct rue_softc *sc = arg; + + RUE_LOCK(sc); + rue_init_locked(sc); + RUE_UNLOCK(sc); +} + +static void +rue_init_locked(struct rue_softc *sc) { - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; RUE_LOCK_ASSERT(sc, MA_OWNED); @@ -839,7 +944,7 @@ rue_init(struct usb_ether *ue) /* Set MAC address */ rue_write_mem(sc, RUE_IDR0, IF_LLADDR(ifp), ETHER_ADDR_LEN); - rue_stop(ue); + rue_stop(sc); /* * Set the initial TX and RX configuration. @@ -848,9 +953,9 @@ rue_init(struct usb_ether *ue) rue_csr_write_2(sc, RUE_RCR, RUE_RCR_CONFIG|RUE_RCR_AB); /* Load the multicast filter */ - rue_setpromisc(ue); + rue_setpromisc(sc); /* Load the multicast filter. */ - rue_setmulti(ue); + rue_setmulti(sc, 0); /* Enable RX and TX */ rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN)); @@ -858,7 +963,8 @@ rue_init(struct usb_ether *ue) usbd_xfer_set_stall(sc->sc_xfer[RUE_BULK_DT_WR]); ifp->if_drv_flags |= IFF_DRV_RUNNING; - rue_start(ue); + sleepout_reset(&sc->sc_watchdog, hz, rue_watchdog, sc); + rue_start(sc->sc_ifp); } /* @@ -900,10 +1006,9 @@ rue_ifmedia_sts(struct ifnet *ifp, struc } static void -rue_stop(struct usb_ether *ue) +rue_stop(struct rue_softc *sc) { - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; RUE_LOCK_ASSERT(sc, MA_OWNED); @@ -921,3 +1026,54 @@ rue_stop(struct usb_ether *ue) rue_reset(sc); } + +static int +rue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct rue_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + struct mii_data *mii = GET_MII(sc); + int error = 0; + + switch (command) { + case SIOCSIFFLAGS: + RUE_LOCK(sc); + if (ifp->if_flags & IFF_UP) { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + rue_setpromisc(sc); + else + rue_init_locked(sc); + } else + rue_stop(sc); + RUE_UNLOCK(sc); + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + if (ifp->if_flags & IFF_UP && + ifp->if_drv_flags & IFF_DRV_RUNNING) + taskqueue_enqueue(sc->sc_sleepout.s_taskqueue, + &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 +rue_watchdog(void *arg) +{ + struct rue_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + + rue_tick(sc); + sleepout_reset(&sc->sc_watchdog, hz, rue_watchdog, sc); +} Modified: user/weongyo/usb/sys/dev/usb/net/if_ruereg.h ============================================================================== --- user/weongyo/usb/sys/dev/usb/net/if_ruereg.h Thu Sep 9 20:07:40 2010 (r212376) +++ user/weongyo/usb/sys/dev/usb/net/if_ruereg.h Thu Sep 9 20:11:41 2010 (r212377) @@ -144,7 +144,7 @@ #define RUE_RXSTAT_PMATCH (0x04 << 12) #define RUE_RXSTAT_MCAST (0x08 << 12) -#define GET_MII(sc) uether_getmii(&(sc)->sc_ue) +#define GET_MII(sc) (device_get_softc(sc->sc_miibus)) struct rue_intrpkt { uint8_t rue_tsr; @@ -170,10 +170,18 @@ enum { }; struct rue_softc { - struct usb_ether sc_ue; + struct ifnet *sc_ifp; + device_t sc_dev; + device_t sc_miibus; struct mtx sc_mtx; - struct usb_xfer *sc_xfer[RUE_N_TRANSFER]; - + struct usb_device *sc_udev; /* used by uether_do_request() */ + struct usb_xfer *sc_xfer[RUE_N_TRANSFER]; + struct sleepout sc_sleepout; + struct sleepout_task sc_watchdog; + struct task sc_setmulti; + struct ifqueue sc_rxq; + /* ethernet address from eeprom */ + uint8_t sc_eaddr[ETHER_ADDR_LEN]; int sc_flags; #define RUE_FLAG_LINK 0x0001 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009092011.o89KBfdV027242>