|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting ! 3: * Copyright (c) 2004-2005 Atheros Communications, Inc. ! 4: * Copyright (c) 2006 Devicescape Software, Inc. ! 5: * Copyright (c) 2007 Jiri Slaby <[email protected]> ! 6: * Copyright (c) 2007 Luis R. Rodriguez <[email protected]> ! 7: * ! 8: * Modified for iPXE, July 2009, by Joshua Oreman <[email protected]> ! 9: * Original from Linux kernel 2.6.30. ! 10: * ! 11: * All rights reserved. ! 12: * ! 13: * Redistribution and use in source and binary forms, with or without ! 14: * modification, are permitted provided that the following conditions ! 15: * are met: ! 16: * 1. Redistributions of source code must retain the above copyright ! 17: * notice, this list of conditions and the following disclaimer, ! 18: * without modification. ! 19: * 2. Redistributions in binary form must reproduce at minimum a disclaimer ! 20: * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any ! 21: * redistribution must be conditioned upon including a substantially ! 22: * similar Disclaimer requirement for further binary redistribution. ! 23: * 3. Neither the names of the above-listed copyright holders nor the names ! 24: * of any contributors may be used to endorse or promote products derived ! 25: * from this software without specific prior written permission. ! 26: * ! 27: * Alternatively, this software may be distributed under the terms of the ! 28: * GNU General Public License ("GPL") version 2 as published by the Free ! 29: * Software Foundation. ! 30: * ! 31: * NO WARRANTY ! 32: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ! 33: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ! 34: * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY ! 35: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ! 36: * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, ! 37: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ! 38: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ! 39: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER ! 40: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ! 41: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF ! 42: * THE POSSIBILITY OF SUCH DAMAGES. ! 43: * ! 44: */ ! 45: ! 46: FILE_LICENCE ( BSD3 ); ! 47: ! 48: #include <stdlib.h> ! 49: #include <ipxe/malloc.h> ! 50: #include <ipxe/timer.h> ! 51: #include <ipxe/netdevice.h> ! 52: #include <ipxe/pci.h> ! 53: #include <ipxe/pci_io.h> ! 54: ! 55: #include "base.h" ! 56: #include "reg.h" ! 57: ! 58: #define ATH5K_CALIB_INTERVAL 10 /* Calibrate PHY every 10 seconds */ ! 59: #define ATH5K_RETRIES 4 /* Number of times to retry packet sends */ ! 60: #define ATH5K_DESC_ALIGN 16 /* Alignment for TX/RX descriptors */ ! 61: ! 62: /******************\ ! 63: * Internal defines * ! 64: \******************/ ! 65: ! 66: /* Known PCI ids */ ! 67: static struct pci_device_id ath5k_nics[] = { ! 68: PCI_ROM(0x168c, 0x0207, "ath5210e", "Atheros 5210 early", AR5K_AR5210), ! 69: PCI_ROM(0x168c, 0x0007, "ath5210", "Atheros 5210", AR5K_AR5210), ! 70: PCI_ROM(0x168c, 0x0011, "ath5311", "Atheros 5311 (AHB)", AR5K_AR5211), ! 71: PCI_ROM(0x168c, 0x0012, "ath5211", "Atheros 5211", AR5K_AR5211), ! 72: PCI_ROM(0x168c, 0x0013, "ath5212", "Atheros 5212", AR5K_AR5212), ! 73: PCI_ROM(0xa727, 0x0013, "ath5212c","3com Ath 5212", AR5K_AR5212), ! 74: PCI_ROM(0x10b7, 0x0013, "rdag675", "3com 3CRDAG675", AR5K_AR5212), ! 75: PCI_ROM(0x168c, 0x1014, "ath5212m", "Ath 5212 miniPCI", AR5K_AR5212), ! 76: PCI_ROM(0x168c, 0x0014, "ath5212x14", "Atheros 5212 x14", AR5K_AR5212), ! 77: PCI_ROM(0x168c, 0x0015, "ath5212x15", "Atheros 5212 x15", AR5K_AR5212), ! 78: PCI_ROM(0x168c, 0x0016, "ath5212x16", "Atheros 5212 x16", AR5K_AR5212), ! 79: PCI_ROM(0x168c, 0x0017, "ath5212x17", "Atheros 5212 x17", AR5K_AR5212), ! 80: PCI_ROM(0x168c, 0x0018, "ath5212x18", "Atheros 5212 x18", AR5K_AR5212), ! 81: PCI_ROM(0x168c, 0x0019, "ath5212x19", "Atheros 5212 x19", AR5K_AR5212), ! 82: PCI_ROM(0x168c, 0x001a, "ath2413", "Atheros 2413 Griffin", AR5K_AR5212), ! 83: PCI_ROM(0x168c, 0x001b, "ath5413", "Atheros 5413 Eagle", AR5K_AR5212), ! 84: PCI_ROM(0x168c, 0x001c, "ath5212e", "Atheros 5212 PCI-E", AR5K_AR5212), ! 85: PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212), ! 86: }; ! 87: ! 88: /* Known SREVs */ ! 89: static const struct ath5k_srev_name srev_names[] = { ! 90: { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, ! 91: { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, ! 92: { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, ! 93: { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, ! 94: { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, ! 95: { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, ! 96: { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, ! 97: { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, ! 98: { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, ! 99: { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, ! 100: { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, ! 101: { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, ! 102: { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, ! 103: { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, ! 104: { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, ! 105: { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, ! 106: { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, ! 107: { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, ! 108: { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, ! 109: { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, ! 110: { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, ! 111: { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, ! 112: { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, ! 113: { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, ! 114: { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, ! 115: { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, ! 116: { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, ! 117: { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, ! 118: { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, ! 119: { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, ! 120: { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, ! 121: { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, ! 122: { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, ! 123: { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, ! 124: { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, ! 125: { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, ! 126: }; ! 127: ! 128: #define ATH5K_SPMBL_NO 1 ! 129: #define ATH5K_SPMBL_YES 2 ! 130: #define ATH5K_SPMBL_BOTH 3 ! 131: ! 132: static const struct { ! 133: u16 bitrate; ! 134: u8 short_pmbl; ! 135: u8 hw_code; ! 136: } ath5k_rates[] = { ! 137: { 10, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_1M }, ! 138: { 20, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_2M }, ! 139: { 55, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_5_5M }, ! 140: { 110, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_11M }, ! 141: { 60, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_6M }, ! 142: { 90, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_9M }, ! 143: { 120, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_12M }, ! 144: { 180, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_18M }, ! 145: { 240, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_24M }, ! 146: { 360, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_36M }, ! 147: { 480, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_48M }, ! 148: { 540, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_54M }, ! 149: { 20, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE }, ! 150: { 55, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE }, ! 151: { 110, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE }, ! 152: { 0, 0, 0 }, ! 153: }; ! 154: ! 155: #define ATH5K_NR_RATES 15 ! 156: ! 157: /* ! 158: * Prototypes - PCI stack related functions ! 159: */ ! 160: static int ath5k_probe(struct pci_device *pdev); ! 161: static void ath5k_remove(struct pci_device *pdev); ! 162: ! 163: struct pci_driver ath5k_pci_driver __pci_driver = { ! 164: .ids = ath5k_nics, ! 165: .id_count = sizeof(ath5k_nics) / sizeof(ath5k_nics[0]), ! 166: .probe = ath5k_probe, ! 167: .remove = ath5k_remove, ! 168: }; ! 169: ! 170: ! 171: ! 172: /* ! 173: * Prototypes - MAC 802.11 stack related functions ! 174: */ ! 175: static int ath5k_tx(struct net80211_device *dev, struct io_buffer *skb); ! 176: static int ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan); ! 177: static int ath5k_reset_wake(struct ath5k_softc *sc); ! 178: static int ath5k_start(struct net80211_device *dev); ! 179: static void ath5k_stop(struct net80211_device *dev); ! 180: static int ath5k_config(struct net80211_device *dev, int changed); ! 181: static void ath5k_poll(struct net80211_device *dev); ! 182: static void ath5k_irq(struct net80211_device *dev, int enable); ! 183: ! 184: static struct net80211_device_operations ath5k_ops = { ! 185: .open = ath5k_start, ! 186: .close = ath5k_stop, ! 187: .transmit = ath5k_tx, ! 188: .poll = ath5k_poll, ! 189: .irq = ath5k_irq, ! 190: .config = ath5k_config, ! 191: }; ! 192: ! 193: /* ! 194: * Prototypes - Internal functions ! 195: */ ! 196: /* Attach detach */ ! 197: static int ath5k_attach(struct net80211_device *dev); ! 198: static void ath5k_detach(struct net80211_device *dev); ! 199: /* Channel/mode setup */ ! 200: static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, ! 201: struct net80211_channel *channels, ! 202: unsigned int mode, ! 203: unsigned int max); ! 204: static int ath5k_setup_bands(struct net80211_device *dev); ! 205: static int ath5k_chan_set(struct ath5k_softc *sc, ! 206: struct net80211_channel *chan); ! 207: static void ath5k_setcurmode(struct ath5k_softc *sc, ! 208: unsigned int mode); ! 209: static void ath5k_mode_setup(struct ath5k_softc *sc); ! 210: ! 211: /* Descriptor setup */ ! 212: static int ath5k_desc_alloc(struct ath5k_softc *sc); ! 213: static void ath5k_desc_free(struct ath5k_softc *sc); ! 214: /* Buffers setup */ ! 215: static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf); ! 216: static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf); ! 217: ! 218: static inline void ath5k_txbuf_free(struct ath5k_softc *sc, ! 219: struct ath5k_buf *bf) ! 220: { ! 221: if (!bf->iob) ! 222: return; ! 223: ! 224: net80211_tx_complete(sc->dev, bf->iob, 0, ECANCELED); ! 225: bf->iob = NULL; ! 226: } ! 227: ! 228: static inline void ath5k_rxbuf_free(struct ath5k_softc *sc __unused, ! 229: struct ath5k_buf *bf) ! 230: { ! 231: free_iob(bf->iob); ! 232: bf->iob = NULL; ! 233: } ! 234: ! 235: /* Queues setup */ ! 236: static int ath5k_txq_setup(struct ath5k_softc *sc, ! 237: int qtype, int subtype); ! 238: static void ath5k_txq_drainq(struct ath5k_softc *sc, ! 239: struct ath5k_txq *txq); ! 240: static void ath5k_txq_cleanup(struct ath5k_softc *sc); ! 241: static void ath5k_txq_release(struct ath5k_softc *sc); ! 242: /* Rx handling */ ! 243: static int ath5k_rx_start(struct ath5k_softc *sc); ! 244: static void ath5k_rx_stop(struct ath5k_softc *sc); ! 245: /* Tx handling */ ! 246: static void ath5k_tx_processq(struct ath5k_softc *sc, ! 247: struct ath5k_txq *txq); ! 248: ! 249: /* Interrupt handling */ ! 250: static int ath5k_init(struct ath5k_softc *sc); ! 251: static int ath5k_stop_hw(struct ath5k_softc *sc); ! 252: ! 253: static void ath5k_calibrate(struct ath5k_softc *sc); ! 254: ! 255: /* Filter */ ! 256: static void ath5k_configure_filter(struct ath5k_softc *sc); ! 257: ! 258: /********************\ ! 259: * PCI Initialization * ! 260: \********************/ ! 261: ! 262: #if DBGLVL_MAX ! 263: static const char * ! 264: ath5k_chip_name(enum ath5k_srev_type type, u16 val) ! 265: { ! 266: const char *name = "xxxxx"; ! 267: unsigned int i; ! 268: ! 269: for (i = 0; i < ARRAY_SIZE(srev_names); i++) { ! 270: if (srev_names[i].sr_type != type) ! 271: continue; ! 272: ! 273: if ((val & 0xf0) == srev_names[i].sr_val) ! 274: name = srev_names[i].sr_name; ! 275: ! 276: if ((val & 0xff) == srev_names[i].sr_val) { ! 277: name = srev_names[i].sr_name; ! 278: break; ! 279: } ! 280: } ! 281: ! 282: return name; ! 283: } ! 284: #endif ! 285: ! 286: static int ath5k_probe(struct pci_device *pdev) ! 287: { ! 288: void *mem; ! 289: struct ath5k_softc *sc; ! 290: struct net80211_device *dev; ! 291: int ret; ! 292: u8 csz; ! 293: ! 294: adjust_pci_device(pdev); ! 295: ! 296: /* ! 297: * Cache line size is used to size and align various ! 298: * structures used to communicate with the hardware. ! 299: */ ! 300: pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); ! 301: if (csz == 0) { ! 302: /* ! 303: * We must have this setup properly for rx buffer ! 304: * DMA to work so force a reasonable value here if it ! 305: * comes up zero. ! 306: */ ! 307: csz = 16; ! 308: pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); ! 309: } ! 310: /* ! 311: * The default setting of latency timer yields poor results, ! 312: * set it to the value used by other systems. It may be worth ! 313: * tweaking this setting more. ! 314: */ ! 315: pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); ! 316: ! 317: /* ! 318: * Disable the RETRY_TIMEOUT register (0x41) to keep ! 319: * PCI Tx retries from interfering with C3 CPU state. ! 320: */ ! 321: pci_write_config_byte(pdev, 0x41, 0); ! 322: ! 323: mem = ioremap(pdev->membase, 0x10000); ! 324: if (!mem) { ! 325: DBG("ath5k: cannot remap PCI memory region\n"); ! 326: ret = -EIO; ! 327: goto err; ! 328: } ! 329: ! 330: /* ! 331: * Allocate dev (net80211 main struct) ! 332: * and dev->priv (driver private data) ! 333: */ ! 334: dev = net80211_alloc(sizeof(*sc)); ! 335: if (!dev) { ! 336: DBG("ath5k: cannot allocate 802.11 device\n"); ! 337: ret = -ENOMEM; ! 338: goto err_map; ! 339: } ! 340: ! 341: /* Initialize driver private data */ ! 342: sc = dev->priv; ! 343: sc->dev = dev; ! 344: sc->pdev = pdev; ! 345: ! 346: sc->hwinfo = zalloc(sizeof(*sc->hwinfo)); ! 347: if (!sc->hwinfo) { ! 348: DBG("ath5k: cannot allocate 802.11 hardware info structure\n"); ! 349: ret = -ENOMEM; ! 350: goto err_free; ! 351: } ! 352: ! 353: sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS; ! 354: sc->hwinfo->signal_type = NET80211_SIGNAL_DB; ! 355: sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */ ! 356: sc->hwinfo->channel_change_time = 5000; ! 357: ! 358: /* Avoid working with the device until setup is complete */ ! 359: sc->status |= ATH_STAT_INVALID; ! 360: ! 361: sc->iobase = mem; ! 362: sc->cachelsz = csz * 4; /* convert to bytes */ ! 363: ! 364: DBG("ath5k: register base at %p (%08lx)\n", sc->iobase, pdev->membase); ! 365: DBG("ath5k: cache line size %d\n", sc->cachelsz); ! 366: ! 367: /* Set private data */ ! 368: pci_set_drvdata(pdev, dev); ! 369: dev->netdev->dev = (struct device *)pdev; ! 370: ! 371: /* Initialize device */ ! 372: ret = ath5k_hw_attach(sc, pdev->id->driver_data, &sc->ah); ! 373: if (ret) ! 374: goto err_free_hwinfo; ! 375: ! 376: /* Finish private driver data initialization */ ! 377: ret = ath5k_attach(dev); ! 378: if (ret) ! 379: goto err_ah; ! 380: ! 381: #if DBGLVL_MAX ! 382: DBG("Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", ! 383: ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), ! 384: sc->ah->ah_mac_srev, sc->ah->ah_phy_revision); ! 385: ! 386: if (!sc->ah->ah_single_chip) { ! 387: /* Single chip radio (!RF5111) */ ! 388: if (sc->ah->ah_radio_5ghz_revision && ! 389: !sc->ah->ah_radio_2ghz_revision) { ! 390: /* No 5GHz support -> report 2GHz radio */ ! 391: if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A)) { ! 392: DBG("RF%s 2GHz radio found (0x%x)\n", ! 393: ath5k_chip_name(AR5K_VERSION_RAD, ! 394: sc->ah->ah_radio_5ghz_revision), ! 395: sc->ah->ah_radio_5ghz_revision); ! 396: /* No 2GHz support (5110 and some ! 397: * 5Ghz only cards) -> report 5Ghz radio */ ! 398: } else if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B)) { ! 399: DBG("RF%s 5GHz radio found (0x%x)\n", ! 400: ath5k_chip_name(AR5K_VERSION_RAD, ! 401: sc->ah->ah_radio_5ghz_revision), ! 402: sc->ah->ah_radio_5ghz_revision); ! 403: /* Multiband radio */ ! 404: } else { ! 405: DBG("RF%s multiband radio found (0x%x)\n", ! 406: ath5k_chip_name(AR5K_VERSION_RAD, ! 407: sc->ah->ah_radio_5ghz_revision), ! 408: sc->ah->ah_radio_5ghz_revision); ! 409: } ! 410: } ! 411: /* Multi chip radio (RF5111 - RF2111) -> ! 412: * report both 2GHz/5GHz radios */ ! 413: else if (sc->ah->ah_radio_5ghz_revision && ! 414: sc->ah->ah_radio_2ghz_revision) { ! 415: DBG("RF%s 5GHz radio found (0x%x)\n", ! 416: ath5k_chip_name(AR5K_VERSION_RAD, ! 417: sc->ah->ah_radio_5ghz_revision), ! 418: sc->ah->ah_radio_5ghz_revision); ! 419: DBG("RF%s 2GHz radio found (0x%x)\n", ! 420: ath5k_chip_name(AR5K_VERSION_RAD, ! 421: sc->ah->ah_radio_2ghz_revision), ! 422: sc->ah->ah_radio_2ghz_revision); ! 423: } ! 424: } ! 425: #endif ! 426: ! 427: /* Ready to go */ ! 428: sc->status &= ~ATH_STAT_INVALID; ! 429: ! 430: return 0; ! 431: err_ah: ! 432: ath5k_hw_detach(sc->ah); ! 433: err_free_hwinfo: ! 434: free(sc->hwinfo); ! 435: err_free: ! 436: net80211_free(dev); ! 437: err_map: ! 438: iounmap(mem); ! 439: err: ! 440: return ret; ! 441: } ! 442: ! 443: static void ath5k_remove(struct pci_device *pdev) ! 444: { ! 445: struct net80211_device *dev = pci_get_drvdata(pdev); ! 446: struct ath5k_softc *sc = dev->priv; ! 447: ! 448: ath5k_detach(dev); ! 449: ath5k_hw_detach(sc->ah); ! 450: iounmap(sc->iobase); ! 451: free(sc->hwinfo); ! 452: net80211_free(dev); ! 453: } ! 454: ! 455: ! 456: /***********************\ ! 457: * Driver Initialization * ! 458: \***********************/ ! 459: ! 460: static int ! 461: ath5k_attach(struct net80211_device *dev) ! 462: { ! 463: struct ath5k_softc *sc = dev->priv; ! 464: struct ath5k_hw *ah = sc->ah; ! 465: int ret; ! 466: ! 467: /* ! 468: * Collect the channel list. The 802.11 layer ! 469: * is resposible for filtering this list based ! 470: * on settings like the phy mode and regulatory ! 471: * domain restrictions. ! 472: */ ! 473: ret = ath5k_setup_bands(dev); ! 474: if (ret) { ! 475: DBG("ath5k: can't get channels\n"); ! 476: goto err; ! 477: } ! 478: ! 479: /* NB: setup here so ath5k_rate_update is happy */ ! 480: if (ah->ah_modes & AR5K_MODE_BIT_11A) ! 481: ath5k_setcurmode(sc, AR5K_MODE_11A); ! 482: else ! 483: ath5k_setcurmode(sc, AR5K_MODE_11B); ! 484: ! 485: /* ! 486: * Allocate tx+rx descriptors and populate the lists. ! 487: */ ! 488: ret = ath5k_desc_alloc(sc); ! 489: if (ret) { ! 490: DBG("ath5k: can't allocate descriptors\n"); ! 491: goto err; ! 492: } ! 493: ! 494: /* ! 495: * Allocate hardware transmit queues. Note that hw functions ! 496: * handle reseting these queues at the needed time. ! 497: */ ! 498: ret = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); ! 499: if (ret) { ! 500: DBG("ath5k: can't setup xmit queue\n"); ! 501: goto err_desc; ! 502: } ! 503: ! 504: sc->last_calib_ticks = currticks(); ! 505: ! 506: ret = ath5k_eeprom_read_mac(ah, sc->hwinfo->hwaddr); ! 507: if (ret) { ! 508: DBG("ath5k: unable to read address from EEPROM: 0x%04x\n", ! 509: sc->pdev->device); ! 510: goto err_queues; ! 511: } ! 512: ! 513: memset(sc->bssidmask, 0xff, ETH_ALEN); ! 514: ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); ! 515: ! 516: ret = net80211_register(sc->dev, &ath5k_ops, sc->hwinfo); ! 517: if (ret) { ! 518: DBG("ath5k: can't register ieee80211 hw\n"); ! 519: goto err_queues; ! 520: } ! 521: ! 522: return 0; ! 523: err_queues: ! 524: ath5k_txq_release(sc); ! 525: err_desc: ! 526: ath5k_desc_free(sc); ! 527: err: ! 528: return ret; ! 529: } ! 530: ! 531: static void ! 532: ath5k_detach(struct net80211_device *dev) ! 533: { ! 534: struct ath5k_softc *sc = dev->priv; ! 535: ! 536: net80211_unregister(dev); ! 537: ath5k_desc_free(sc); ! 538: ath5k_txq_release(sc); ! 539: } ! 540: ! 541: ! 542: ! 543: ! 544: /********************\ ! 545: * Channel/mode setup * ! 546: \********************/ ! 547: ! 548: /* ! 549: * Convert IEEE channel number to MHz frequency. ! 550: */ ! 551: static inline short ! 552: ath5k_ieee2mhz(short chan) ! 553: { ! 554: if (chan < 14) ! 555: return 2407 + 5 * chan; ! 556: if (chan == 14) ! 557: return 2484; ! 558: if (chan < 27) ! 559: return 2212 + 20 * chan; ! 560: return 5000 + 5 * chan; ! 561: } ! 562: ! 563: static unsigned int ! 564: ath5k_copy_channels(struct ath5k_hw *ah, ! 565: struct net80211_channel *channels, ! 566: unsigned int mode, unsigned int max) ! 567: { ! 568: unsigned int i, count, size, chfreq, freq, ch; ! 569: ! 570: if (!(ah->ah_modes & (1 << mode))) ! 571: return 0; ! 572: ! 573: switch (mode) { ! 574: case AR5K_MODE_11A: ! 575: case AR5K_MODE_11A_TURBO: ! 576: /* 1..220, but 2GHz frequencies are filtered by check_channel */ ! 577: size = 220; ! 578: chfreq = CHANNEL_5GHZ; ! 579: break; ! 580: case AR5K_MODE_11B: ! 581: case AR5K_MODE_11G: ! 582: case AR5K_MODE_11G_TURBO: ! 583: size = 26; ! 584: chfreq = CHANNEL_2GHZ; ! 585: break; ! 586: default: ! 587: return 0; ! 588: } ! 589: ! 590: for (i = 0, count = 0; i < size && max > 0; i++) { ! 591: ch = i + 1 ; ! 592: freq = ath5k_ieee2mhz(ch); ! 593: ! 594: /* Check if channel is supported by the chipset */ ! 595: if (!ath5k_channel_ok(ah, freq, chfreq)) ! 596: continue; ! 597: ! 598: /* Write channel info and increment counter */ ! 599: channels[count].center_freq = freq; ! 600: channels[count].maxpower = 0; /* use regulatory */ ! 601: channels[count].band = (chfreq == CHANNEL_2GHZ) ? ! 602: NET80211_BAND_2GHZ : NET80211_BAND_5GHZ; ! 603: switch (mode) { ! 604: case AR5K_MODE_11A: ! 605: case AR5K_MODE_11G: ! 606: channels[count].hw_value = chfreq | CHANNEL_OFDM; ! 607: break; ! 608: case AR5K_MODE_11A_TURBO: ! 609: case AR5K_MODE_11G_TURBO: ! 610: channels[count].hw_value = chfreq | ! 611: CHANNEL_OFDM | CHANNEL_TURBO; ! 612: break; ! 613: case AR5K_MODE_11B: ! 614: channels[count].hw_value = CHANNEL_B; ! 615: } ! 616: ! 617: count++; ! 618: max--; ! 619: } ! 620: ! 621: return count; ! 622: } ! 623: ! 624: static int ! 625: ath5k_setup_bands(struct net80211_device *dev) ! 626: { ! 627: struct ath5k_softc *sc = dev->priv; ! 628: struct ath5k_hw *ah = sc->ah; ! 629: int max_c, count_c = 0; ! 630: int i; ! 631: int band; ! 632: ! 633: max_c = sizeof(sc->hwinfo->channels) / sizeof(sc->hwinfo->channels[0]); ! 634: ! 635: /* 2GHz band */ ! 636: if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11G) { ! 637: /* G mode */ ! 638: band = NET80211_BAND_2GHZ; ! 639: sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ; ! 640: sc->hwinfo->modes = (NET80211_MODE_G | NET80211_MODE_B); ! 641: ! 642: for (i = 0; i < 12; i++) ! 643: sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate; ! 644: sc->hwinfo->nr_rates[band] = 12; ! 645: ! 646: sc->hwinfo->nr_channels = ! 647: ath5k_copy_channels(ah, sc->hwinfo->channels, ! 648: AR5K_MODE_11G, max_c); ! 649: count_c = sc->hwinfo->nr_channels; ! 650: max_c -= count_c; ! 651: } else if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B) { ! 652: /* B mode */ ! 653: band = NET80211_BAND_2GHZ; ! 654: sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ; ! 655: sc->hwinfo->modes = NET80211_MODE_B; ! 656: ! 657: for (i = 0; i < 4; i++) ! 658: sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate; ! 659: sc->hwinfo->nr_rates[band] = 4; ! 660: ! 661: sc->hwinfo->nr_channels = ! 662: ath5k_copy_channels(ah, sc->hwinfo->channels, ! 663: AR5K_MODE_11B, max_c); ! 664: count_c = sc->hwinfo->nr_channels; ! 665: max_c -= count_c; ! 666: } ! 667: ! 668: /* 5GHz band, A mode */ ! 669: if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A) { ! 670: band = NET80211_BAND_5GHZ; ! 671: sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ; ! 672: sc->hwinfo->modes |= NET80211_MODE_A; ! 673: ! 674: for (i = 0; i < 8; i++) ! 675: sc->hwinfo->rates[band][i] = ath5k_rates[i+4].bitrate; ! 676: sc->hwinfo->nr_rates[band] = 8; ! 677: ! 678: sc->hwinfo->nr_channels = ! 679: ath5k_copy_channels(ah, sc->hwinfo->channels, ! 680: AR5K_MODE_11B, max_c); ! 681: count_c = sc->hwinfo->nr_channels; ! 682: max_c -= count_c; ! 683: } ! 684: ! 685: return 0; ! 686: } ! 687: ! 688: /* ! 689: * Set/change channels. If the channel is really being changed, ! 690: * it's done by reseting the chip. To accomplish this we must ! 691: * first cleanup any pending DMA, then restart stuff after a la ! 692: * ath5k_init. ! 693: */ ! 694: static int ! 695: ath5k_chan_set(struct ath5k_softc *sc, struct net80211_channel *chan) ! 696: { ! 697: if (chan->center_freq != sc->curchan->center_freq || ! 698: chan->hw_value != sc->curchan->hw_value) { ! 699: /* ! 700: * To switch channels clear any pending DMA operations; ! 701: * wait long enough for the RX fifo to drain, reset the ! 702: * hardware at the new frequency, and then re-enable ! 703: * the relevant bits of the h/w. ! 704: */ ! 705: DBG2("ath5k: resetting for channel change (%d -> %d MHz)\n", ! 706: sc->curchan->center_freq, chan->center_freq); ! 707: return ath5k_reset(sc, chan); ! 708: } ! 709: ! 710: return 0; ! 711: } ! 712: ! 713: static void ! 714: ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) ! 715: { ! 716: sc->curmode = mode; ! 717: ! 718: if (mode == AR5K_MODE_11A) { ! 719: sc->curband = NET80211_BAND_5GHZ; ! 720: } else { ! 721: sc->curband = NET80211_BAND_2GHZ; ! 722: } ! 723: } ! 724: ! 725: static void ! 726: ath5k_mode_setup(struct ath5k_softc *sc) ! 727: { ! 728: struct ath5k_hw *ah = sc->ah; ! 729: u32 rfilt; ! 730: ! 731: /* configure rx filter */ ! 732: rfilt = sc->filter_flags; ! 733: ath5k_hw_set_rx_filter(ah, rfilt); ! 734: ! 735: if (ath5k_hw_hasbssidmask(ah)) ! 736: ath5k_hw_set_bssid_mask(ah, sc->bssidmask); ! 737: ! 738: /* configure operational mode */ ! 739: ath5k_hw_set_opmode(ah); ! 740: ! 741: ath5k_hw_set_mcast_filter(ah, 0, 0); ! 742: } ! 743: ! 744: static inline int ! 745: ath5k_hw_rix_to_bitrate(int hw_rix) ! 746: { ! 747: int i; ! 748: ! 749: for (i = 0; i < ATH5K_NR_RATES; i++) { ! 750: if (ath5k_rates[i].hw_code == hw_rix) ! 751: return ath5k_rates[i].bitrate; ! 752: } ! 753: ! 754: DBG("ath5k: invalid rix %02x\n", hw_rix); ! 755: return 10; /* use lowest rate */ ! 756: } ! 757: ! 758: int ath5k_bitrate_to_hw_rix(int bitrate) ! 759: { ! 760: int i; ! 761: ! 762: for (i = 0; i < ATH5K_NR_RATES; i++) { ! 763: if (ath5k_rates[i].bitrate == bitrate) ! 764: return ath5k_rates[i].hw_code; ! 765: } ! 766: ! 767: DBG("ath5k: invalid bitrate %d\n", bitrate); ! 768: return ATH5K_RATE_CODE_1M; /* use lowest rate */ ! 769: } ! 770: ! 771: /***************\ ! 772: * Buffers setup * ! 773: \***************/ ! 774: ! 775: static struct io_buffer * ! 776: ath5k_rx_iob_alloc(struct ath5k_softc *sc, u32 *iob_addr) ! 777: { ! 778: struct io_buffer *iob; ! 779: unsigned int off; ! 780: ! 781: /* ! 782: * Allocate buffer with headroom_needed space for the ! 783: * fake physical layer header at the start. ! 784: */ ! 785: iob = alloc_iob(sc->rxbufsize + sc->cachelsz - 1); ! 786: ! 787: if (!iob) { ! 788: DBG("ath5k: can't alloc iobuf of size %d\n", ! 789: sc->rxbufsize + sc->cachelsz - 1); ! 790: return NULL; ! 791: } ! 792: ! 793: *iob_addr = virt_to_bus(iob->data); ! 794: ! 795: /* ! 796: * Cache-line-align. This is important (for the ! 797: * 5210 at least) as not doing so causes bogus data ! 798: * in rx'd frames. ! 799: */ ! 800: off = *iob_addr % sc->cachelsz; ! 801: if (off != 0) { ! 802: iob_reserve(iob, sc->cachelsz - off); ! 803: *iob_addr += sc->cachelsz - off; ! 804: } ! 805: ! 806: return iob; ! 807: } ! 808: ! 809: static int ! 810: ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ! 811: { ! 812: struct ath5k_hw *ah = sc->ah; ! 813: struct io_buffer *iob = bf->iob; ! 814: struct ath5k_desc *ds; ! 815: ! 816: if (!iob) { ! 817: iob = ath5k_rx_iob_alloc(sc, &bf->iobaddr); ! 818: if (!iob) ! 819: return -ENOMEM; ! 820: bf->iob = iob; ! 821: } ! 822: ! 823: /* ! 824: * Setup descriptors. For receive we always terminate ! 825: * the descriptor list with a self-linked entry so we'll ! 826: * not get overrun under high load (as can happen with a ! 827: * 5212 when ANI processing enables PHY error frames). ! 828: * ! 829: * To insure the last descriptor is self-linked we create ! 830: * each descriptor as self-linked and add it to the end. As ! 831: * each additional descriptor is added the previous self-linked ! 832: * entry is ``fixed'' naturally. This should be safe even ! 833: * if DMA is happening. When processing RX interrupts we ! 834: * never remove/process the last, self-linked, entry on the ! 835: * descriptor list. This insures the hardware always has ! 836: * someplace to write a new frame. ! 837: */ ! 838: ds = bf->desc; ! 839: ds->ds_link = bf->daddr; /* link to self */ ! 840: ds->ds_data = bf->iobaddr; ! 841: if (ah->ah_setup_rx_desc(ah, ds, ! 842: iob_tailroom(iob), /* buffer size */ ! 843: 0) != 0) { ! 844: DBG("ath5k: error setting up RX descriptor for %zd bytes\n", iob_tailroom(iob)); ! 845: return -EINVAL; ! 846: } ! 847: ! 848: if (sc->rxlink != NULL) ! 849: *sc->rxlink = bf->daddr; ! 850: sc->rxlink = &ds->ds_link; ! 851: return 0; ! 852: } ! 853: ! 854: static int ! 855: ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ! 856: { ! 857: struct ath5k_hw *ah = sc->ah; ! 858: struct ath5k_txq *txq = &sc->txq; ! 859: struct ath5k_desc *ds = bf->desc; ! 860: struct io_buffer *iob = bf->iob; ! 861: unsigned int pktlen, flags; ! 862: int ret; ! 863: u16 duration = 0; ! 864: u16 cts_rate = 0; ! 865: ! 866: flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; ! 867: bf->iobaddr = virt_to_bus(iob->data); ! 868: pktlen = iob_len(iob); ! 869: ! 870: /* FIXME: If we are in g mode and rate is a CCK rate ! 871: * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta ! 872: * from tx power (value is in dB units already) */ ! 873: if (sc->dev->phy_flags & NET80211_PHY_USE_PROTECTION) { ! 874: struct net80211_device *dev = sc->dev; ! 875: ! 876: flags |= AR5K_TXDESC_CTSENA; ! 877: cts_rate = sc->hw_rtscts_rate; ! 878: duration = net80211_cts_duration(dev, pktlen); ! 879: } ! 880: ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ! 881: IEEE80211_TYP_FRAME_HEADER_LEN, ! 882: AR5K_PKT_TYPE_NORMAL, sc->power_level * 2, ! 883: sc->hw_rate, ATH5K_RETRIES, ! 884: AR5K_TXKEYIX_INVALID, 0, flags, ! 885: cts_rate, duration); ! 886: if (ret) ! 887: return ret; ! 888: ! 889: ds->ds_link = 0; ! 890: ds->ds_data = bf->iobaddr; ! 891: ! 892: list_add_tail(&bf->list, &txq->q); ! 893: if (txq->link == NULL) /* is this first packet? */ ! 894: ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); ! 895: else /* no, so only link it */ ! 896: *txq->link = bf->daddr; ! 897: ! 898: txq->link = &ds->ds_link; ! 899: ath5k_hw_start_tx_dma(ah, txq->qnum); ! 900: mb(); ! 901: ! 902: return 0; ! 903: } ! 904: ! 905: /*******************\ ! 906: * Descriptors setup * ! 907: \*******************/ ! 908: ! 909: static int ! 910: ath5k_desc_alloc(struct ath5k_softc *sc) ! 911: { ! 912: struct ath5k_desc *ds; ! 913: struct ath5k_buf *bf; ! 914: u32 da; ! 915: unsigned int i; ! 916: int ret; ! 917: ! 918: /* allocate descriptors */ ! 919: sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + 1); ! 920: sc->desc = malloc_dma(sc->desc_len, ATH5K_DESC_ALIGN); ! 921: if (sc->desc == NULL) { ! 922: DBG("ath5k: can't allocate descriptors\n"); ! 923: ret = -ENOMEM; ! 924: goto err; ! 925: } ! 926: memset(sc->desc, 0, sc->desc_len); ! 927: sc->desc_daddr = virt_to_bus(sc->desc); ! 928: ! 929: ds = sc->desc; ! 930: da = sc->desc_daddr; ! 931: ! 932: bf = calloc(ATH_TXBUF + ATH_RXBUF + 1, sizeof(struct ath5k_buf)); ! 933: if (bf == NULL) { ! 934: DBG("ath5k: can't allocate buffer pointers\n"); ! 935: ret = -ENOMEM; ! 936: goto err_free; ! 937: } ! 938: sc->bufptr = bf; ! 939: ! 940: INIT_LIST_HEAD(&sc->rxbuf); ! 941: for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { ! 942: bf->desc = ds; ! 943: bf->daddr = da; ! 944: list_add_tail(&bf->list, &sc->rxbuf); ! 945: } ! 946: ! 947: INIT_LIST_HEAD(&sc->txbuf); ! 948: sc->txbuf_len = ATH_TXBUF; ! 949: for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) { ! 950: bf->desc = ds; ! 951: bf->daddr = da; ! 952: list_add_tail(&bf->list, &sc->txbuf); ! 953: } ! 954: ! 955: return 0; ! 956: ! 957: err_free: ! 958: free_dma(sc->desc, sc->desc_len); ! 959: err: ! 960: sc->desc = NULL; ! 961: return ret; ! 962: } ! 963: ! 964: static void ! 965: ath5k_desc_free(struct ath5k_softc *sc) ! 966: { ! 967: struct ath5k_buf *bf; ! 968: ! 969: list_for_each_entry(bf, &sc->txbuf, list) ! 970: ath5k_txbuf_free(sc, bf); ! 971: list_for_each_entry(bf, &sc->rxbuf, list) ! 972: ath5k_rxbuf_free(sc, bf); ! 973: ! 974: /* Free memory associated with all descriptors */ ! 975: free_dma(sc->desc, sc->desc_len); ! 976: ! 977: free(sc->bufptr); ! 978: sc->bufptr = NULL; ! 979: } ! 980: ! 981: ! 982: ! 983: ! 984: ! 985: /**************\ ! 986: * Queues setup * ! 987: \**************/ ! 988: ! 989: static int ! 990: ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype) ! 991: { ! 992: struct ath5k_hw *ah = sc->ah; ! 993: struct ath5k_txq *txq; ! 994: struct ath5k_txq_info qi = { ! 995: .tqi_subtype = subtype, ! 996: .tqi_aifs = AR5K_TXQ_USEDEFAULT, ! 997: .tqi_cw_min = AR5K_TXQ_USEDEFAULT, ! 998: .tqi_cw_max = AR5K_TXQ_USEDEFAULT ! 999: }; ! 1000: int qnum; ! 1001: ! 1002: /* ! 1003: * Enable interrupts only for EOL and DESC conditions. ! 1004: * We mark tx descriptors to receive a DESC interrupt ! 1005: * when a tx queue gets deep; otherwise waiting for the ! 1006: * EOL to reap descriptors. Note that this is done to ! 1007: * reduce interrupt load and this only defers reaping ! 1008: * descriptors, never transmitting frames. Aside from ! 1009: * reducing interrupts this also permits more concurrency. ! 1010: * The only potential downside is if the tx queue backs ! 1011: * up in which case the top half of the kernel may backup ! 1012: * due to a lack of tx descriptors. ! 1013: */ ! 1014: qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE | ! 1015: AR5K_TXQ_FLAG_TXDESCINT_ENABLE; ! 1016: qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi); ! 1017: if (qnum < 0) { ! 1018: DBG("ath5k: can't set up a TX queue\n"); ! 1019: return -EIO; ! 1020: } ! 1021: ! 1022: txq = &sc->txq; ! 1023: if (!txq->setup) { ! 1024: txq->qnum = qnum; ! 1025: txq->link = NULL; ! 1026: INIT_LIST_HEAD(&txq->q); ! 1027: txq->setup = 1; ! 1028: } ! 1029: return 0; ! 1030: } ! 1031: ! 1032: static void ! 1033: ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) ! 1034: { ! 1035: struct ath5k_buf *bf, *bf0; ! 1036: ! 1037: list_for_each_entry_safe(bf, bf0, &txq->q, list) { ! 1038: ath5k_txbuf_free(sc, bf); ! 1039: ! 1040: list_del(&bf->list); ! 1041: list_add_tail(&bf->list, &sc->txbuf); ! 1042: sc->txbuf_len++; ! 1043: } ! 1044: txq->link = NULL; ! 1045: } ! 1046: ! 1047: /* ! 1048: * Drain the transmit queues and reclaim resources. ! 1049: */ ! 1050: static void ! 1051: ath5k_txq_cleanup(struct ath5k_softc *sc) ! 1052: { ! 1053: struct ath5k_hw *ah = sc->ah; ! 1054: ! 1055: if (!(sc->status & ATH_STAT_INVALID)) { ! 1056: /* don't touch the hardware if marked invalid */ ! 1057: if (sc->txq.setup) { ! 1058: ath5k_hw_stop_tx_dma(ah, sc->txq.qnum); ! 1059: DBG("ath5k: txq [%d] %x, link %p\n", ! 1060: sc->txq.qnum, ! 1061: ath5k_hw_get_txdp(ah, sc->txq.qnum), ! 1062: sc->txq.link); ! 1063: } ! 1064: } ! 1065: ! 1066: if (sc->txq.setup) ! 1067: ath5k_txq_drainq(sc, &sc->txq); ! 1068: } ! 1069: ! 1070: static void ! 1071: ath5k_txq_release(struct ath5k_softc *sc) ! 1072: { ! 1073: if (sc->txq.setup) { ! 1074: ath5k_hw_release_tx_queue(sc->ah); ! 1075: sc->txq.setup = 0; ! 1076: } ! 1077: } ! 1078: ! 1079: ! 1080: ! 1081: ! 1082: /*************\ ! 1083: * RX Handling * ! 1084: \*************/ ! 1085: ! 1086: /* ! 1087: * Enable the receive h/w following a reset. ! 1088: */ ! 1089: static int ! 1090: ath5k_rx_start(struct ath5k_softc *sc) ! 1091: { ! 1092: struct ath5k_hw *ah = sc->ah; ! 1093: struct ath5k_buf *bf; ! 1094: int ret; ! 1095: ! 1096: sc->rxbufsize = IEEE80211_MAX_LEN; ! 1097: if (sc->rxbufsize % sc->cachelsz != 0) ! 1098: sc->rxbufsize += sc->cachelsz - (sc->rxbufsize % sc->cachelsz); ! 1099: ! 1100: sc->rxlink = NULL; ! 1101: ! 1102: list_for_each_entry(bf, &sc->rxbuf, list) { ! 1103: ret = ath5k_rxbuf_setup(sc, bf); ! 1104: if (ret != 0) ! 1105: return ret; ! 1106: } ! 1107: ! 1108: bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list); ! 1109: ! 1110: ath5k_hw_set_rxdp(ah, bf->daddr); ! 1111: ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ ! 1112: ath5k_mode_setup(sc); /* set filters, etc. */ ! 1113: ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ ! 1114: ! 1115: return 0; ! 1116: } ! 1117: ! 1118: /* ! 1119: * Disable the receive h/w in preparation for a reset. ! 1120: */ ! 1121: static void ! 1122: ath5k_rx_stop(struct ath5k_softc *sc) ! 1123: { ! 1124: struct ath5k_hw *ah = sc->ah; ! 1125: ! 1126: ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ! 1127: ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ ! 1128: ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ ! 1129: ! 1130: sc->rxlink = NULL; /* just in case */ ! 1131: } ! 1132: ! 1133: static void ! 1134: ath5k_handle_rx(struct ath5k_softc *sc) ! 1135: { ! 1136: struct ath5k_rx_status rs; ! 1137: struct io_buffer *iob, *next_iob; ! 1138: u32 next_iob_addr; ! 1139: struct ath5k_buf *bf, *bf_last; ! 1140: struct ath5k_desc *ds; ! 1141: int ret; ! 1142: ! 1143: memset(&rs, 0, sizeof(rs)); ! 1144: ! 1145: if (list_empty(&sc->rxbuf)) { ! 1146: DBG("ath5k: empty rx buf pool\n"); ! 1147: return; ! 1148: } ! 1149: ! 1150: bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); ! 1151: ! 1152: do { ! 1153: bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list); ! 1154: assert(bf->iob != NULL); ! 1155: iob = bf->iob; ! 1156: ds = bf->desc; ! 1157: ! 1158: /* ! 1159: * last buffer must not be freed to ensure proper hardware ! 1160: * function. When the hardware finishes also a packet next to ! 1161: * it, we are sure, it doesn't use it anymore and we can go on. ! 1162: */ ! 1163: if (bf_last == bf) ! 1164: bf->flags |= 1; ! 1165: if (bf->flags) { ! 1166: struct ath5k_buf *bf_next = list_entry(bf->list.next, ! 1167: struct ath5k_buf, list); ! 1168: ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, ! 1169: &rs); ! 1170: if (ret) ! 1171: break; ! 1172: bf->flags &= ~1; ! 1173: /* skip the overwritten one (even status is martian) */ ! 1174: goto next; ! 1175: } ! 1176: ! 1177: ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); ! 1178: if (ret) { ! 1179: if (ret != -EINPROGRESS) { ! 1180: DBG("ath5k: error in processing rx desc: %s\n", ! 1181: strerror(ret)); ! 1182: net80211_rx_err(sc->dev, NULL, -ret); ! 1183: } else { ! 1184: /* normal return, reached end of ! 1185: available descriptors */ ! 1186: } ! 1187: return; ! 1188: } ! 1189: ! 1190: if (rs.rs_more) { ! 1191: DBG("ath5k: unsupported fragmented rx\n"); ! 1192: goto next; ! 1193: } ! 1194: ! 1195: if (rs.rs_status) { ! 1196: if (rs.rs_status & AR5K_RXERR_PHY) { ! 1197: /* These are uncommon, and may indicate a real problem. */ ! 1198: net80211_rx_err(sc->dev, NULL, EIO); ! 1199: goto next; ! 1200: } ! 1201: if (rs.rs_status & AR5K_RXERR_CRC) { ! 1202: /* These occur *all the time*. */ ! 1203: goto next; ! 1204: } ! 1205: if (rs.rs_status & AR5K_RXERR_DECRYPT) { ! 1206: /* ! 1207: * Decrypt error. If the error occurred ! 1208: * because there was no hardware key, then ! 1209: * let the frame through so the upper layers ! 1210: * can process it. This is necessary for 5210 ! 1211: * parts which have no way to setup a ``clear'' ! 1212: * key cache entry. ! 1213: * ! 1214: * XXX do key cache faulting ! 1215: */ ! 1216: if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && ! 1217: !(rs.rs_status & AR5K_RXERR_CRC)) ! 1218: goto accept; ! 1219: } ! 1220: ! 1221: /* any other error, unhandled */ ! 1222: DBG("ath5k: packet rx status %x\n", rs.rs_status); ! 1223: goto next; ! 1224: } ! 1225: accept: ! 1226: next_iob = ath5k_rx_iob_alloc(sc, &next_iob_addr); ! 1227: ! 1228: /* ! 1229: * If we can't replace bf->iob with a new iob under memory ! 1230: * pressure, just skip this packet ! 1231: */ ! 1232: if (!next_iob) { ! 1233: DBG("ath5k: dropping packet under memory pressure\n"); ! 1234: goto next; ! 1235: } ! 1236: ! 1237: iob_put(iob, rs.rs_datalen); ! 1238: ! 1239: /* The MAC header is padded to have 32-bit boundary if the ! 1240: * packet payload is non-zero. However, iPXE only ! 1241: * supports standard 802.11 packets with 24-byte ! 1242: * header, so no padding correction should be needed. ! 1243: */ ! 1244: ! 1245: DBG2("ath5k: rx %d bytes, signal %d\n", rs.rs_datalen, ! 1246: rs.rs_rssi); ! 1247: ! 1248: net80211_rx(sc->dev, iob, rs.rs_rssi, ! 1249: ath5k_hw_rix_to_bitrate(rs.rs_rate)); ! 1250: ! 1251: bf->iob = next_iob; ! 1252: bf->iobaddr = next_iob_addr; ! 1253: next: ! 1254: list_del(&bf->list); ! 1255: list_add_tail(&bf->list, &sc->rxbuf); ! 1256: } while (ath5k_rxbuf_setup(sc, bf) == 0); ! 1257: } ! 1258: ! 1259: ! 1260: ! 1261: ! 1262: /*************\ ! 1263: * TX Handling * ! 1264: \*************/ ! 1265: ! 1266: static void ! 1267: ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) ! 1268: { ! 1269: struct ath5k_tx_status ts; ! 1270: struct ath5k_buf *bf, *bf0; ! 1271: struct ath5k_desc *ds; ! 1272: struct io_buffer *iob; ! 1273: int ret; ! 1274: ! 1275: memset(&ts, 0, sizeof(ts)); ! 1276: ! 1277: list_for_each_entry_safe(bf, bf0, &txq->q, list) { ! 1278: ds = bf->desc; ! 1279: ! 1280: ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); ! 1281: if (ret) { ! 1282: if (ret != -EINPROGRESS) { ! 1283: DBG("ath5k: error in processing tx desc: %s\n", ! 1284: strerror(ret)); ! 1285: } else { ! 1286: /* normal return, reached end of tx completions */ ! 1287: } ! 1288: break; ! 1289: } ! 1290: ! 1291: iob = bf->iob; ! 1292: bf->iob = NULL; ! 1293: ! 1294: DBG2("ath5k: tx %zd bytes complete, %d retries\n", ! 1295: iob_len(iob), ts.ts_retry[0]); ! 1296: ! 1297: net80211_tx_complete(sc->dev, iob, ts.ts_retry[0], ! 1298: ts.ts_status ? EIO : 0); ! 1299: ! 1300: list_del(&bf->list); ! 1301: list_add_tail(&bf->list, &sc->txbuf); ! 1302: sc->txbuf_len++; ! 1303: } ! 1304: ! 1305: if (list_empty(&txq->q)) ! 1306: txq->link = NULL; ! 1307: } ! 1308: ! 1309: static void ! 1310: ath5k_handle_tx(struct ath5k_softc *sc) ! 1311: { ! 1312: ath5k_tx_processq(sc, &sc->txq); ! 1313: } ! 1314: ! 1315: ! 1316: /********************\ ! 1317: * Interrupt handling * ! 1318: \********************/ ! 1319: ! 1320: static void ! 1321: ath5k_irq(struct net80211_device *dev, int enable) ! 1322: { ! 1323: struct ath5k_softc *sc = dev->priv; ! 1324: struct ath5k_hw *ah = sc->ah; ! 1325: ! 1326: sc->irq_ena = enable; ! 1327: ah->ah_ier = enable ? AR5K_IER_ENABLE : AR5K_IER_DISABLE; ! 1328: ! 1329: ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER); ! 1330: ath5k_hw_set_imr(ah, sc->imask); ! 1331: } ! 1332: ! 1333: static int ! 1334: ath5k_init(struct ath5k_softc *sc) ! 1335: { ! 1336: struct ath5k_hw *ah = sc->ah; ! 1337: int ret, i; ! 1338: ! 1339: /* ! 1340: * Stop anything previously setup. This is safe ! 1341: * no matter this is the first time through or not. ! 1342: */ ! 1343: ath5k_stop_hw(sc); ! 1344: ! 1345: /* ! 1346: * The basic interface to setting the hardware in a good ! 1347: * state is ``reset''. On return the hardware is known to ! 1348: * be powered up and with interrupts disabled. This must ! 1349: * be followed by initialization of the appropriate bits ! 1350: * and then setup of the interrupt mask. ! 1351: */ ! 1352: sc->curchan = sc->dev->channels + sc->dev->channel; ! 1353: sc->curband = sc->curchan->band; ! 1354: sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | ! 1355: AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | ! 1356: AR5K_INT_FATAL | AR5K_INT_GLOBAL; ! 1357: ret = ath5k_reset(sc, NULL); ! 1358: if (ret) ! 1359: goto done; ! 1360: ! 1361: ath5k_rfkill_hw_start(ah); ! 1362: ! 1363: /* ! 1364: * Reset the key cache since some parts do not reset the ! 1365: * contents on initial power up or resume from suspend. ! 1366: */ ! 1367: for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) ! 1368: ath5k_hw_reset_key(ah, i); ! 1369: ! 1370: /* Set ack to be sent at low bit-rates */ ! 1371: ath5k_hw_set_ack_bitrate_high(ah, 0); ! 1372: ! 1373: ret = 0; ! 1374: done: ! 1375: mb(); ! 1376: return ret; ! 1377: } ! 1378: ! 1379: static int ! 1380: ath5k_stop_hw(struct ath5k_softc *sc) ! 1381: { ! 1382: struct ath5k_hw *ah = sc->ah; ! 1383: ! 1384: /* ! 1385: * Shutdown the hardware and driver: ! 1386: * stop output from above ! 1387: * disable interrupts ! 1388: * turn off timers ! 1389: * turn off the radio ! 1390: * clear transmit machinery ! 1391: * clear receive machinery ! 1392: * drain and release tx queues ! 1393: * reclaim beacon resources ! 1394: * power down hardware ! 1395: * ! 1396: * Note that some of this work is not possible if the ! 1397: * hardware is gone (invalid). ! 1398: */ ! 1399: ! 1400: if (!(sc->status & ATH_STAT_INVALID)) { ! 1401: ath5k_hw_set_imr(ah, 0); ! 1402: } ! 1403: ath5k_txq_cleanup(sc); ! 1404: if (!(sc->status & ATH_STAT_INVALID)) { ! 1405: ath5k_rx_stop(sc); ! 1406: ath5k_hw_phy_disable(ah); ! 1407: } else ! 1408: sc->rxlink = NULL; ! 1409: ! 1410: ath5k_rfkill_hw_stop(sc->ah); ! 1411: ! 1412: return 0; ! 1413: } ! 1414: ! 1415: static void ! 1416: ath5k_poll(struct net80211_device *dev) ! 1417: { ! 1418: struct ath5k_softc *sc = dev->priv; ! 1419: struct ath5k_hw *ah = sc->ah; ! 1420: enum ath5k_int status; ! 1421: unsigned int counter = 1000; ! 1422: ! 1423: if (currticks() - sc->last_calib_ticks > ! 1424: ATH5K_CALIB_INTERVAL * ticks_per_sec()) { ! 1425: ath5k_calibrate(sc); ! 1426: sc->last_calib_ticks = currticks(); ! 1427: } ! 1428: ! 1429: if ((sc->status & ATH_STAT_INVALID) || ! 1430: (sc->irq_ena && !ath5k_hw_is_intr_pending(ah))) ! 1431: return; ! 1432: ! 1433: do { ! 1434: ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ ! 1435: DBGP("ath5k: status %#x/%#x\n", status, sc->imask); ! 1436: if (status & AR5K_INT_FATAL) { ! 1437: /* ! 1438: * Fatal errors are unrecoverable. ! 1439: * Typically these are caused by DMA errors. ! 1440: */ ! 1441: DBG("ath5k: fatal error, resetting\n"); ! 1442: ath5k_reset_wake(sc); ! 1443: } else if (status & AR5K_INT_RXORN) { ! 1444: DBG("ath5k: rx overrun, resetting\n"); ! 1445: ath5k_reset_wake(sc); ! 1446: } else { ! 1447: if (status & AR5K_INT_RXEOL) { ! 1448: /* ! 1449: * NB: the hardware should re-read the link when ! 1450: * RXE bit is written, but it doesn't work at ! 1451: * least on older hardware revs. ! 1452: */ ! 1453: DBG("ath5k: rx EOL\n"); ! 1454: sc->rxlink = NULL; ! 1455: } ! 1456: if (status & AR5K_INT_TXURN) { ! 1457: /* bump tx trigger level */ ! 1458: DBG("ath5k: tx underrun\n"); ! 1459: ath5k_hw_update_tx_triglevel(ah, 1); ! 1460: } ! 1461: if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) ! 1462: ath5k_handle_rx(sc); ! 1463: if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC ! 1464: | AR5K_INT_TXERR | AR5K_INT_TXEOL)) ! 1465: ath5k_handle_tx(sc); ! 1466: } ! 1467: } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); ! 1468: ! 1469: if (!counter) ! 1470: DBG("ath5k: too many interrupts, giving up for now\n"); ! 1471: } ! 1472: ! 1473: /* ! 1474: * Periodically recalibrate the PHY to account ! 1475: * for temperature/environment changes. ! 1476: */ ! 1477: static void ! 1478: ath5k_calibrate(struct ath5k_softc *sc) ! 1479: { ! 1480: struct ath5k_hw *ah = sc->ah; ! 1481: ! 1482: if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { ! 1483: /* ! 1484: * Rfgain is out of bounds, reset the chip ! 1485: * to load new gain values. ! 1486: */ ! 1487: DBG("ath5k: resetting for calibration\n"); ! 1488: ath5k_reset_wake(sc); ! 1489: } ! 1490: if (ath5k_hw_phy_calibrate(ah, sc->curchan)) ! 1491: DBG("ath5k: calibration of channel %d failed\n", ! 1492: sc->curchan->channel_nr); ! 1493: } ! 1494: ! 1495: ! 1496: /********************\ ! 1497: * Net80211 functions * ! 1498: \********************/ ! 1499: ! 1500: static int ! 1501: ath5k_tx(struct net80211_device *dev, struct io_buffer *iob) ! 1502: { ! 1503: struct ath5k_softc *sc = dev->priv; ! 1504: struct ath5k_buf *bf; ! 1505: int rc; ! 1506: ! 1507: /* ! 1508: * The hardware expects the header padded to 4 byte boundaries. ! 1509: * iPXE only ever sends 24-byte headers, so no action necessary. ! 1510: */ ! 1511: ! 1512: if (list_empty(&sc->txbuf)) { ! 1513: DBG("ath5k: dropping packet because no tx bufs available\n"); ! 1514: return -ENOBUFS; ! 1515: } ! 1516: ! 1517: bf = list_entry(sc->txbuf.next, struct ath5k_buf, list); ! 1518: list_del(&bf->list); ! 1519: sc->txbuf_len--; ! 1520: ! 1521: bf->iob = iob; ! 1522: ! 1523: if ((rc = ath5k_txbuf_setup(sc, bf)) != 0) { ! 1524: bf->iob = NULL; ! 1525: list_add_tail(&bf->list, &sc->txbuf); ! 1526: sc->txbuf_len++; ! 1527: return rc; ! 1528: } ! 1529: return 0; ! 1530: } ! 1531: ! 1532: /* ! 1533: * Reset the hardware. If chan is not NULL, then also pause rx/tx ! 1534: * and change to the given channel. ! 1535: */ ! 1536: static int ! 1537: ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan) ! 1538: { ! 1539: struct ath5k_hw *ah = sc->ah; ! 1540: int ret; ! 1541: ! 1542: if (chan) { ! 1543: ath5k_hw_set_imr(ah, 0); ! 1544: ath5k_txq_cleanup(sc); ! 1545: ath5k_rx_stop(sc); ! 1546: ! 1547: sc->curchan = chan; ! 1548: sc->curband = chan->band; ! 1549: } ! 1550: ! 1551: ret = ath5k_hw_reset(ah, sc->curchan, 1); ! 1552: if (ret) { ! 1553: DBG("ath5k: can't reset hardware: %s\n", strerror(ret)); ! 1554: return ret; ! 1555: } ! 1556: ! 1557: ret = ath5k_rx_start(sc); ! 1558: if (ret) { ! 1559: DBG("ath5k: can't start rx logic: %s\n", strerror(ret)); ! 1560: return ret; ! 1561: } ! 1562: ! 1563: /* ! 1564: * Change channels and update the h/w rate map if we're switching; ! 1565: * e.g. 11a to 11b/g. ! 1566: * ! 1567: * We may be doing a reset in response to an ioctl that changes the ! 1568: * channel so update any state that might change as a result. ! 1569: * ! 1570: * XXX needed? ! 1571: */ ! 1572: /* ath5k_chan_change(sc, c); */ ! 1573: ! 1574: /* Reenable interrupts if necessary */ ! 1575: ath5k_irq(sc->dev, sc->irq_ena); ! 1576: ! 1577: return 0; ! 1578: } ! 1579: ! 1580: static int ath5k_reset_wake(struct ath5k_softc *sc) ! 1581: { ! 1582: return ath5k_reset(sc, sc->curchan); ! 1583: } ! 1584: ! 1585: static int ath5k_start(struct net80211_device *dev) ! 1586: { ! 1587: struct ath5k_softc *sc = dev->priv; ! 1588: int ret; ! 1589: ! 1590: if ((ret = ath5k_init(sc)) != 0) ! 1591: return ret; ! 1592: ! 1593: sc->assoc = 0; ! 1594: ath5k_configure_filter(sc); ! 1595: ath5k_hw_set_lladdr(sc->ah, dev->netdev->ll_addr); ! 1596: ! 1597: return 0; ! 1598: } ! 1599: ! 1600: static void ath5k_stop(struct net80211_device *dev) ! 1601: { ! 1602: struct ath5k_softc *sc = dev->priv; ! 1603: u8 mac[ETH_ALEN] = {}; ! 1604: ! 1605: ath5k_hw_set_lladdr(sc->ah, mac); ! 1606: ! 1607: ath5k_stop_hw(sc); ! 1608: } ! 1609: ! 1610: static int ! 1611: ath5k_config(struct net80211_device *dev, int changed) ! 1612: { ! 1613: struct ath5k_softc *sc = dev->priv; ! 1614: struct ath5k_hw *ah = sc->ah; ! 1615: struct net80211_channel *chan = &dev->channels[dev->channel]; ! 1616: int ret; ! 1617: ! 1618: if (changed & NET80211_CFG_CHANNEL) { ! 1619: sc->power_level = chan->maxpower; ! 1620: if ((ret = ath5k_chan_set(sc, chan)) != 0) ! 1621: return ret; ! 1622: } ! 1623: ! 1624: if ((changed & NET80211_CFG_RATE) || ! 1625: (changed & NET80211_CFG_PHY_PARAMS)) { ! 1626: int spmbl = ATH5K_SPMBL_NO; ! 1627: u16 rate = dev->rates[dev->rate]; ! 1628: u16 slowrate = dev->rates[dev->rtscts_rate]; ! 1629: int i; ! 1630: ! 1631: if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE) ! 1632: spmbl = ATH5K_SPMBL_YES; ! 1633: ! 1634: for (i = 0; i < ATH5K_NR_RATES; i++) { ! 1635: if (ath5k_rates[i].bitrate == rate && ! 1636: (ath5k_rates[i].short_pmbl & spmbl)) ! 1637: sc->hw_rate = ath5k_rates[i].hw_code; ! 1638: ! 1639: if (ath5k_rates[i].bitrate == slowrate && ! 1640: (ath5k_rates[i].short_pmbl & spmbl)) ! 1641: sc->hw_rtscts_rate = ath5k_rates[i].hw_code; ! 1642: } ! 1643: } ! 1644: ! 1645: if (changed & NET80211_CFG_ASSOC) { ! 1646: sc->assoc = !!(dev->state & NET80211_ASSOCIATED); ! 1647: if (sc->assoc) { ! 1648: memcpy(ah->ah_bssid, dev->bssid, ETH_ALEN); ! 1649: } else { ! 1650: memset(ah->ah_bssid, 0xff, ETH_ALEN); ! 1651: } ! 1652: ath5k_hw_set_associd(ah, ah->ah_bssid, 0); ! 1653: } ! 1654: ! 1655: return 0; ! 1656: } ! 1657: ! 1658: /* ! 1659: * o always accept unicast, broadcast, and multicast traffic ! 1660: * o multicast traffic for all BSSIDs will be enabled if mac80211 ! 1661: * says it should be ! 1662: * o maintain current state of phy ofdm or phy cck error reception. ! 1663: * If the hardware detects any of these type of errors then ! 1664: * ath5k_hw_get_rx_filter() will pass to us the respective ! 1665: * hardware filters to be able to receive these type of frames. ! 1666: * o probe request frames are accepted only when operating in ! 1667: * hostap, adhoc, or monitor modes ! 1668: * o enable promiscuous mode according to the interface state ! 1669: * o accept beacons: ! 1670: * - when operating in adhoc mode so the 802.11 layer creates ! 1671: * node table entries for peers, ! 1672: * - when operating in station mode for collecting rssi data when ! 1673: * the station is otherwise quiet, or ! 1674: * - when scanning ! 1675: */ ! 1676: static void ath5k_configure_filter(struct ath5k_softc *sc) ! 1677: { ! 1678: struct ath5k_hw *ah = sc->ah; ! 1679: u32 mfilt[2], rfilt; ! 1680: ! 1681: /* Enable all multicast */ ! 1682: mfilt[0] = ~0; ! 1683: mfilt[1] = ~0; ! 1684: ! 1685: /* Enable data frames and beacons */ ! 1686: rfilt = (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | ! 1687: AR5K_RX_FILTER_MCAST | AR5K_RX_FILTER_BEACON); ! 1688: ! 1689: /* Set filters */ ! 1690: ath5k_hw_set_rx_filter(ah, rfilt); ! 1691: ! 1692: /* Set multicast bits */ ! 1693: ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); ! 1694: ! 1695: /* Set the cached hw filter flags, this will alter actually ! 1696: * be set in HW */ ! 1697: sc->filter_flags = rfilt; ! 1698: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.