Date: Tue, 27 Jan 2009 01:32:13 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r187756 - user/thompsa/usb/sys/dev/usb2/wlan Message-ID: <200901270132.n0R1WDbu069663@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: thompsa Date: Tue Jan 27 01:32:13 2009 New Revision: 187756 URL: http://svn.freebsd.org/changeset/base/187756 Log: Convert over to the USB2 API. Modified: user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c user/thompsa/usb/sys/dev/usb2/wlan/if_rumvar.h user/thompsa/usb/sys/dev/usb2/wlan/if_ural2.c user/thompsa/usb/sys/dev/usb2/wlan/if_uralreg.h user/thompsa/usb/sys/dev/usb2/wlan/if_uralvar.h user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h Modified: user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c ============================================================================== --- user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c Tue Jan 27 01:31:52 2009 (r187755) +++ user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c Tue Jan 27 01:32:13 2009 (r187756) @@ -3,6 +3,7 @@ /*- * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr> * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> + * Copyright (c) 2007-2008 Hans Petter Selasky <hselasky@freebsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,129 +26,113 @@ __FBSDID("$FreeBSD$"); * http://www.ralinktech.com.tw/ */ -#include <sys/param.h> -#include <sys/sysctl.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/endian.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_phy.h> -#include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_regdomain.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/if_rumreg.h> -#include <dev/usb/if_rumvar.h> -#include <dev/usb/rt2573_ucode.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) do { if (rumdebug > 0) printf x; } while (0) -#define DPRINTFN(n, x) do { if (rumdebug >= (n)) printf x; } while (0) -int rumdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum"); -SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rumdebug, 0, - "rum debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) +#include <dev/usb2/include/usb2_devid.h> +#include <dev/usb2/include/usb2_standard.h> +#include <dev/usb2/include/usb2_mfunc.h> +#include <dev/usb2/include/usb2_error.h> + +#define USB_DEBUG_VAR rum_debug + +#include <dev/usb2/core/usb2_core.h> +#include <dev/usb2/core/usb2_lookup.h> +#include <dev/usb2/core/usb2_process.h> +#include <dev/usb2/core/usb2_debug.h> +#include <dev/usb2/core/usb2_request.h> +#include <dev/usb2/core/usb2_busdma.h> +#include <dev/usb2/core/usb2_util.h> + +#include <dev/usb2/wlan/usb2_wlan.h> +#include <dev/usb2/wlan/if_rumreg.h> +#include <dev/usb2/wlan/if_rumvar.h> +#include <dev/usb2/wlan/if_rumfw.h> + +#if USB_DEBUG +static int rum_debug = 0; + +SYSCTL_NODE(_hw_usb2, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum"); +SYSCTL_INT(_hw_usb2_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0, + "Debug level"); #endif -/* various supported device vendors/products */ -static const struct usb_devno rum_devs[] = { - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700 }, - { USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO }, - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1 }, - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3 }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR }, - { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2 }, - { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL }, - { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX }, - { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F }, - { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110 }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS }, - { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573 }, - { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573 }, - { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB }, - { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP }, - { USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4 }, - { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573 }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2 }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM }, - { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573 }, - { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671 }, - { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2 }, - { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172 }, - { USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573 }, - { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573 } +static const struct usb2_device_id rum_devs[] = { + { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM) }, + { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2) }, + { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3) }, + { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4) }, + { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700) }, + { USB_VP(USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO) }, + { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1) }, + { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2) }, + { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A) }, + { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3) }, + { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC) }, + { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR) }, + { USB_VP(USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2) }, + { USB_VP(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL) }, + { USB_VP(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX) }, + { USB_VP(USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F) }, + { USB_VP(USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573) }, + { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1) }, + { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340) }, + { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111) }, + { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110) }, + { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS) }, + { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS) }, + { USB_VP(USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573) }, + { USB_VP(USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573) }, + { USB_VP(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB) }, + { USB_VP(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP) }, + { USB_VP(USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G) }, + { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP) }, + { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP) }, + { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1) }, + { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2) }, + { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3) }, + { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4) }, + { USB_VP(USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573) }, + { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP) }, + { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2) }, + { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM) }, + { USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573) }, + { USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2) }, + { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573) }, + { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2) }, + { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671) }, + { USB_VP(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2) }, + { USB_VP(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172) }, + { USB_VP(USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573) }, + { USB_VP(USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573) }, }; MODULE_DEPEND(rum, wlan, 1, 1, 1); MODULE_DEPEND(rum, wlan_amrr, 1, 1, 1); -MODULE_DEPEND(rum, usb, 1, 1, 1); +MODULE_DEPEND(rum, usb2_wlan, 1, 1, 1); +MODULE_DEPEND(rum, usb2_core, 1, 1, 1); + +static device_probe_t rum_match; +static device_attach_t rum_attach; +static device_detach_t rum_detach; + +static usb2_callback_t rum_bulk_read_callback; +static usb2_callback_t rum_bulk_read_clear_stall_callback; +static usb2_callback_t rum_bulk_write_callback; +static usb2_callback_t rum_bulk_write_clear_stall_callback; + +static usb2_task_fn_t rum_task; +static usb2_task_fn_t rum_scantask; +static usb2_task_fn_t rum_promisctask; +static usb2_task_fn_t rum_amrr_task; static struct ieee80211vap *rum_vap_create(struct ieee80211com *, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]); static void rum_vap_delete(struct ieee80211vap *); +static void rum_tx_free(struct rum_tx_data *, int); static int rum_alloc_tx_list(struct rum_softc *); static void rum_free_tx_list(struct rum_softc *); -static int rum_alloc_rx_list(struct rum_softc *); -static void rum_free_rx_list(struct rum_softc *); -static void rum_task(void *); -static void rum_scantask(void *); static int rum_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static void rum_txeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void rum_rxeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); static void rum_setup_tx_desc(struct rum_softc *, struct rum_tx_desc *, uint32_t, uint16_t, int, int); @@ -159,7 +144,6 @@ static int rum_tx_raw(struct rum_softc static int rum_tx_data(struct rum_softc *, struct mbuf *, struct ieee80211_node *); static void rum_start(struct ifnet *); -static void rum_watchdog(void *); static int rum_ioctl(struct ifnet *, u_long, caddr_t); static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, int); @@ -184,7 +168,6 @@ static void rum_enable_tsf_sync(struct static void rum_update_slot(struct ifnet *); static void rum_set_bssid(struct rum_softc *, const uint8_t *); static void rum_set_macaddr(struct rum_softc *, const uint8_t *); -static void rum_update_promisc(struct rum_softc *); static const char *rum_get_rf(int); static void rum_read_eeprom(struct rum_softc *); static int rum_bbp_init(struct rum_softc *); @@ -207,8 +190,6 @@ static int rum_get_rssi(struct rum_soft static void rum_amrr_start(struct rum_softc *, struct ieee80211_node *); static void rum_amrr_timeout(void *); -static void rum_amrr_update(usbd_xfer_handle, usbd_private_handle, - usbd_status); static const struct { uint32_t reg; @@ -369,89 +350,110 @@ static const struct rfprog { { 165, 0x00b33, 0x012ad, 0x2e014, 0x30285 } }; +static const struct usb2_config rum_config[RUM_N_TRANSFER] = { + [RUM_BULK_DT_WR] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .mh.bufsize = (MCLBYTES + RT2573_TX_DESC_SIZE + 8), + .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, + .mh.callback = rum_bulk_write_callback, + .mh.timeout = 5000, /* ms */ + }, + + [RUM_BULK_DT_RD] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .mh.bufsize = (MCLBYTES + RT2573_RX_DESC_SIZE), + .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .mh.callback = rum_bulk_read_callback, + }, + + [RUM_BULK_CS_WR] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.callback = rum_bulk_write_clear_stall_callback, + .mh.timeout = 1000, /* 1 second */ + .mh.interval = 50, /* 50ms */ + }, + + [RUM_BULK_CS_RD] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.callback = rum_bulk_read_clear_stall_callback, + .mh.timeout = 1000, /* 1 second */ + .mh.interval = 50, /* 50ms */ + }, +}; + static int rum_match(device_t self) { - struct usb_attach_arg *uaa = device_get_ivars(self); + struct usb2_attach_arg *uaa = device_get_ivars(self); - if (uaa->iface != NULL) - return UMATCH_NONE; + if (uaa->usb2_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != 0) + return (ENXIO); + if (uaa->info.bIfaceIndex != RT2573_IFACE_INDEX) + return (ENXIO); - return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; + return (usb2_lookup_id_by_uaa(rum_devs, sizeof(rum_devs), uaa)); } static int rum_attach(device_t self) { + struct usb2_attach_arg *uaa = device_get_ivars(self); struct rum_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); struct ieee80211com *ic; struct ifnet *ifp; const uint8_t *ucode = NULL; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i, ntries, size; - uint8_t bands; + uint8_t bands, iface_index; uint32_t tmp; + int error, ntries, size; + if (sc == NULL) + return (ENOMEM); + + device_set_usb2_desc(self); sc->sc_udev = uaa->device; sc->sc_dev = self; - if (usbd_set_config_no(sc->sc_udev, RT2573_CONFIG_NO, 0) != 0) { - device_printf(self, "could not set configuration no\n"); - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, RT2573_IFACE_INDEX, - &sc->sc_iface); - if (error != 0) { - device_printf(self, "could not get interface handle\n"); - return ENXIO; - } - - /* - * Find endpoints. - */ - id = usbd_get_interface_descriptor(sc->sc_iface); - - sc->sc_rx_no = sc->sc_tx_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - device_printf(self, - "no endpoint descriptor for iface %d\n", i); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_rx_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_tx_no = ed->bEndpointAddress; - } - if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { - device_printf(self, "missing endpoint\n"); - return ENXIO; + mtx_init(&sc->sc_mtx, device_get_nameunit(self), + MTX_NETWORK_LOCK, MTX_DEF); + USB_TASK_INIT(&sc->sc_task, rum_task, sc, NULL); + USB_TASK_INIT(&sc->sc_promisctask, rum_promisctask, sc, &sc->sc_mtx); + USB_TASK_INIT(&sc->sc_scantask, rum_scantask, sc, &sc->sc_mtx); + + iface_index = RT2573_IFACE_INDEX; + error = usb2_transfer_setup(uaa->device, &iface_index, + sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx); + if (error) { + device_printf(self, "could not allocate USB transfers, " + "err=%s\n", usb2_errstr(error)); + goto detach; + } + error = usb2_proc_create(&sc->sc_tq, USB_PRI_MED, + device_get_nameunit(self)); + if (error) { + device_printf(self, "could not setup config thread!\n"); + goto detach; } ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { - device_printf(self, "can not if_alloc()\n"); - return ENXIO; + device_printf(sc->sc_dev, "can not if_alloc()\n"); + goto detach; } ic = ifp->if_l2com; - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - - usb_init_task(&sc->sc_task, rum_task, sc); - usb_init_task(&sc->sc_scantask, rum_scantask, sc); - callout_init(&sc->watchdog_ch, 0); - + RUM_LOCK(sc); /* retrieve RT2573 rev. no */ for (ntries = 0; ntries < 1000; ntries++) { if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0) @@ -460,7 +462,8 @@ rum_attach(device_t self) } if (ntries == 1000) { device_printf(self, "timeout waiting for chip to settle\n"); - goto bad; + RUM_UNLOCK(sc); + goto detach; } /* retrieve MAC address and various other things from EEPROM */ @@ -474,13 +477,14 @@ rum_attach(device_t self) error = rum_load_microcode(sc, ucode, size); if (error != 0) { device_printf(self, "could not load 8051 microcode\n"); - goto bad; + RUM_UNLOCK(sc); + goto detach; } + RUM_UNLOCK(sc); ifp->if_softc = sc; if_initname(ifp, "rum", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = rum_init; ifp->if_ioctl = rum_ioctl; ifp->if_start = rum_start; @@ -539,10 +543,9 @@ rum_attach(device_t self) ieee80211_announce(ic); return 0; -bad: - mtx_destroy(&sc->sc_mtx); - if_free(ifp); - return ENXIO; +detach: + rum_detach(self); + return (ENXIO); /* failure */ } static int @@ -552,35 +555,23 @@ rum_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + RUM_LOCK(sc); + sc->sc_flags |= RUM_FLAG_DETACH; rum_stop(sc); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - callout_stop(&sc->watchdog_ch); - - if (sc->amrr_xfer != NULL) { - usbd_free_xfer(sc->amrr_xfer); - sc->amrr_xfer = NULL; - } + RUM_UNLOCK(sc); - if (sc->sc_rx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_rx_pipeh); - usbd_close_pipe(sc->sc_rx_pipeh); - } - if (sc->sc_tx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_tx_pipeh); - usbd_close_pipe(sc->sc_tx_pipeh); + /* stop all USB transfers first */ + usb2_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER); + usb2_proc_free(&sc->sc_tq); + + if (ifp) { + bpfdetach(ifp); + ieee80211_ifdetach(ic); + if_free(ifp); } - - rum_free_rx_list(sc); - rum_free_tx_list(sc); - - if_free(ifp); mtx_destroy(&sc->sc_mtx); - return 0; + return (0); } static struct ieee80211vap * @@ -589,6 +580,7 @@ rum_vap_create(struct ieee80211com *ic, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { + struct rum_softc *sc = ic->ic_ifp->if_softc; struct rum_vap *rvp; struct ieee80211vap *vap; @@ -607,7 +599,9 @@ rum_vap_create(struct ieee80211com *ic, rvp->newstate = vap->iv_newstate; vap->iv_newstate = rum_newstate; - callout_init(&rvp->amrr_ch, 0); + rvp->sc = sc; + usb2_callout_init_mtx(&rvp->amrr_ch, &sc->sc_mtx, 0); + USB_TASK_INIT(&rvp->amrr_task, rum_amrr_task, rvp, &sc->sc_mtx); ieee80211_amrr_init(&rvp->amrr, vap, IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, @@ -623,49 +617,58 @@ static void rum_vap_delete(struct ieee80211vap *vap) { struct rum_vap *rvp = RUM_VAP(vap); + struct rum_softc *sc = rvp->sc; - callout_stop(&rvp->amrr_ch); + RUM_LOCK(sc); + usb2_callout_stop(&rvp->amrr_ch); + RUM_UNLOCK(sc); ieee80211_amrr_cleanup(&rvp->amrr); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } +static void +rum_tx_free(struct rum_tx_data *data, int txerr) +{ + struct rum_softc *sc = data->sc; + + if (data->m != NULL) { + if (data->m->m_flags & M_TXCB) + ieee80211_process_callback(data->ni, data->m, + txerr ? ETIMEDOUT : 0); + m_freem(data->m); + data->m = NULL; + + ieee80211_free_node(data->ni); + data->ni = NULL; + } + STAILQ_INSERT_TAIL(&sc->tx_free, data, next); + sc->tx_nfree++; +} + static int rum_alloc_tx_list(struct rum_softc *sc) { struct rum_tx_data *data; - int i, error; + int i; - sc->tx_queued = sc->tx_cur = 0; + sc->tx_data = malloc(sizeof(struct rum_tx_data) * RUM_TX_LIST_COUNT, + M_USB, M_NOWAIT|M_ZERO); + if (sc->tx_data == NULL) + return (ENOMEM); + + sc->tx_nfree = 0; + STAILQ_INIT(&sc->tx_q); + STAILQ_INIT(&sc->tx_free); for (i = 0; i < RUM_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx xfer\n"); - error = ENOMEM; - goto fail; - } - data->buf = usbd_alloc_buffer(data->xfer, - RT2573_TX_DESC_SIZE + MCLBYTES); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx buffer\n"); - error = ENOMEM; - goto fail; - } - /* clean Tx descriptor */ - bzero(data->buf, RT2573_TX_DESC_SIZE); + STAILQ_INSERT_TAIL(&sc->tx_free, data, next); + sc->tx_nfree++; } - return 0; - -fail: rum_free_tx_list(sc); - return error; } static void @@ -674,85 +677,27 @@ rum_free_tx_list(struct rum_softc *sc) struct rum_tx_data *data; int i; + if (sc->tx_data == NULL) + return; + for (i = 0; i < RUM_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; + if (data->m != NULL) { + m_freem(data->m); + data->m = NULL; } - if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; } } -} - -static int -rum_alloc_rx_list(struct rum_softc *sc) -{ - struct rum_rx_data *data; - int i, error; - - for (i = 0; i < RUM_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx xfer\n"); - error = ENOMEM; - goto fail; - } - if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx buffer\n"); - error = ENOMEM; - goto fail; - } - - data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (data->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - - data->buf = mtod(data->m, uint8_t *); - } - - return 0; - -fail: rum_free_rx_list(sc); - return error; + free(sc->tx_data, M_USB); + sc->tx_data = NULL; } static void -rum_free_rx_list(struct rum_softc *sc) -{ - struct rum_rx_data *data; - int i; - - for (i = 0; i < RUM_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - if (data->m != NULL) { - m_freem(data->m); - data->m = NULL; - } - } -} - -static void -rum_task(void *arg) +rum_task(void *arg, struct usb2_task *task) { struct rum_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; @@ -764,10 +709,12 @@ rum_task(void *arg) struct ieee80211_node *ni; uint32_t tmp; + if (sc->sc_flags & RUM_FLAG_DETACH) + return; + ostate = vap->iv_state; RUM_LOCK(sc); - switch (sc->sc_state) { case IEEE80211_S_INIT: if (ostate == IEEE80211_S_RUN) { @@ -803,7 +750,6 @@ rum_task(void *arg) default: break; } - RUM_UNLOCK(sc); IEEE80211_LOCK(ic); @@ -820,152 +766,264 @@ rum_newstate(struct ieee80211vap *vap, e struct ieee80211com *ic = vap->iv_ic; struct rum_softc *sc = ic->ic_ifp->if_softc; - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - callout_stop(&rvp->amrr_ch); + DPRINTF("%s -> %s\n", + ieee80211_state_name[vap->iv_state], + ieee80211_state_name[nstate]); + + RUM_LOCK(sc); + usb2_callout_stop(&rvp->amrr_ch); /* do it in a process context */ sc->sc_state = nstate; sc->sc_arg = arg; + RUM_UNLOCK(sc); if (nstate == IEEE80211_S_INIT) { rvp->newstate(vap, nstate, arg); return 0; } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); + usb2_proc_enqueue(&sc->sc_tq, &sc->sc_task); return EINPROGRESS; } } static void -rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) +rum_bulk_write_callback(struct usb2_xfer *xfer) { - struct rum_tx_data *data = priv; - struct rum_softc *sc = data->sc; + struct rum_softc *sc = xfer->priv_sc; struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211_channel *c = ic->ic_curchan; + struct rum_tx_data *data; + struct mbuf *m; + int len; - if (data->m != NULL && data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, 0/*XXX*/); + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen); + + /* free resources */ + data = xfer->priv_fifo; + rum_tx_free(data, 0); + xfer->priv_fifo = NULL; + + ifp->if_opackets++; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + + /* FALLTHROUGH */ + case USB_ST_SETUP: + if (sc->sc_flags & RUM_FLAG_WRITE_STALL) { + usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_WR]); + break; + } +#if 0 + if (sc->sc_flags & RUM_FLAG_WAIT_COMMAND) { + /* + * don't send anything while a command is pending ! + */ + break; + } +#endif - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; + data = STAILQ_FIRST(&sc->tx_q); + if (data) { + STAILQ_REMOVE_HEAD(&sc->tx_q, next); + m = data->m; + + if (m->m_pkthdr.len > (MCLBYTES + RT2573_TX_DESC_SIZE)) { + DPRINTFN(0, "data overflow, %u bytes\n", + m->m_pkthdr.len); + m->m_pkthdr.len = (MCLBYTES + RT2573_TX_DESC_SIZE); + } + usb2_copy_in(xfer->frbuffers, 0, &data->desc, + RT2573_TX_DESC_SIZE); + usb2_m_copy_in(xfer->frbuffers, RT2573_TX_DESC_SIZE, m, + 0, m->m_pkthdr.len); + + if (bpf_peers_present(ifp->if_bpf)) { + struct rum_tx_radiotap_header *tap = &sc->sc_txtap; + + tap->wt_flags = 0; + tap->wt_rate = data->rate; + tap->wt_chan_freq = htole16(c->ic_freq); + tap->wt_chan_flags = htole16(c->ic_flags); + tap->wt_antenna = sc->tx_ant; - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); + } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh); + /* align end on a 4-bytes boundary */ + len = (RT2573_TX_DESC_SIZE + m->m_pkthdr.len + 3) & ~3; + if ((len % 64) == 0) + len += 4; - ifp->if_oerrors++; - return; - } + DPRINTFN(11, "sending frame len=%u xferlen=%u\n", + m->m_pkthdr.len, len); - m_freem(data->m); - data->m = NULL; - ieee80211_free_node(data->ni); - data->ni = NULL; + xfer->frlengths[0] = len; + xfer->priv_fifo = data; - sc->tx_queued--; - ifp->if_opackets++; + usb2_start_hardware(xfer); + } + break; + + default: /* Error */ + DPRINTFN(11, "transfer error, %s\n", + usb2_errstr(xfer->error)); + + if (xfer->error == USB_ERR_STALLED) { + /* try to clear stall first */ + sc->sc_flags |= RUM_FLAG_WRITE_STALL; + usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_WR]); + return; + } + if (xfer->error == USB_ERR_TIMEOUT) + device_printf(sc->sc_dev, "device timeout\n"); - DPRINTFN(10, ("tx done\n")); + ifp->if_oerrors++; + data = xfer->priv_fifo; + if (data != NULL) { + rum_tx_free(data, xfer->error); + xfer->priv_fifo = NULL; + } + break; + } +} - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rum_start(ifp); +static void +rum_bulk_write_clear_stall_callback(struct usb2_xfer *xfer) +{ + struct rum_softc *sc = xfer->priv_sc; + struct usb2_xfer *xfer_other = sc->sc_xfer[RUM_BULK_DT_WR]; + + if (usb2_clear_stall_callback(xfer, xfer_other)) { + DPRINTF("stall cleared\n"); + sc->sc_flags &= ~RUM_FLAG_WRITE_STALL; + usb2_transfer_start(xfer_other); + } } static void -rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) +rum_bulk_read_callback(struct usb2_xfer *xfer) { - struct rum_rx_data *data = priv; - struct rum_softc *sc = data->sc; + struct rum_softc *sc = xfer->priv_sc; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - struct rum_rx_desc *desc; struct ieee80211_node *ni; - struct mbuf *mnew, *m; - int len, rssi; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; + struct mbuf *m = NULL; + uint32_t flags; + uint8_t rssi = 0; + int len; - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - goto skip; - } + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: - usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); + DPRINTFN(15, "rx done, actlen=%d\n", xfer->actlen); - if (len < RT2573_RX_DESC_SIZE + sizeof (struct ieee80211_frame_min)) { - DPRINTF(("%s: xfer too short %d\n", - device_get_nameunit(sc->sc_dev), len)); - ifp->if_ierrors++; - goto skip; - } + len = xfer->actlen; + if (len < RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN) { + DPRINTF("%s: xfer too short %d\n", + device_get_nameunit(sc->sc_dev), len); + ifp->if_ierrors++; + goto tr_setup; + } + + len -= RT2573_RX_DESC_SIZE; + usb2_copy_out(xfer->frbuffers, 0, &sc->sc_rx_desc, + RT2573_RX_DESC_SIZE); + + rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi); + flags = le32toh(sc->sc_rx_desc.flags); + if (flags & RT2573_RX_CRC_ERROR) { + /* + * This should not happen since we did not + * request to receive those frames when we + * filled RUM_TXRX_CSR2: + */ + DPRINTFN(5, "PHY or CRC error\n"); + ifp->if_ierrors++; + goto tr_setup; + } - desc = (struct rum_rx_desc *)data->buf; + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + DPRINTF("could not allocate mbuf\n"); + ifp->if_ierrors++; + goto tr_setup; + } + usb2_copy_out(xfer->frbuffers, RT2573_RX_DESC_SIZE, + mtod(m, uint8_t *), len); + + /* finalize mbuf */ + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; + + if (bpf_peers_present(ifp->if_bpf)) { + struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; + + tap->wr_flags = IEEE80211_RADIOTAP_F_FCS; + tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate, + (flags & RT2573_RX_OFDM) ? + IEEE80211_T_OFDM : IEEE80211_T_CCK); + tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); + tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + tap->wr_antenna = sc->rx_ant; + tap->wr_antsignal = rssi; + + bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); + } + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + if (sc->sc_flags & RUM_FLAG_READ_STALL) { + usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_RD]); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901270132.n0R1WDbu069663>