1132718Skan/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ 2117395Skan 3169689Skan/*- 4117395Skan * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 5117395Skan * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> 6117395Skan * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org> 7117395Skan * 8117395Skan * Permission to use, copy, modify, and distribute this software for any 9117395Skan * purpose with or without fee is hereby granted, provided that the above 10117395Skan * copyright notice and this permission notice appear in all copies. 11117395Skan * 12117395Skan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13117395Skan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14117395Skan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15117395Skan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16117395Skan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17117395Skan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18169689Skan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19169689Skan */ 20117395Skan 21117395Skan#include <sys/cdefs.h> 22117395Skan__FBSDID("$FreeBSD$"); 23117395Skan 24117395Skan#include <sys/param.h> 25117395Skan#include <sys/sysctl.h> 26117395Skan#include <sys/lock.h> 27117395Skan#include <sys/mutex.h> 28132718Skan#include <sys/mbuf.h> 29132718Skan#include <sys/kernel.h> 30117395Skan#include <sys/socket.h> 31132718Skan#include <sys/systm.h> 32117395Skan#include <sys/malloc.h> 33132718Skan#include <sys/module.h> 34132718Skan#include <sys/bus.h> 35117395Skan#include <sys/endian.h> 36132718Skan#include <sys/linker.h> 37132718Skan#include <sys/kdb.h> 38132718Skan 39132718Skan#include <net/if.h> 40169689Skan#include <net/if_var.h> 41132718Skan#include <net/ethernet.h> 42117395Skan#include <net/if_media.h> 43132718Skan 44132718Skan#include <net80211/ieee80211_var.h> 45132718Skan 46132718Skan#include <dev/usb/usb.h> 47132718Skan#include <dev/usb/usbdi.h> 48132718Skan#include "usbdevs.h" 49132718Skan 50132718Skan#include <dev/rtwn/if_rtwnvar.h> 51132718Skan#include <dev/rtwn/if_rtwn_nop.h> 52132718Skan 53132718Skan#include <dev/rtwn/usb/rtwn_usb_var.h> 54169689Skan 55132718Skan#include <dev/rtwn/usb/rtwn_usb_attach.h> 56117395Skan#include <dev/rtwn/usb/rtwn_usb_ep.h> 57117395Skan#include <dev/rtwn/usb/rtwn_usb_reg.h> 58132718Skan#include <dev/rtwn/usb/rtwn_usb_tx.h> 59169689Skan 60117395Skan#include <dev/rtwn/rtl8192c/r92c_reg.h> 61132718Skan 62117395Skanstatic device_probe_t rtwn_usb_match; 63132718Skanstatic device_attach_t rtwn_usb_attach; 64132718Skanstatic device_detach_t rtwn_usb_detach; 65132718Skanstatic device_suspend_t rtwn_usb_suspend; 66132718Skanstatic device_resume_t rtwn_usb_resume; 67132718Skan 68117395Skanstatic int rtwn_usb_alloc_list(struct rtwn_softc *, 69132718Skan struct rtwn_data[], int, int); 70132718Skanstatic int rtwn_usb_alloc_rx_list(struct rtwn_softc *); 71132718Skanstatic int rtwn_usb_alloc_tx_list(struct rtwn_softc *); 72117395Skanstatic void rtwn_usb_free_list(struct rtwn_softc *, 73132718Skan struct rtwn_data data[], int); 74117395Skanstatic void rtwn_usb_free_rx_list(struct rtwn_softc *); 75132718Skanstatic void rtwn_usb_free_tx_list(struct rtwn_softc *); 76132718Skanstatic void rtwn_usb_reset_lists(struct rtwn_softc *, 77117395Skan struct ieee80211vap *); 78132718Skanstatic void rtwn_usb_reset_tx_list(struct rtwn_usb_softc *, 79132718Skan rtwn_datahead *, struct ieee80211vap *); 80117395Skanstatic void rtwn_usb_reset_rx_list(struct rtwn_usb_softc *); 81132718Skanstatic void rtwn_usb_start_xfers(struct rtwn_softc *); 82132718Skanstatic void rtwn_usb_abort_xfers(struct rtwn_softc *); 83132718Skanstatic int rtwn_usb_fw_write_block(struct rtwn_softc *, 84117395Skan const uint8_t *, uint16_t, int); 85132718Skanstatic void rtwn_usb_drop_incorrect_tx(struct rtwn_softc *); 86117395Skanstatic void rtwn_usb_attach_methods(struct rtwn_softc *); 87132718Skanstatic void rtwn_usb_sysctlattach(struct rtwn_softc *); 88132718Skan 89117395Skan#define RTWN_CONFIG_INDEX 0 90132718Skan 91169689Skanstatic int 92132718Skanrtwn_usb_match(device_t self) 93117395Skan{ 94132718Skan struct usb_attach_arg *uaa = device_get_ivars(self); 95132718Skan 96132718Skan if (uaa->usb_mode != USB_MODE_HOST) 97117395Skan return (ENXIO); 98117395Skan if (uaa->info.bConfigIndex != RTWN_CONFIG_INDEX) 99132718Skan return (ENXIO); 100132718Skan if (uaa->info.bIfaceIndex != RTWN_IFACE_INDEX) 101132718Skan return (ENXIO); 102132718Skan 103117395Skan return (usbd_lookup_id_by_uaa(rtwn_devs, sizeof(rtwn_devs), uaa)); 104132718Skan} 105169689Skan 106132718Skanstatic int 107132718Skanrtwn_usb_alloc_list(struct rtwn_softc *sc, struct rtwn_data data[], 108132718Skan int ndata, int maxsz) 109132718Skan{ 110132718Skan int i, error; 111117395Skan 112117395Skan for (i = 0; i < ndata; i++) { 113169689Skan struct rtwn_data *dp = &data[i]; 114117395Skan dp->m = NULL; 115132718Skan dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT); 116132718Skan if (dp->buf == NULL) { 117117395Skan device_printf(sc->sc_dev, 118132718Skan "could not allocate buffer\n"); 119117395Skan error = ENOMEM; 120132718Skan goto fail; 121132718Skan } 122132718Skan dp->ni = NULL; 123132718Skan } 124132718Skan 125132718Skan return (0); 126117395Skanfail: 127132718Skan rtwn_usb_free_list(sc, data, ndata); 128132718Skan return (error); 129132718Skan} 130132718Skan 131132718Skanstatic int 132132718Skanrtwn_usb_alloc_rx_list(struct rtwn_softc *sc) 133132718Skan{ 134132718Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 135132718Skan int error, i; 136117395Skan 137132718Skan error = rtwn_usb_alloc_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT, 138169689Skan uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT); 139117395Skan if (error != 0) 140132718Skan return (error); 141132718Skan 142132718Skan STAILQ_INIT(&uc->uc_rx_active); 143132718Skan STAILQ_INIT(&uc->uc_rx_inactive); 144132718Skan 145117395Skan for (i = 0; i < RTWN_USB_RX_LIST_COUNT; i++) 146169689Skan STAILQ_INSERT_HEAD(&uc->uc_rx_inactive, &uc->uc_rx[i], next); 147169689Skan 148169689Skan return (0); 149169689Skan} 150117395Skan 151132718Skanstatic int 152132718Skanrtwn_usb_alloc_tx_list(struct rtwn_softc *sc) 153169689Skan{ 154169689Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 155132718Skan int error, i; 156117395Skan 157132718Skan error = rtwn_usb_alloc_list(sc, uc->uc_tx, RTWN_USB_TX_LIST_COUNT, 158132718Skan RTWN_USB_TXBUFSZ); 159169689Skan if (error != 0) 160169689Skan return (error); 161132718Skan 162117395Skan STAILQ_INIT(&uc->uc_tx_active); 163169689Skan STAILQ_INIT(&uc->uc_tx_inactive); 164169689Skan STAILQ_INIT(&uc->uc_tx_pending); 165169689Skan 166132718Skan for (i = 0; i < RTWN_USB_TX_LIST_COUNT; i++) 167117395Skan STAILQ_INSERT_HEAD(&uc->uc_tx_inactive, &uc->uc_tx[i], next); 168132718Skan 169117395Skan return (0); 170132718Skan} 171132718Skan 172132718Skanstatic void 173132718Skanrtwn_usb_free_list(struct rtwn_softc *sc, struct rtwn_data data[], int ndata) 174132718Skan{ 175132718Skan int i; 176132718Skan 177132718Skan for (i = 0; i < ndata; i++) { 178132718Skan struct rtwn_data *dp = &data[i]; 179117395Skan 180132718Skan if (dp->buf != NULL) { 181117395Skan free(dp->buf, M_USBDEV); 182132718Skan dp->buf = NULL; 183132718Skan } 184132718Skan if (dp->ni != NULL) { 185132718Skan ieee80211_free_node(dp->ni); 186132718Skan dp->ni = NULL; 187117395Skan } 188132718Skan if (dp->m != NULL) { 189132718Skan m_freem(dp->m); 190117395Skan dp->m = NULL; 191132718Skan } 192117395Skan } 193169689Skan} 194169689Skan 195169689Skanstatic void 196169689Skanrtwn_usb_free_rx_list(struct rtwn_softc *sc) 197132718Skan{ 198169689Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 199169689Skan 200117395Skan rtwn_usb_free_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT); 201132718Skan 202117395Skan uc->uc_rx_stat_len = 0; 203132718Skan uc->uc_rx_off = 0; 204132718Skan 205132718Skan STAILQ_INIT(&uc->uc_rx_active); 206132718Skan STAILQ_INIT(&uc->uc_rx_inactive); 207117395Skan} 208132718Skan 209132718Skanstatic void 210132718Skanrtwn_usb_free_tx_list(struct rtwn_softc *sc) 211132718Skan{ 212132718Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 213132718Skan 214132718Skan rtwn_usb_free_list(sc, uc->uc_tx, RTWN_USB_TX_LIST_COUNT); 215132718Skan 216117395Skan STAILQ_INIT(&uc->uc_tx_active); 217117395Skan STAILQ_INIT(&uc->uc_tx_inactive); 218132718Skan STAILQ_INIT(&uc->uc_tx_pending); 219169689Skan} 220169689Skan 221169689Skanstatic void 222132718Skanrtwn_usb_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap) 223132718Skan{ 224132718Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 225117395Skan 226132718Skan RTWN_ASSERT_LOCKED(sc); 227117395Skan 228132718Skan rtwn_usb_reset_tx_list(uc, &uc->uc_tx_active, vap); 229132718Skan rtwn_usb_reset_tx_list(uc, &uc->uc_tx_pending, vap); 230132718Skan if (vap == NULL) { 231132718Skan rtwn_usb_reset_rx_list(uc); 232117395Skan sc->qfullmsk = 0; 233169689Skan } 234117395Skan} 235132718Skan 236132718Skanstatic void 237132718Skanrtwn_usb_reset_tx_list(struct rtwn_usb_softc *uc, 238132718Skan rtwn_datahead *head, struct ieee80211vap *vap) 239132718Skan{ 240132718Skan struct rtwn_vap *uvp = RTWN_VAP(vap); 241132718Skan struct rtwn_data *dp, *tmp; 242132718Skan int id; 243132718Skan 244132718Skan id = (uvp != NULL ? uvp->id : RTWN_VAP_ID_INVALID); 245132718Skan 246132718Skan STAILQ_FOREACH_SAFE(dp, head, next, tmp) { 247132718Skan if (vap == NULL || (dp->ni == NULL && 248132718Skan (dp->id == id || id == RTWN_VAP_ID_INVALID)) || 249132718Skan (dp->ni != NULL && dp->ni->ni_vap == vap)) { 250132718Skan if (dp->ni != NULL) { 251132718Skan ieee80211_free_node(dp->ni); 252132718Skan dp->ni = NULL; 253132718Skan } 254132718Skan 255132718Skan if (dp->m != NULL) { 256132718Skan m_freem(dp->m); 257132718Skan dp->m = NULL; 258132718Skan } 259132718Skan 260132718Skan STAILQ_REMOVE(head, dp, rtwn_data, next); 261132718Skan STAILQ_INSERT_TAIL(&uc->uc_tx_inactive, dp, next); 262132718Skan } 263117395Skan } 264132718Skan} 265132718Skan 266132718Skanstatic void 267132718Skanrtwn_usb_reset_rx_list(struct rtwn_usb_softc *uc) 268117395Skan{ 269132718Skan int i; 270169689Skan 271117395Skan for (i = 0; i < RTWN_USB_RX_LIST_COUNT; i++) { 272132718Skan struct rtwn_data *dp = &uc->uc_rx[i]; 273132718Skan 274132718Skan if (dp->m != NULL) { 275132718Skan m_freem(dp->m); 276132718Skan dp->m = NULL; 277117395Skan } 278117395Skan } 279169689Skan uc->uc_rx_stat_len = 0; 280132718Skan uc->uc_rx_off = 0; 281132718Skan} 282117395Skan 283117395Skanstatic void 284132718Skanrtwn_usb_start_xfers(struct rtwn_softc *sc) 285132718Skan{ 286132718Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 287117395Skan 288132718Skan usbd_transfer_start(uc->uc_xfer[RTWN_BULK_RX]); 289117395Skan} 290132718Skan 291132718Skanstatic void 292117395Skanrtwn_usb_abort_xfers(struct rtwn_softc *sc) 293132718Skan{ 294169689Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 295132718Skan int i; 296117395Skan 297132718Skan RTWN_ASSERT_LOCKED(sc); 298117395Skan 299169689Skan /* abort any pending transfers */ 300117395Skan RTWN_UNLOCK(sc); 301132718Skan for (i = 0; i < RTWN_N_TRANSFER; i++) 302132718Skan usbd_transfer_drain(uc->uc_xfer[i]); 303132718Skan RTWN_LOCK(sc); 304132718Skan} 305132718Skan 306117395Skanstatic int 307132718Skanrtwn_usb_fw_write_block(struct rtwn_softc *sc, const uint8_t *buf, 308132718Skan uint16_t reg, int mlen) 309132718Skan{ 310132718Skan int error; 311132718Skan 312132718Skan /* XXX fix this deconst */ 313117395Skan error = rtwn_usb_write_region_1(sc, reg, __DECONST(uint8_t *, buf), 314132718Skan mlen); 315117395Skan 316132718Skan return (error); 317132718Skan} 318117395Skan 319132718Skanstatic void 320117395Skanrtwn_usb_drop_incorrect_tx(struct rtwn_softc *sc) 321132718Skan{ 322132718Skan 323132718Skan rtwn_setbits_1_shift(sc, R92C_TXDMA_OFFSET_CHK, 0, 324132718Skan R92C_TXDMA_OFFSET_DROP_DATA_EN, 1); 325132718Skan} 326117395Skan 327132718Skanstatic void 328132718Skanrtwn_usb_attach_methods(struct rtwn_softc *sc) 329132718Skan{ 330132718Skan sc->sc_write_1 = rtwn_usb_write_1; 331132718Skan sc->sc_write_2 = rtwn_usb_write_2; 332132718Skan sc->sc_write_4 = rtwn_usb_write_4; 333132718Skan sc->sc_read_1 = rtwn_usb_read_1; 334132718Skan sc->sc_read_2 = rtwn_usb_read_2; 335132718Skan sc->sc_read_4 = rtwn_usb_read_4; 336132718Skan sc->sc_delay = rtwn_usb_delay; 337132718Skan sc->sc_tx_start = rtwn_usb_tx_start; 338132718Skan sc->sc_start_xfers = rtwn_usb_start_xfers; 339132718Skan sc->sc_reset_lists = rtwn_usb_reset_lists; 340132718Skan sc->sc_abort_xfers = rtwn_usb_abort_xfers; 341132718Skan sc->sc_fw_write_block = rtwn_usb_fw_write_block; 342132718Skan sc->sc_get_qmap = rtwn_usb_get_qmap; 343117395Skan sc->sc_set_desc_addr = rtwn_nop_softc; 344132718Skan sc->sc_drop_incorrect_tx = rtwn_usb_drop_incorrect_tx; 345132718Skan sc->sc_beacon_update_begin = rtwn_nop_softc_vap; 346132718Skan sc->sc_beacon_update_end = rtwn_nop_softc_vap; 347132718Skan sc->sc_beacon_unload = rtwn_nop_softc_int; 348132718Skan 349132718Skan sc->bcn_check_interval = 100; 350132718Skan} 351117395Skan 352132718Skanstatic void 353132718Skanrtwn_usb_sysctlattach(struct rtwn_softc *sc) 354132718Skan{ 355132718Skan struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 356132718Skan struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 357132718Skan struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 358132718Skan char str[64]; 359132718Skan int ret; 360132718Skan 361117395Skan ret = snprintf(str, sizeof(str), 362132718Skan "Rx buffer size, 512-byte units [%d...%d]", 363132718Skan RTWN_USB_RXBUFSZ_MIN, RTWN_USB_RXBUFSZ_MAX); 364132718Skan KASSERT(ret > 0, ("ret (%d) <= 0!\n", ret)); 365132718Skan (void) ret; 366132718Skan 367132718Skan uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_DEF; 368132718Skan SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 369117395Skan "rx_buf_size", CTLFLAG_RDTUN, &uc->uc_rx_buf_size, 370132718Skan uc->uc_rx_buf_size, str); 371132718Skan if (uc->uc_rx_buf_size < RTWN_USB_RXBUFSZ_MIN) 372132718Skan uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MIN; 373132718Skan if (uc->uc_rx_buf_size > RTWN_USB_RXBUFSZ_MAX) 374132718Skan uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MAX; 375132718Skan} 376132718Skan 377132718Skanstatic int 378132718Skanrtwn_usb_attach(device_t self) 379132718Skan{ 380132718Skan struct usb_attach_arg *uaa = device_get_ivars(self); 381132718Skan struct rtwn_usb_softc *uc = device_get_softc(self); 382117395Skan struct rtwn_softc *sc = &uc->uc_sc; 383132718Skan struct ieee80211com *ic = &sc->sc_ic; 384132718Skan int error; 385132718Skan 386132718Skan device_set_usb_desc(self); 387132718Skan uc->uc_udev = uaa->device; 388132718Skan sc->sc_dev = self; 389132718Skan ic->ic_name = device_get_nameunit(self); 390132718Skan 391132718Skan /* Need to be initialized early. */ 392132718Skan rtwn_sysctlattach(sc); 393132718Skan rtwn_usb_sysctlattach(sc); 394132718Skan mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF); 395132718Skan 396132718Skan rtwn_usb_attach_methods(sc); 397132718Skan rtwn_usb_attach_private(uc, USB_GET_DRIVER_INFO(uaa)); 398117395Skan 399132718Skan error = rtwn_usb_setup_endpoints(uc); 400132718Skan if (error != 0) 401132718Skan goto detach; 402132718Skan 403132718Skan /* Allocate Tx/Rx buffers. */ 404132718Skan error = rtwn_usb_alloc_rx_list(sc); 405132718Skan if (error != 0) 406132718Skan goto detach; 407132718Skan 408132718Skan error = rtwn_usb_alloc_tx_list(sc); 409132718Skan if (error != 0) 410132718Skan goto detach; 411132718Skan 412132718Skan /* Generic attach. */ 413132718Skan error = rtwn_attach(sc); 414132718Skan if (error != 0) 415132718Skan goto detach; 416132718Skan 417117395Skan return (0); 418132718Skan 419132718Skandetach: 420132718Skan rtwn_usb_detach(self); /* failure */ 421132718Skan return (ENXIO); 422132718Skan} 423132718Skan 424132718Skanstatic int 425132718Skanrtwn_usb_detach(device_t self) 426132718Skan{ 427132718Skan struct rtwn_usb_softc *uc = device_get_softc(self); 428132718Skan struct rtwn_softc *sc = &uc->uc_sc; 429132718Skan 430132718Skan /* Generic detach. */ 431132718Skan rtwn_detach(sc); 432132718Skan 433117395Skan /* Free Tx/Rx buffers. */ 434117395Skan rtwn_usb_free_tx_list(sc); 435132718Skan rtwn_usb_free_rx_list(sc); 436132718Skan 437132718Skan /* Detach all USB transfers. */ 438132718Skan usbd_transfer_unsetup(uc->uc_xfer, RTWN_N_TRANSFER); 439117395Skan 440117395Skan rtwn_detach_private(sc); 441169689Skan mtx_destroy(&sc->sc_mtx); 442132718Skan 443132718Skan return (0); 444132718Skan} 445117395Skan 446132718Skanstatic int 447132718Skanrtwn_usb_suspend(device_t self) 448169689Skan{ 449169689Skan struct rtwn_usb_softc *uc = device_get_softc(self); 450169689Skan 451117395Skan rtwn_suspend(&uc->uc_sc); 452132718Skan 453132718Skan return (0); 454132718Skan} 455132718Skan 456117395Skanstatic int 457132718Skanrtwn_usb_resume(device_t self) 458132718Skan{ 459132718Skan struct rtwn_usb_softc *uc = device_get_softc(self); 460117395Skan 461132718Skan rtwn_resume(&uc->uc_sc); 462117395Skan 463117395Skan return (0); 464132718Skan} 465117395Skan 466132718Skanstatic device_method_t rtwn_usb_methods[] = { 467132718Skan /* Device interface */ 468132718Skan DEVMETHOD(device_probe, rtwn_usb_match), 469132718Skan DEVMETHOD(device_attach, rtwn_usb_attach), 470132718Skan DEVMETHOD(device_detach, rtwn_usb_detach), 471132718Skan DEVMETHOD(device_suspend, rtwn_usb_suspend), 472132718Skan DEVMETHOD(device_resume, rtwn_usb_resume), 473132718Skan 474117395Skan DEVMETHOD_END 475132718Skan}; 476132718Skan 477132718Skanstatic driver_t rtwn_usb_driver = { 478132718Skan "rtwn", 479132718Skan rtwn_usb_methods, 480117395Skan sizeof(struct rtwn_usb_softc) 481132718Skan}; 482132718Skan 483117395Skanstatic devclass_t rtwn_usb_devclass; 484132718Skan 485117395SkanDRIVER_MODULE(rtwn_usb, uhub, rtwn_usb_driver, rtwn_usb_devclass, NULL, NULL); 486117395SkanMODULE_VERSION(rtwn_usb, 1); 487132718SkanMODULE_DEPEND(rtwn_usb, usb, 1, 1, 1); 488117395SkanMODULE_DEPEND(rtwn_usb, wlan, 1, 1, 1); 489132718SkanMODULE_DEPEND(rtwn_usb, rtwn, 2, 2, 2); 490132718SkanUSB_PNP_HOST_INFO(rtwn_devs); 491117395Skan