From owner-svn-src-user@FreeBSD.ORG Thu Sep 9 19:51:54 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4165510657CB; Thu, 9 Sep 2010 19:51:54 +0000 (UTC) (envelope-from weongyo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8B93F8FC20; Thu, 9 Sep 2010 19:51:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o89Jpkgr024732; Thu, 9 Sep 2010 19:51:46 GMT (envelope-from weongyo@svn.freebsd.org) Received: (from weongyo@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o89Jpk6g024728; Thu, 9 Sep 2010 19:51:46 GMT (envelope-from weongyo@svn.freebsd.org) Message-Id: <201009091951.o89Jpk6g024728@svn.freebsd.org> From: Weongyo Jeong Date: Thu, 9 Sep 2010 19:51:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212375 - user/weongyo/usb/sys/dev/usb/net X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Sep 2010 19:51:54 -0000 Author: weongyo Date: Thu Sep 9 19:51:46 2010 New Revision: 212375 URL: http://svn.freebsd.org/changeset/base/212375 Log: kue(4) don't depend on uther module anymore that it's not tested due to lack of H/W. Modified: user/weongyo/usb/sys/dev/usb/net/if_kue.c user/weongyo/usb/sys/dev/usb/net/if_kuereg.h Modified: user/weongyo/usb/sys/dev/usb/net/if_kue.c ============================================================================== --- user/weongyo/usb/sys/dev/usb/net/if_kue.c Thu Sep 9 19:27:40 2010 (r212374) +++ user/weongyo/usb/sys/dev/usb/net/if_kue.c Thu Sep 9 19:51:46 2010 (r212375) @@ -78,6 +78,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -85,6 +87,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -92,9 +102,8 @@ __FBSDID("$FreeBSD$"); #define USB_DEBUG_VAR kue_debug #include -#include +#include -#include #include #include @@ -148,13 +157,6 @@ static device_detach_t kue_detach; static usb_callback_t kue_bulk_read_callback; static usb_callback_t kue_bulk_write_callback; -static uether_fn_t kue_attach_post; -static uether_fn_t kue_init; -static uether_fn_t kue_stop; -static uether_fn_t kue_start; -static uether_fn_t kue_setmulti; -static uether_fn_t kue_setpromisc; - static int kue_do_request(struct kue_softc *, struct usb_device_request *, void *); static int kue_setword(struct kue_softc *, uint8_t, uint16_t); @@ -162,6 +164,10 @@ static int kue_ctl(struct kue_softc *, u void *, int); static int kue_load_fw(struct kue_softc *); static void kue_reset(struct kue_softc *); +static void kue_init(void *); +static void kue_init_locked(struct kue_softc *); +static int kue_ioctl(struct ifnet *, u_long, caddr_t); +static void kue_start(struct ifnet *); #ifdef USB_DEBUG static int kue_debug = 0; @@ -212,20 +218,10 @@ static driver_t kue_driver = { static devclass_t kue_devclass; DRIVER_MODULE(kue, uhub, kue_driver, kue_devclass, NULL, 0); -MODULE_DEPEND(kue, uether, 1, 1, 1); MODULE_DEPEND(kue, usb, 1, 1, 1); MODULE_DEPEND(kue, ether, 1, 1, 1); MODULE_VERSION(kue, 1); -static const struct usb_ether_methods kue_ue_methods = { - .ue_attach_post = kue_attach_post, - .ue_start = kue_start, - .ue_init = kue_init, - .ue_stop = kue_stop, - .ue_setmulti = kue_setmulti, - .ue_setpromisc = kue_setpromisc, -}; - /* * We have a custom do_request function which is almost like the * regular do_request function, except it has a much longer timeout. @@ -239,7 +235,8 @@ kue_do_request(struct kue_softc *sc, str { usb_error_t err; - err = uether_do_request(&sc->sc_ue, req, data, 60000); + err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, req, data, 0, + NULL, 60000); return (err); } @@ -269,7 +266,6 @@ kue_ctl(struct kue_softc *sc, uint8_t rw else req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = breq; USETW(req.wValue, val); USETW(req.wIndex, 0); @@ -285,7 +281,7 @@ kue_load_fw(struct kue_softc *sc) uint16_t hwrev; usb_error_t err; - dd = usbd_get_device_descriptor(sc->sc_ue.ue_udev); + dd = usbd_get_device_descriptor(sc->sc_udev); hwrev = UGETW(dd->bcdDevice); /* @@ -309,7 +305,7 @@ kue_load_fw(struct kue_softc *sc) err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, kue_code_seg, sizeof(kue_code_seg)); if (err) { - device_printf(sc->sc_ue.ue_dev, "failed to load code segment: %s\n", + device_printf(sc->sc_dev, "failed to load code segment: %s\n", usbd_errstr(err)); return(ENXIO); } @@ -318,7 +314,7 @@ kue_load_fw(struct kue_softc *sc) err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, kue_fix_seg, sizeof(kue_fix_seg)); if (err) { - device_printf(sc->sc_ue.ue_dev, "failed to load fixup segment: %s\n", + device_printf(sc->sc_dev, "failed to load fixup segment: %s\n", usbd_errstr(err)); return(ENXIO); } @@ -327,8 +323,8 @@ kue_load_fw(struct kue_softc *sc) err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, kue_trig_seg, sizeof(kue_trig_seg)); if (err) { - device_printf(sc->sc_ue.ue_dev, "failed to load trigger segment: %s\n", - usbd_errstr(err)); + device_printf(sc->sc_dev, + "failed to load trigger segment: %s\n", usbd_errstr(err)); return(ENXIO); } @@ -336,10 +332,9 @@ kue_load_fw(struct kue_softc *sc) } static void -kue_setpromisc(struct usb_ether *ue) +kue_setpromisc(struct kue_softc *sc) { - struct kue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; KUE_LOCK_ASSERT(sc, MA_OWNED); @@ -352,10 +347,10 @@ kue_setpromisc(struct usb_ether *ue) } static void -kue_setmulti(struct usb_ether *ue) +kue_setmulti(void *arg, int npending) { - struct kue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct kue_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; struct ifmultiaddr *ifma; int i = 0; @@ -409,27 +404,26 @@ kue_reset(struct kue_softc *sc) struct usb_config_descriptor *cd; usb_error_t err; - cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev); + cd = usbd_get_config_descriptor(sc->sc_udev); - err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx, + err = usbd_req_set_config(sc->sc_udev, &sc->sc_mtx, cd->bConfigurationValue); if (err) DPRINTF("reset failed (ignored)\n"); /* wait a little while for the chip to get its brains in order */ - uether_pause(&sc->sc_ue, hz / 100); + usb_pause_mtx(&sc->sc_mtx, hz / 100); } static void -kue_attach_post(struct usb_ether *ue) +kue_attach_post(struct kue_softc *sc) { - struct kue_softc *sc = uether_getsc(ue); int error; /* load the firmware into the NIC */ error = kue_load_fw(sc); if (error) { - device_printf(sc->sc_ue.ue_dev, "could not load firmware\n"); + device_printf(sc->sc_dev, "could not load firmware\n"); /* ignore the error */ } @@ -441,7 +435,7 @@ kue_attach_post(struct usb_ether *ue) 0, &sc->sc_desc, sizeof(sc->sc_desc)); /* copy in ethernet address */ - memcpy(ue->ue_eaddr, sc->sc_desc.kue_macaddr, sizeof(ue->ue_eaddr)); + memcpy(sc->sc_eaddr, sc->sc_desc.kue_macaddr, sizeof(sc->sc_eaddr)); } /* @@ -471,12 +465,16 @@ kue_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct kue_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, "kue sleepout"); + TASK_INIT(&sc->sc_setmulti, 0, kue_setmulti, sc); iface_index = KUE_IFACE_IDX; error = usbd_transfer_setup(uaa->device, &iface_index, @@ -493,19 +491,32 @@ kue_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 = &kue_ue_methods; - - error = uether_ifattach(ue); - if (error) { - device_printf(dev, "could not attach interface\n"); + KUE_LOCK(sc); + kue_attach_post(sc); + KUE_UNLOCK(sc); + + sc->sc_ifp = ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) { + device_printf(sc->sc_dev, "could not allocate ifnet\n"); goto detach; } - return (0); /* success */ + 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 = kue_ioctl; + ifp->if_start = kue_start; + ifp->if_init = kue_init; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; + IFQ_SET_READY(&ifp->if_snd); + + if_printf(ifp, " on %s\n", + device_get_nameunit(sc->sc_dev)); + ether_ifattach(ifp, sc->sc_eaddr); + return (0); detach: kue_detach(dev); return (ENXIO); /* failure */ @@ -515,16 +526,90 @@ static int kue_detach(device_t dev) { struct kue_softc *sc = device_get_softc(dev); - struct usb_ether *ue = &sc->sc_ue; + struct ifnet *ifp = sc->sc_ifp; + taskqueue_drain(sc->sc_sleepout.s_taskqueue, &sc->sc_setmulti); usbd_transfer_unsetup(sc->sc_xfer, KUE_N_TRANSFER); - uether_ifdetach(ue); + if (ifp != NULL) { + KUE_LOCK(sc); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + KUE_UNLOCK(sc); + ether_ifdetach(ifp); + if_free(ifp); + } + sleepout_free(&sc->sc_sleepout); mtx_destroy(&sc->sc_mtx); free(sc->sc_mcfilters, M_USBDEV); return (0); } +static void +kue_rxflush(struct kue_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + + KUE_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. + */ + KUE_UNLOCK(sc); + ifp->if_input(ifp, m); + KUE_LOCK(sc); + } +} + +static struct mbuf * +kue_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 +kue_rxbuf(struct kue_softc *sc, struct usb_page_cache *pc, + unsigned int offset, unsigned int len) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + + KUE_LOCK_ASSERT(sc, MA_OWNED); + + if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) + return (1); + + m = kue_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); +} + /* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. @@ -533,8 +618,7 @@ static void kue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct kue_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; uint8_t buf[2]; int len; @@ -555,13 +639,13 @@ kue_bulk_read_callback(struct usb_xfer * len = buf[0] | (buf[1] << 8); len = min(actlen, len); - uether_rxbuf(ue, pc, 2, len); + kue_rxbuf(sc, pc, 2, len); /* 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); + kue_rxflush(sc); return; default: /* Error */ @@ -582,7 +666,7 @@ static void kue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct kue_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 total_len; @@ -647,9 +731,9 @@ tr_setup: } static void -kue_start(struct usb_ether *ue) +kue_start(struct ifnet *ifp) { - struct kue_softc *sc = uether_getsc(ue); + struct kue_softc *sc = ifp->if_softc; /* * start the USB transfers, if not already started: @@ -659,10 +743,19 @@ kue_start(struct usb_ether *ue) } static void -kue_init(struct usb_ether *ue) +kue_init(void *arg) +{ + struct kue_softc *sc = arg; + + KUE_LOCK(sc); + kue_init_locked(sc); + KUE_UNLOCK(sc); +} + +static void +kue_init_locked(struct kue_softc *sc) { - struct kue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; KUE_LOCK_ASSERT(sc, MA_OWNED); @@ -681,19 +774,18 @@ kue_init(struct usb_ether *ue) kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64); /* load the multicast filter */ - kue_setpromisc(ue); + kue_setpromisc(sc); usbd_xfer_set_stall(sc->sc_xfer[KUE_BULK_DT_WR]); ifp->if_drv_flags |= IFF_DRV_RUNNING; - kue_start(ue); + kue_start(sc->sc_ifp); } static void -kue_stop(struct usb_ether *ue) +kue_stop(struct kue_softc *sc) { - struct kue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); + struct ifnet *ifp = sc->sc_ifp; KUE_LOCK_ASSERT(sc, MA_OWNED); @@ -705,3 +797,33 @@ kue_stop(struct usb_ether *ue) usbd_transfer_stop(sc->sc_xfer[KUE_BULK_DT_WR]); usbd_transfer_stop(sc->sc_xfer[KUE_BULK_DT_RD]); } + +static int +kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct kue_softc *sc = ifp->if_softc; + int error = 0; + + switch (command) { + case SIOCSIFFLAGS: + KUE_LOCK(sc); + if (ifp->if_flags & IFF_UP) { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + kue_init_locked(sc); + } else + kue_stop(sc); + KUE_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; + default: + error = ether_ioctl(ifp, command, data); + break; + } + return (error); +} Modified: user/weongyo/usb/sys/dev/usb/net/if_kuereg.h ============================================================================== --- user/weongyo/usb/sys/dev/usb/net/if_kuereg.h Thu Sep 9 19:27:40 2010 (r212374) +++ user/weongyo/usb/sys/dev/usb/net/if_kuereg.h Thu Sep 9 19:51:46 2010 (r212375) @@ -124,15 +124,21 @@ enum { }; struct kue_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[KUE_N_TRANSFER]; struct mtx sc_mtx; + struct sleepout sc_sleepout; + struct task sc_setmulti; + struct ifqueue sc_rxq; + /* ethernet address from eeprom */ + uint8_t sc_eaddr[ETHER_ADDR_LEN]; struct kue_ether_desc sc_desc; - struct usb_xfer *sc_xfer[KUE_N_TRANSFER]; uint8_t *sc_mcfilters; - int sc_flags; #define KUE_FLAG_LINK 0x0001 - uint16_t sc_rxfilt; };