diff options
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/controller/xhci.c | 85 | ||||
-rw-r--r-- | sys/dev/usb/controller/xhci_pci.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/controller/xhcireg.h | 5 | ||||
-rw-r--r-- | sys/dev/usb/net/if_umb.c | 4 | ||||
-rw-r--r-- | sys/dev/usb/serial/udbc.c | 404 | ||||
-rw-r--r-- | sys/dev/usb/usb_hub.c | 3 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_rsu.c | 66 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_rsureg.h | 9 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_run.c | 14 |
9 files changed, 567 insertions, 25 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 5be592512196..788b2b718062 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -156,6 +156,7 @@ struct xhci_std_temp { static void xhci_do_poll(struct usb_bus *); static void xhci_device_done(struct usb_xfer *, usb_error_t); +static void xhci_get_xecp(struct xhci_softc *); static void xhci_root_intr(struct xhci_softc *); static void xhci_free_device_ext(struct usb_device *); static struct xhci_endpoint_ext *xhci_get_endpoint_ext(struct usb_device *, @@ -566,6 +567,8 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) device_printf(self, "%d bytes context size, %d-bit DMA\n", sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits); + xhci_get_xecp(sc); + /* enable 64Kbyte control endpoint quirk */ sc->sc_bus.control_ep_quirk = (xhcictlquirk ? 1 : 0); @@ -654,6 +657,88 @@ xhci_uninit(struct xhci_softc *sc) } static void +xhci_get_xecp(struct xhci_softc *sc) +{ + + uint32_t hccp1; + uint32_t eec; + uint32_t eecp; + bool first = true; + + hccp1 = XREAD4(sc, capa, XHCI_HCSPARAMS0); + + if (XHCI_HCS0_XECP(hccp1) == 0) { + device_printf(sc->sc_bus.parent, + "xECP: no capabilities found\n"); + return; + } + + /* + * Parse the xECP Capabilities table and print known caps. + * Implemented, vendor and reserved xECP Capabilities values are + * documented in Table 7.2 of eXtensible Host Controller Interface for + * Universal Serial Bus (xHCI) Rev 1.2b 2023. + */ + device_printf(sc->sc_bus.parent, "xECP capabilities <"); + + eec = -1; + for (eecp = XHCI_HCS0_XECP(hccp1) << 2; + eecp != 0 && XHCI_XECP_NEXT(eec) != 0; + eecp += XHCI_XECP_NEXT(eec) << 2) { + eec = XREAD4(sc, capa, eecp); + + uint8_t xecpid = XHCI_XECP_ID(eec); + + if ((xecpid >= 11 && xecpid <= 16) || + (xecpid >= 19 && xecpid <= 191)) { + if (!first) + printf(","); + printf("RES(%x)", xecpid); + } else if (xecpid > 191) { + if (!first) + printf(","); + printf("VEND(%x)", xecpid); + } else { + if (!first) + printf(","); + switch (xecpid) + { + case XHCI_ID_USB_LEGACY: + printf("LEGACY"); + break; + case XHCI_ID_PROTOCOLS: + printf("PROTO"); + break; + case XHCI_ID_POWER_MGMT: + printf("POWER"); + break; + case XHCI_ID_VIRTUALIZATION: + printf("VIRT"); + break; + case XHCI_ID_MSG_IRQ: + printf("MSG IRQ"); + break; + case XHCI_ID_USB_LOCAL_MEM: + printf("LOCAL MEM"); + break; + case XHCI_ID_USB_DEBUG: + printf("DEBUG"); + break; + case XHCI_ID_EXT_MSI: + printf("EXT MSI"); + break; + case XHCI_ID_USB3_TUN: + printf("TUN"); + break; + + } + } + first = false; + } + printf(">\n"); +} + +static void xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) { struct xhci_softc *sc = XHCI_BUS2SC(bus); diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index d5cfd228a429..820fb2f738a1 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -178,6 +178,8 @@ xhci_pci_match(device_t self) return ("Intel Tiger Lake-H USB 3.2 controller"); case 0x461e8086: return ("Intel Alder Lake-P Thunderbolt 4 USB controller"); + case 0x4b7d8086: + return ("Intel Elkhart Lake USB 3.1 controller"); case 0x51ed8086: return ("Intel Alder Lake USB 3.2 controller"); case 0x5aa88086: diff --git a/sys/dev/usb/controller/xhcireg.h b/sys/dev/usb/controller/xhcireg.h index 9d0b6e2f4b4b..821897155544 100644 --- a/sys/dev/usb/controller/xhcireg.h +++ b/sys/dev/usb/controller/xhcireg.h @@ -205,6 +205,11 @@ #define XHCI_ID_VIRTUALIZATION 0x0004 #define XHCI_ID_MSG_IRQ 0x0005 #define XHCI_ID_USB_LOCAL_MEM 0x0006 +/* values 7-9 are reserved */ +#define XHCI_ID_USB_DEBUG 0x000a +/* values 11-16 are reserved */ +#define XHCI_ID_EXT_MSI 0x0011 +#define XHCI_ID_USB3_TUN 0x0012 /* XHCI register R/W wrappers */ #define XREAD1(sc, what, a) \ diff --git a/sys/dev/usb/net/if_umb.c b/sys/dev/usb/net/if_umb.c index f640b4224aad..b1082b117259 100644 --- a/sys/dev/usb/net/if_umb.c +++ b/sys/dev/usb/net/if_umb.c @@ -177,9 +177,7 @@ static void umb_ncm_setup(struct umb_softc *, struct usb_config *); static void umb_close_bulkpipes(struct umb_softc *); static int umb_ioctl(if_t , u_long, caddr_t); static void umb_init(void *); -#ifdef DEV_NETMAP static void umb_input(if_t , struct mbuf *); -#endif static int umb_output(if_t , struct mbuf *, const struct sockaddr *, struct route *); static void umb_start(if_t ); @@ -585,9 +583,7 @@ umb_attach_task(struct usb_proc_msg *msg) if_setsoftc(ifp, sc); if_setflags(ifp, IFF_SIMPLEX | IFF_MULTICAST | IFF_POINTOPOINT); if_setioctlfn(ifp, umb_ioctl); -#ifdef DEV_NETMAP if_setinputfn(ifp, umb_input); -#endif if_setoutputfn(ifp, umb_output); if_setstartfn(ifp, umb_start); if_setinitfn(ifp, umb_init); diff --git a/sys/dev/usb/serial/udbc.c b/sys/dev/usb/serial/udbc.c new file mode 100644 index 000000000000..d7ca6b25bf32 --- /dev/null +++ b/sys/dev/usb/serial/udbc.c @@ -0,0 +1,404 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * Copyright (c) 2016-2024 Hiroki Sato <hrs@FreeBSD.org> + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/callout.h> +#include <sys/condvar.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/priv.h> +#include <sys/queue.h> +#include <sys/stddef.h> +#include <sys/stdint.h> +#include <sys/sx.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usb_ioctl.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> +#include <dev/usb/usb_core.h> + +#include "usbdevs.h" + +#define USB_DEBUG_VAR udbc_debug +#include <dev/usb/usb_process.h> +#include <dev/usb/serial/usb_serial.h> +#include <dev/usb/usb_debug.h> + +static SYSCTL_NODE(_hw_usb, OID_AUTO, udbc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "USB DbC Client"); + +#ifdef USB_DEBUG +static int udbc_debug = 0; +SYSCTL_INT(_hw_usb_udbc, OID_AUTO, debug, CTLFLAG_RWTUN, &udbc_debug, 0, + "Debug level"); +#endif + +#define UDBC_CONFIG_INDEX 0 + +#define UDBC_IBUFSIZE 1024 +#define UDBC_OBUFSIZE 1024 + +enum { + UDBC_BULK_DT_WR, + UDBC_BULK_DT_RD, + UDBC_N_TRANSFER, /* n of EP */ +}; + +struct udbc_softc { + struct ucom_super_softc sc_super_ucom; + struct ucom_softc sc_ucom; + + struct usb_device *sc_udev; + struct usb_xfer *sc_xfer[UDBC_N_TRANSFER]; + device_t sc_dev; + struct mtx sc_mtx; + + uint32_t sc_unit; +}; + +/* prototypes */ + +static device_probe_t udbc_probe; +static device_attach_t udbc_attach; +static device_detach_t udbc_detach; +static void udbc_free_softc(struct udbc_softc *); + +static usb_callback_t udbc_write_callback; +static usb_callback_t udbc_read_callback; + +static void udbc_free(struct ucom_softc *); +static void udbc_cfg_open(struct ucom_softc *); +static void udbc_cfg_close(struct ucom_softc *); +static int udbc_pre_param(struct ucom_softc *, struct termios *); +static int udbc_ioctl(struct ucom_softc *, uint32_t, caddr_t, int, + struct thread *); +static void udbc_start_read(struct ucom_softc *); +static void udbc_stop_read(struct ucom_softc *); +static void udbc_start_write(struct ucom_softc *); +static void udbc_stop_write(struct ucom_softc *); +static void udbc_poll(struct ucom_softc *ucom); + +static const struct usb_config udbc_config[UDBC_N_TRANSFER] = { + [UDBC_BULK_DT_WR] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = UDBC_OBUFSIZE, + .flags = {.pipe_bof = 1,}, + .callback = &udbc_write_callback, + }, + + [UDBC_BULK_DT_RD] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = UDBC_IBUFSIZE, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .callback = &udbc_read_callback, + }, +}; + +static const struct ucom_callback udbc_callback = { + .ucom_cfg_open = &udbc_cfg_open, + .ucom_cfg_close = &udbc_cfg_close, + .ucom_pre_param = &udbc_pre_param, + .ucom_ioctl = &udbc_ioctl, + .ucom_start_read = &udbc_start_read, + .ucom_stop_read = &udbc_stop_read, + .ucom_start_write = &udbc_start_write, + .ucom_stop_write = &udbc_stop_write, + .ucom_poll = &udbc_poll, + .ucom_free = &udbc_free, +}; + +static device_method_t udbc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, udbc_probe), + DEVMETHOD(device_attach, udbc_attach), + DEVMETHOD(device_detach, udbc_detach), + DEVMETHOD_END +}; + +static int +udbc_probe(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != UDBC_CONFIG_INDEX) + return (ENXIO); + if (uaa->info.bInterfaceClass != UICLASS_DIAGNOSTIC) + return (ENXIO); + if (uaa->info.bDeviceProtocol != 0x00) /* GNU GDB == 1 */ + return (ENXIO); + + return (BUS_PROBE_SPECIFIC); +} + +static int +udbc_attach(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + struct udbc_softc *sc = device_get_softc(dev); + int error; + + DPRINTF("\n"); + + sc->sc_udev = uaa->device; + sc->sc_dev = dev; + sc->sc_unit = device_get_unit(dev); + + device_set_usb_desc(dev); + mtx_init(&sc->sc_mtx, "udbc", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); + + sc->sc_ucom.sc_portno = 0; + + error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, + sc->sc_xfer, udbc_config, UDBC_N_TRANSFER, sc, &sc->sc_mtx); + + if (error) { + device_printf(dev, + "allocating USB transfers failed\n"); + goto detach; + } + /* clear stall at first run */ + mtx_lock(&sc->sc_mtx); + usbd_xfer_set_stall(sc->sc_xfer[UDBC_BULK_DT_WR]); + usbd_xfer_set_stall(sc->sc_xfer[UDBC_BULK_DT_RD]); + mtx_unlock(&sc->sc_mtx); + + error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &udbc_callback, &sc->sc_mtx); + if (error) + goto detach; + ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); + + return (0); /* success */ + +detach: + udbc_detach(dev); + return (ENXIO); +} + +static int +udbc_detach(device_t dev) +{ + struct udbc_softc *sc = device_get_softc(dev); + + ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); + usbd_transfer_unsetup(sc->sc_xfer, UDBC_N_TRANSFER); + + device_claim_softc(dev); + + udbc_free_softc(sc); + + return (0); +} + +UCOM_UNLOAD_DRAIN(udbc); + +static void +udbc_free_softc(struct udbc_softc *sc) +{ + if (ucom_unref(&sc->sc_super_ucom)) { + mtx_destroy(&sc->sc_mtx); + device_free_softc(sc); + } +} + +static void +udbc_free(struct ucom_softc *ucom) +{ + udbc_free_softc(ucom->sc_parent); +} + +static void +udbc_cfg_open(struct ucom_softc *ucom) +{ + /* + * This do-nothing open routine exists for the sole purpose of this + * DPRINTF() so that you can see the point at which open gets called + * when debugging is enabled. + */ + DPRINTF("\n"); +} + +static void +udbc_cfg_close(struct ucom_softc *ucom) +{ + /* + * This do-nothing close routine exists for the sole purpose of this + * DPRINTF() so that you can see the point at which close gets called + * when debugging is enabled. + */ + DPRINTF("\n"); +} + +static void +udbc_write_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct udbc_softc *sc = usbd_xfer_softc(xfer); + struct usb_page_cache *pc; + uint32_t buflen; + + DPRINTFN(3, "\n"); + + switch (USB_GET_STATE(xfer)) { + default: /* Error */ + if (error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + usbd_xfer_set_stall(xfer); + } + /* FALLTHROUGH */ + case USB_ST_SETUP: + case USB_ST_TRANSFERRED: + pc = usbd_xfer_get_frame(xfer, 0); + if (ucom_get_data(&sc->sc_ucom, pc, 0, UDBC_OBUFSIZE, + &buflen) == 0) + break; + if (buflen != 0) { + usbd_xfer_set_frame_len(xfer, 0, buflen); + usbd_transfer_submit(xfer); + } + break; + } +} + +static void +udbc_read_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct udbc_softc *sc = usbd_xfer_softc(xfer); + struct usb_page_cache *pc; + int buflen; + + DPRINTFN(3, "\n"); + + usbd_xfer_status(xfer, &buflen, NULL, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + pc = usbd_xfer_get_frame(xfer, 0); + ucom_put_data(&sc->sc_ucom, pc, 0, buflen); + /* FALLTHROUGH */ + case USB_ST_SETUP: +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 */ + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + return; + } +} + +static int +udbc_pre_param(struct ucom_softc *ucom, struct termios *t) +{ + DPRINTF("\n"); + + return (0); +} + +static int +udbc_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data, int flag, + struct thread *td) +{ + return (ENOIOCTL); +} + +static void +udbc_start_read(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_start(sc->sc_xfer[UDBC_BULK_DT_RD]); +} + +static void +udbc_stop_read(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_stop(sc->sc_xfer[UDBC_BULK_DT_RD]); +} + +static void +udbc_start_write(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_start(sc->sc_xfer[UDBC_BULK_DT_WR]); +} + +static void +udbc_stop_write(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_stop(sc->sc_xfer[UDBC_BULK_DT_WR]); +} + +static void +udbc_poll(struct ucom_softc *ucom) +{ + struct udbc_softc *sc = ucom->sc_parent; + + usbd_transfer_poll(sc->sc_xfer, UDBC_N_TRANSFER); +} + +static driver_t udbc_driver = { + .name = "udbc", + .methods = udbc_methods, + .size = sizeof(struct udbc_softc), +}; + +DRIVER_MODULE(udbc, uhub, udbc_driver, NULL, NULL); +MODULE_DEPEND(udbc, ucom, 1, 1, 1); +MODULE_DEPEND(udbc, usb, 1, 1, 1); +MODULE_VERSION(udbc, 1); diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index e3509862ef54..ee9d8ab0c9bb 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -954,7 +954,8 @@ done: * packet. This function is called having the "bus_mtx" locked. *------------------------------------------------------------------------*/ void -uhub_root_intr(struct usb_bus *bus, const uint8_t *ptr, uint8_t len) +uhub_root_intr(struct usb_bus *bus, + const uint8_t *ptr __unused, uint8_t len __unused) { USB_BUS_LOCK_ASSERT(bus, MA_OWNED); diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index 07f7b6f3a708..e976948f6849 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -371,18 +371,16 @@ rsu_update_chw(struct ieee80211com *ic) /* * notification from net80211 that it'd like to do A-MPDU on the given TID. - * - * Note: this actually hangs traffic at the present moment, so don't use it. - * The firmware debug does indiciate it's sending and establishing a TX AMPDU - * session, but then no traffic flows. */ static int rsu_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) { -#if 0 struct rsu_softc *sc = ni->ni_ic->ic_softc; struct r92s_add_ba_req req; + RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: called, tid=%d\n", + __func__, tap->txa_tid); + /* Don't enable if it's requested or running */ if (IEEE80211_AMPDU_REQUESTED(tap)) return (0); @@ -397,23 +395,30 @@ rsu_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) return (0); /* Send the firmware command */ - RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: establishing AMPDU TX for TID %d\n", + RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, + "%s: establishing AMPDU TX for TID %d\n", __func__, tap->txa_tid); RSU_LOCK(sc); - if (rsu_fw_cmd(sc, R92S_CMD_ADDBA_REQ, &req, sizeof(req)) != 1) { + if (rsu_fw_cmd(sc, R92S_CMD_ADDBA_REQ, &req, sizeof(req)) != 0) { RSU_UNLOCK(sc); + RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: AMPDU TX cmd failure\n", + __func__); /* Mark failure */ - (void) ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 0); + ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 0); + /* Return 0, we've been driving this ourselves */ return (0); } RSU_UNLOCK(sc); + RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: AMPDU TX cmd success\n", + __func__); + /* Mark success; we don't get any further notifications */ - (void) ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 1); -#endif - /* Return 0, we're driving this ourselves */ + ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 1); + + /* Return 0, we've been driving this ourselves */ return (0); } @@ -563,9 +568,7 @@ rsu_attach(device_t self) /* Enable basic HT */ ic->ic_htcaps = IEEE80211_HTC_HT | -#if 0 IEEE80211_HTC_AMPDU | -#endif IEEE80211_HTC_AMSDU | IEEE80211_HTCAP_MAXAMSDU_3839 | IEEE80211_HTCAP_SMPS_OFF; @@ -576,6 +579,7 @@ rsu_attach(device_t self) ic->ic_rxstream = sc->sc_nrxstream; } ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; rsu_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -1537,6 +1541,10 @@ rsu_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, is_checked = 1; k->wk_flags |= IEEE80211_KEY_SWCRYPT; } else + /* + * TODO: should allocate these from the CAM space; + * skipping over the fixed slots and _BC / _BSS. + */ *keyix = R92S_MACID_BSS; } @@ -2166,7 +2174,7 @@ rsu_event_addba_req_report(struct rsu_softc *sc, uint8_t *buf, int len) __func__, ether_sprintf(ba->mac_addr), (int) ba->tid, - (int) le16toh(ba->ssn)); + (int) le16toh(ba->ssn) >> 4); /* XXX do node lookup; this is STA specific */ @@ -2212,6 +2220,11 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len) if (vap->iv_state == IEEE80211_S_AUTH) rsu_event_join_bss(sc, buf, len); break; + + /* TODO: what about R92S_EVT_ADD_STA? and decoding macid? */ + /* It likely is required for IBSS/AP mode */ + + /* TODO: should I be doing this transition in AP mode? */ case R92S_EVT_DEL_STA: RSU_DPRINTF(sc, RSU_DEBUG_FWCMD | RSU_DEBUG_STATE, "%s: disassociated from %s\n", __func__, @@ -2229,6 +2242,7 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len) break; case R92S_EVT_FWDBG: buf[60] = '\0'; + /* TODO: some are \n terminated, some aren't, sigh */ RSU_DPRINTF(sc, RSU_DEBUG_FWDBG, "FWDBG: %s\n", (char *)buf); break; case R92S_EVT_ADDBA_REQ_REPORT: @@ -2782,6 +2796,9 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, if (rate != 0) ridx = rate2ridx(rate); + /* Assign sequence number, A-MPDU or otherwise */ + ieee80211_output_seqno_assign(ni, -1, m0); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { @@ -2838,8 +2855,10 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, SM(R92S_TXDW0_OFFSET, sizeof(*txd)) | R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG); + /* TODO: correct macid here? It should be in the node */ txd->txdw1 |= htole32( SM(R92S_TXDW1_MACID, R92S_MACID_BSS) | SM(R92S_TXDW1_QSEL, qid)); + if (!hasqos) txd->txdw1 |= htole32(R92S_TXDW1_NONQOS); if (k != NULL && !(k->wk_flags & IEEE80211_KEY_SWENCRYPT)) { @@ -2860,8 +2879,13 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, SM(R92S_TXDW1_CIPHER, cipher) | SM(R92S_TXDW1_KEYIDX, k->wk_keyix)); } - /* XXX todo: set AGGEN bit if appropriate? */ - txd->txdw2 |= htole32(R92S_TXDW2_BK); + + /* + * Note: no need to set TXDW2_AGGEN/TXDW2_BK to mark + * A-MPDU and non-AMPDU candidates; the firmware will + * handle this for us. + */ + if (ismcast) txd->txdw2 |= htole32(R92S_TXDW2_BMCAST); @@ -2880,8 +2904,11 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, } /* - * Firmware will use and increment the sequence number for the - * specified priority. + * Pass in prio here, NOT the sequence number. + * + * The hardware is in theory incrementing sequence numbers + * for us, but I haven't yet figured out exactly when/how + * it's supposed to work. */ txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, prio)); @@ -3481,7 +3508,8 @@ rsu_load_firmware(struct rsu_softc *sc) dmem.vcs_mode = R92S_VCS_MODE_RTS_CTS; dmem.turbo_mode = 0; dmem.bw40_en = !! (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40); - dmem.amsdu2ampdu_en = !! (sc->sc_ht); + /* net80211 handles AMSDUs just fine */ + dmem.amsdu2ampdu_en = 0; dmem.ampdu_en = !! (sc->sc_ht); dmem.agg_offload = !! (sc->sc_ht); dmem.qos_en = 1; diff --git a/sys/dev/usb/wlan/if_rsureg.h b/sys/dev/usb/wlan/if_rsureg.h index fb706a4d9b1a..e2074e1dd2ad 100644 --- a/sys/dev/usb/wlan/if_rsureg.h +++ b/sys/dev/usb/wlan/if_rsureg.h @@ -593,7 +593,14 @@ struct r92s_event_join_bss { struct ndis_wlan_bssid_ex bss; } __packed; -#define R92S_MACID_BSS 5 /* XXX hardcoded somewhere */ +/* + * This is hard-coded in the firmware for a STA mode + * BSS join. If you turn on FWDEBUG, you'll see this + * in the logs: + * + * rsu0: FWDBG: mac id #5: 0000005b, 000fffff, 00000000 + */ +#define R92S_MACID_BSS 5 /* Rx MAC descriptor. */ struct r92s_rx_stat { diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 97c790dd5b81..147aa4044057 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -882,6 +882,7 @@ run_attach(device_t self) ic->ic_flags |= IEEE80211_F_DATAPAD; ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; run_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); @@ -3522,6 +3523,9 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) data->ni = ni; data->ridx = ridx; + /* Assign sequence number now, regardless of A-MPDU TX or otherwise (for now) */ + ieee80211_output_seqno_assign(ni, -1, m); + run_set_tx_desc(sc, data); /* @@ -3627,6 +3631,9 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) data->ni = ni; data->ridx = ridx; + /* Assign sequence number now, regardless of A-MPDU TX or otherwise (for now) */ + ieee80211_output_seqno_assign(ni, -1, m); + run_set_tx_desc(sc, data); RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending mgt frame len=%d rate=%d\n", @@ -3771,6 +3778,9 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni, break; data->ridx = ridx; + /* Assign sequence number now, regardless of A-MPDU TX or otherwise (for now) */ + ieee80211_output_seqno_assign(ni, -1, m); + run_set_tx_desc(sc, data); RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending raw frame len=%u rate=%u\n", @@ -6416,6 +6426,10 @@ run_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) { /* For now, no A-MPDU TX support in the driver */ + /* + * TODO: maybe we needed to enable seqno generation too? + * What other TX desc bits are missing/needed? + */ return (0); } |