From 0a3437aa52c010dc2ab10b9778a383fef436382c Mon Sep 17 00:00:00 2001 From: Renato Botelho Date: Mon, 22 Feb 2016 14:40:56 -0300 Subject: Revert "Importing pfSense patches net80211HEAD.tgz and conf.file.ieee80211.diff" This reverts commit 6ee75bdd7bf7c20359dd6e38c243586cb062edea. --- sys/dev/ath/ah_osdep.c | 49 +- sys/dev/ath/ath_dfs/null/dfs_null.c | 2 - sys/dev/ath/ath_hal/ah.c | 52 +- sys/dev/ath/ath_hal/ah.h | 64 +- sys/dev/ath/ath_hal/ah_decode.h | 3 - sys/dev/ath/ath_hal/ah_devid.h | 1 - sys/dev/ath/ath_hal/ah_internal.h | 28 +- sys/dev/ath/ath_hal/ah_regdomain.c | 5 - sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h | 1 - sys/dev/ath/ath_hal/ar5210/ar5210.h | 3 +- sys/dev/ath/ath_hal/ar5210/ar5210_attach.c | 4 +- sys/dev/ath/ath_hal/ar5210/ar5210_misc.c | 1 - sys/dev/ath/ath_hal/ar5210/ar5210_power.c | 12 +- sys/dev/ath/ath_hal/ar5210/ar5210_reset.c | 4 - sys/dev/ath/ath_hal/ar5211/ar5211.h | 1 + sys/dev/ath/ath_hal/ar5211/ar5211_attach.c | 2 +- sys/dev/ath/ath_hal/ar5211/ar5211_power.c | 12 +- sys/dev/ath/ath_hal/ar5212/ar5212.h | 11 +- sys/dev/ath/ath_hal/ar5212/ar5212_ani.c | 13 +- sys/dev/ath/ath_hal/ar5212/ar5212_attach.c | 2 +- sys/dev/ath/ath_hal/ar5212/ar5212_misc.c | 18 +- sys/dev/ath/ath_hal/ar5212/ar5212_power.c | 10 +- sys/dev/ath/ath_hal/ar5212/ar5212_reset.c | 3 +- sys/dev/ath/ath_hal/ar5312/ar5312_attach.c | 2 +- sys/dev/ath/ath_hal/ar5312/ar5312_power.c | 5 +- sys/dev/ath/ath_hal/ar5416/ar5416_ani.c | 13 +- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 7 +- sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c | 26 - sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 3 +- sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c | 3 - sys/dev/ath/ath_hal/ar5416/ar5416_power.c | 13 +- sys/dev/ath/ath_hal/ar5416/ar5416_reset.c | 3 +- sys/dev/ath/ath_hal/ar5416/ar5416reg.h | 4 +- sys/dev/ath/ath_hal/ar9001/ar9130_attach.c | 4 +- sys/dev/ath/ath_hal/ar9001/ar9160_attach.c | 1 - sys/dev/ath/ath_hal/ar9002/ar9280_attach.c | 1 - sys/dev/ath/ath_hal/ar9002/ar9285_attach.c | 1 - sys/dev/ath/ath_hal/ar9002/ar9287_attach.c | 1 - sys/dev/ath/ath_rate/sample/sample.c | 6 +- sys/dev/ath/ath_rate/sample/sample.h | 2 +- sys/dev/ath/if_ath.c | 937 +-- sys/dev/ath/if_ath_ahb.c | 24 +- sys/dev/ath/if_ath_beacon.c | 93 +- sys/dev/ath/if_ath_beacon.h | 2 - sys/dev/ath/if_ath_btcoex.c | 70 - sys/dev/ath/if_ath_debug.c | 3 +- sys/dev/ath/if_ath_debug.h | 1 - sys/dev/ath/if_ath_keycache.c | 17 +- sys/dev/ath/if_ath_led.c | 9 - sys/dev/ath/if_ath_lna_div.c | 6 - sys/dev/ath/if_ath_misc.h | 13 - sys/dev/ath/if_ath_pci.c | 138 +- sys/dev/ath/if_ath_pci_devlist.h | 669 -- sys/dev/ath/if_ath_rx.c | 250 +- sys/dev/ath/if_ath_rx_edma.c | 175 +- sys/dev/ath/if_ath_spectral.c | 2 - sys/dev/ath/if_ath_sysctl.c | 36 +- sys/dev/ath/if_ath_tdma.c | 16 +- sys/dev/ath/if_ath_tx.c | 422 +- sys/dev/ath/if_ath_tx_edma.c | 15 +- sys/dev/ath/if_athvar.h | 48 +- sys/dev/iwi/if_iwi.c | 75 +- sys/dev/iwi/if_iwi_ioctl.h | 25 - sys/dev/iwi/if_iwireg.h | 63 - sys/dev/iwi/if_iwivar.h | 3 - sys/dev/iwn/if_iwn.c | 2094 ++----- sys/dev/iwn/if_iwn_chip_cfg.h | 413 -- sys/dev/iwn/if_iwn_debug.h | 123 - sys/dev/iwn/if_iwn_devid.h | 39 - sys/dev/iwn/if_iwn_ioctl.h | 25 - sys/dev/iwn/if_iwnreg.h | 326 +- sys/dev/iwn/if_iwnvar.h | 36 +- sys/dev/ral/rt2560.c | 25 +- sys/dev/ral/rt2661.c | 23 +- sys/dev/ral/rt2860.c | 19 +- sys/dev/usb/wlan/if_rsu.c | 45 +- sys/dev/usb/wlan/if_rum.c | 21 +- sys/dev/usb/wlan/if_run.c | 34 +- sys/dev/usb/wlan/if_runreg.h | 25 + sys/dev/usb/wlan/if_uath.c | 31 +- sys/dev/usb/wlan/if_upgt.c | 23 +- sys/dev/usb/wlan/if_ural.c | 21 +- sys/dev/usb/wlan/if_urtw.c | 33 +- sys/dev/usb/wlan/if_urtwn.c | 116 +- sys/dev/usb/wlan/if_urtwnreg.h | 2 +- sys/dev/usb/wlan/if_zyd.c | 21 +- sys/dev/wi/if_wi.c | 57 +- sys/dev/wi/if_wi_pccard.c | 2 +- sys/dev/wi/if_wi_pci.c | 1 - sys/dev/wpi/if_wpi.c | 7117 ++++++++-------------- sys/dev/wpi/if_wpi_debug.h | 143 - sys/dev/wpi/if_wpireg.h | 1021 ++-- sys/dev/wpi/if_wpivar.h | 211 +- 93 files changed, 4151 insertions(+), 11404 deletions(-) delete mode 100644 sys/dev/ath/if_ath_pci_devlist.h delete mode 100644 sys/dev/iwi/if_iwi_ioctl.h delete mode 100644 sys/dev/iwn/if_iwn_chip_cfg.h delete mode 100644 sys/dev/iwn/if_iwn_debug.h delete mode 100644 sys/dev/iwn/if_iwn_ioctl.h delete mode 100644 sys/dev/wpi/if_wpi_debug.h (limited to 'sys/dev') diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c index fe4a657..043ebed 100644 --- a/sys/dev/ath/ah_osdep.c +++ b/sys/dev/ath/ah_osdep.c @@ -96,8 +96,9 @@ static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, #ifdef AH_DEBUG int ath_hal_debug = 0; -SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_hal_debug, +SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug, 0, "Atheros HAL debugging printfs"); +TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug); #endif /* AH_DEBUG */ static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data"); @@ -137,24 +138,6 @@ ath_hal_ether_sprintf(const u_int8_t *mac) #ifdef AH_DEBUG -/* - * XXX This is highly relevant only for the AR5416 and later - * PCI/PCIe NICs. It'll need adjustment for other hardware - * variations. - */ -static int -ath_hal_reg_whilst_asleep(struct ath_hal *ah, uint32_t reg) -{ - - if (reg >= 0x4000 && reg < 0x5000) - return (1); - if (reg >= 0x6000 && reg < 0x7000) - return (1); - if (reg >= 0x7000 && reg < 0x8000) - return (1); - return (0); -} - void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) { @@ -270,13 +253,6 @@ ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val) bus_space_tag_t tag = BUSTAG(ah); bus_space_handle_t h = ah->ah_sh; - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n", - __func__, reg, val, ah->ah_powerMode); - } - if (ath_hal_alq) { struct ale *ale = ath_hal_alq_get(ah); if (ale) { @@ -302,13 +278,6 @@ ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg) bus_space_handle_t h = ah->ah_sh; u_int32_t val; - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n", - __func__, reg, ah->ah_powerMode); - } - if (ah->ah_config.ah_serialise_reg_war) mtx_lock_spin(&ah_regser_mtx); val = bus_space_read_4(tag, h, reg); @@ -361,13 +330,6 @@ ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val) bus_space_tag_t tag = BUSTAG(ah); bus_space_handle_t h = ah->ah_sh; - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n", - __func__, reg, val, ah->ah_powerMode); - } - if (ah->ah_config.ah_serialise_reg_war) mtx_lock_spin(&ah_regser_mtx); bus_space_write_4(tag, h, reg, val); @@ -382,13 +344,6 @@ ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg) bus_space_handle_t h = ah->ah_sh; u_int32_t val; - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n", - __func__, reg, ah->ah_powerMode); - } - if (ah->ah_config.ah_serialise_reg_war) mtx_lock_spin(&ah_regser_mtx); val = bus_space_read_4(tag, h, reg); diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c index c980a79..36b2042 100644 --- a/sys/dev/ath/ath_dfs/null/dfs_null.c +++ b/sys/dev/ath/ath_dfs/null/dfs_null.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -54,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include /* XXX for ether_sprintf */ diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c index 4eb7fb6..7187d57 100644 --- a/sys/dev/ath/ath_hal/ah.c +++ b/sys/dev/ath/ath_hal/ah.c @@ -55,9 +55,7 @@ ath_hal_probe(uint16_t vendorid, uint16_t devid) */ struct ath_hal* ath_hal_attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, - HAL_STATUS *error) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error) { struct ath_hal_chip * const *pchip; @@ -68,8 +66,7 @@ ath_hal_attach(uint16_t devid, HAL_SOFTC sc, /* XXX don't have vendorid, assume atheros one works */ if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL) continue; - ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config, - error); + ah = chip->attach(devid, sc, st, sh, eepromdata, error); if (ah != AH_NULL) { /* copy back private state to public area */ ah->ah_devid = AH_PRIVATE(ah)->ah_devid; @@ -789,8 +786,6 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return HAL_OK; case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */ return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP; - case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */ - return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP; default: return HAL_EINVAL; } @@ -853,11 +848,10 @@ ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, int i; for (i = 0; space >= 2*sizeof(uint32_t); i++) { - uint32_t r = regs[i].start; - uint32_t e = regs[i].end; - *dp++ = r; - *dp++ = e; - space -= 2*sizeof(uint32_t); + u_int r = regs[i].start; + u_int e = regs[i].end; + *dp++ = (r<<16) | e; + space -= sizeof(uint32_t); do { *dp++ = OS_REG_READ(ah, r); r += sizeof(uint32_t); @@ -881,7 +875,6 @@ ath_hal_getdiagstate(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize) { - switch (request) { case HAL_DIAG_REVS: *result = &AH_PRIVATE(ah)->ah_devid; @@ -939,10 +932,6 @@ ath_hal_getdiagstate(struct ath_hal *ah, int request, } else return AH_FALSE; return AH_TRUE; - case HAL_DIAG_CHANSURVEY: - *result = &AH_PRIVATE(ah)->ah_chansurvey; - *resultsize = sizeof(HAL_CHANNEL_SURVEY); - return AH_TRUE; } return AH_FALSE; } @@ -1438,32 +1427,3 @@ ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan) else return 15 + ((ichan->channel - 2512) / 20); } - -/* - * Clear the current survey data. - * - * This should be done during a channel change. - */ -void -ath_hal_survey_clear(struct ath_hal *ah) -{ - - OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey, - sizeof(AH_PRIVATE(ah)->ah_chansurvey)); -} - -/* - * Add a sample to the channel survey. - */ -void -ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) -{ - HAL_CHANNEL_SURVEY *cs; - - cs = &AH_PRIVATE(ah)->ah_chansurvey; - - OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs)); - cs->samples[cs->cur_sample].seq_num = cs->cur_seq; - cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; - cs->cur_seq++; -} diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index facfceb1..2480803 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -199,7 +199,6 @@ typedef enum { HAL_CAP_SERIALISE_WAR = 245, /* serialise register access on PCI */ HAL_CAP_ENFORCE_TXOP = 246, /* Enforce TXOP if supported */ HAL_CAP_RX_LNA_MIXING = 247, /* RX hardware uses LNA mixing */ - HAL_CAP_DO_MYBEACON = 248, /* Supports HAL_RX_FILTER_MYBEACON */ } HAL_CAPABILITY_TYPE; /* @@ -405,7 +404,6 @@ typedef enum { HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */ HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */ HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */ - HAL_RX_FILTER_MYBEACON = 0x00000200, /* Filter beacons other than mine */ HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */ HAL_RX_FILTER_COMP_BA = 0x00000800, /* Allow compressed blockack */ HAL_RX_FILTER_PHYRADAR = 0x00002000, /* Allow phy radar errors */ @@ -540,7 +538,6 @@ typedef enum { typedef struct { u_int32_t cyclecnt_diff; /* delta cycle count */ u_int32_t rxclr_cnt; /* rx clear count */ - u_int32_t extrxclr_cnt; /* ext chan rx clear count */ u_int32_t txframecnt_diff; /* delta tx frame count */ u_int32_t rxframecnt_diff; /* delta rx frame count */ u_int32_t listen_time; /* listen time in msec - time for which ch is free */ @@ -850,48 +847,6 @@ typedef struct { #define HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ -/* - * This is the ANI state and MIB stats. - * - * It's used by the HAL modules to keep state /and/ by the debug ioctl - * to fetch ANI information. - */ -typedef struct { - uint32_t ast_ani_niup; /* ANI increased noise immunity */ - uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ - uint32_t ast_ani_spurup; /* ANI increased spur immunity */ - uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */ - uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */ - uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */ - uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */ - uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */ - uint32_t ast_ani_stepup; /* ANI increased first step level */ - uint32_t ast_ani_stepdown;/* ANI decreased first step level */ - uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */ - uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */ - uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */ - uint32_t ast_ani_lzero; /* ANI listen time forced to zero */ - uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */ - HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ - HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ -} HAL_ANI_STATS; - -typedef struct { - uint8_t noiseImmunityLevel; - uint8_t spurImmunityLevel; - uint8_t firstepLevel; - uint8_t ofdmWeakSigDetectOff; - uint8_t cckWeakSigThreshold; - uint32_t listenTime; - - /* NB: intentionally ordered so data exported to user space is first */ - uint32_t txFrameCount; /* Last txFrameCount */ - uint32_t rxFrameCount; /* Last rx Frame count */ - uint32_t cycleCount; /* Last cycleCount - (to detect wrap-around) */ - uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */ - uint32_t cckPhyErrCount; /* CCK err count since last reset */ -} HAL_ANI_STATE; struct ath_desc; struct ath_tx_status; @@ -1307,7 +1262,6 @@ typedef struct int ath_hal_show_bb_panic; int ath_hal_ant_ctrl_comm2g_switch_enable; int ath_hal_ext_atten_margin_cfg; - int ath_hal_min_gainidx; int ath_hal_war70c; uint32_t ath_hal_mci_config; } HAL_OPS_CONFIG; @@ -1343,9 +1297,6 @@ struct ath_hal { uint32_t ah_intrstate[8]; /* last int state */ uint32_t ah_syncstate; /* last sync intr state */ - /* Current powerstate from HAL calls */ - HAL_POWER_MODE ah_powerMode; - HAL_OPS_CONFIG ah_config; const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, u_int mode); @@ -1632,18 +1583,6 @@ struct ath_hal { void __ahdecl(*ah_btCoexDisable)(struct ath_hal *); int __ahdecl(*ah_btCoexEnable)(struct ath_hal *); - /* Bluetooth MCI methods */ - void __ahdecl(*ah_btMciSetup)(struct ath_hal *, - uint32_t, void *, uint16_t, uint32_t); - HAL_BOOL __ahdecl(*ah_btMciSendMessage)(struct ath_hal *, - uint8_t, uint32_t, uint32_t *, uint8_t, - HAL_BOOL, HAL_BOOL); - uint32_t __ahdecl(*ah_btMciGetInterrupt)(struct ath_hal *, - uint32_t *, uint32_t *); - uint32_t __ahdecl(*ah_btMciGetState)(struct ath_hal *, - uint32_t, uint32_t *); - void __ahdecl(*ah_btMciDetach)(struct ath_hal *); - /* LNA diversity configuration */ void __ahdecl(*ah_divLnaConfGet)(struct ath_hal *, HAL_ANT_COMB_CONFIG *); @@ -1672,8 +1611,7 @@ extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid); * be returned if the status parameter is non-zero. */ extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC, - HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS* status); + HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, HAL_STATUS* status); extern const char *ath_hal_mac_name(struct ath_hal *); extern const char *ath_hal_rf_name(struct ath_hal *); diff --git a/sys/dev/ath/ath_hal/ah_decode.h b/sys/dev/ath/ath_hal/ah_decode.h index 3aca975..07c4ac7 100644 --- a/sys/dev/ath/ath_hal/ah_decode.h +++ b/sys/dev/ath/ath_hal/ah_decode.h @@ -53,8 +53,6 @@ enum { AH_MARK_ANI_POLL, /* ar*AniReset, listen time */ AH_MARK_ANI_CONTROL, /* ar*AniReset, cmd */ AH_MARK_RX_CTL, /* RX DMA control */ - AH_MARK_CHIP_POWER, /* chip power control, mode */ - AH_MARK_CHIP_POWER_DONE, /* chip power control done, status */ }; enum { @@ -63,7 +61,6 @@ enum { AH_MARK_RX_CTL_DMA_START, AH_MARK_RX_CTL_DMA_STOP, AH_MARK_RX_CTL_DMA_STOP_ERR, - AH_MARK_RX_CTL_DMA_STOP_OK, }; #endif /* _ATH_AH_DECODE_H_ */ diff --git a/sys/dev/ath/ath_hal/ah_devid.h b/sys/dev/ath/ath_hal/ah_devid.h index 1e4d473..43d994d 100644 --- a/sys/dev/ath/ath_hal/ah_devid.h +++ b/sys/dev/ath/ath_hal/ah_devid.h @@ -92,7 +92,6 @@ #define AR9300_DEVID_AR946X_PCIE 0x0034 #define AR9300_DEVID_AR9330 0x0035 #define AR9300_DEVID_QCA9565 0x0036 -#define AR9300_DEVID_AR1111_PCIE 0x0037 #define AR9300_DEVID_QCA955X 0x0039 #define AR_SUBVENDOR_ID_NOG 0x0e11 /* No 11G subvendor ID */ diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 0c855d4..908f33e 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -50,8 +50,8 @@ #endif typedef struct { - uint32_t start; /* first register */ - uint32_t end; /* ending register or zero */ + uint16_t start; /* first register */ + uint16_t end; /* ending register or zero */ } HAL_REGRANGE; typedef struct { @@ -91,7 +91,6 @@ struct ath_hal_chip { const char *(*probe)(uint16_t vendorid, uint16_t devid); struct ath_hal *(*attach)(uint16_t devid, HAL_SOFTC, HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah, HAL_STATUS *error); }; #ifndef AH_CHIP @@ -281,9 +280,7 @@ typedef struct { halAntDivCombSupportOrg : 1, halRadioRetentionSupport : 1, halSpectralScanSupport : 1, - halRxUsingLnaMixing : 1, - halRxDoMyBeacon : 1, - halHwUapsdTrig : 1; + halRxUsingLnaMixing : 1; uint32_t halWirelessModes; uint16_t halTotalQueues; @@ -422,13 +419,9 @@ struct ath_hal_private { uint32_t ah_fatalState[6]; /* AR_ISR+shadow regs */ int ah_rxornIsFatal; /* how to treat HAL_INT_RXORN */ - /* Only used if ATH_NF_PER_CHAN is defined */ +#ifndef ATH_NF_PER_CHAN HAL_NFCAL_HIST_FULL nf_cal_hist; - - /* - * Channel survey history - current channel only. - */ - HAL_CHANNEL_SURVEY ah_chansurvey; /* channel survey */ +#endif /* ! ATH_NF_PER_CHAN */ }; #define AH_PRIVATE(_ah) ((struct ath_hal_private *)(_ah)) @@ -1033,15 +1026,4 @@ ath_hal_getantennaallowed(struct ath_hal *ah, */ extern int ath_hal_mhz2ieee_2ghz(struct ath_hal *, HAL_CHANNEL_INTERNAL *); -/* - * Clear the channel survey data. - */ -extern void ath_hal_survey_clear(struct ath_hal *ah); - -/* - * Add a sample to the channel survey data. - */ -extern void ath_hal_survey_add_sample(struct ath_hal *ah, - HAL_SURVEY_SAMPLE *hs); - #endif /* _ATH_AH_INTERAL_H_ */ diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c index fb0c841..807db44 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain.c +++ b/sys/dev/ath/ath_hal/ah_regdomain.c @@ -169,11 +169,6 @@ isEepromValid(struct ath_hal *ah) if (regDomainPairs[i].regDmnEnum == rd) return AH_TRUE; } - - if (rd == FCC_UBNT) { - return AH_TRUE; - } - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); return AH_FALSE; diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h index d8d211e..bc569cb 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h +++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h @@ -51,7 +51,6 @@ enum { FCC2_FCCA = 0x20, /* Canada */ FCC2_WORLD = 0x21, /* Australia & HK */ FCC2_ETSIC = 0x22, - FCC_UBNT = 0x2A, /* Ubiquity PicoStation M2HP */ FRANCE_RES = 0x31, /* Legacy France for OEM */ FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h index 3e372f7..48ccc20 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210.h +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -108,6 +108,7 @@ struct ath_hal_5210 { uint32_t ah_txDescInterruptMask; uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; + HAL_POWER_MODE ah_powerMode; uint8_t ah_bssid[IEEE80211_ADDR_LEN]; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */ /* @@ -120,8 +121,6 @@ struct ath_hal_5210 { u_int ah_slottime; /* user-specified slot time */ u_int ah_acktimeout; /* user-specified ack timeout */ u_int ah_ctstimeout; /* user-specified cts timeout */ - - uint16_t ah_associd; /* association id */ }; #define AH5210(ah) ((struct ath_hal_5210 *)(ah)) diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c index ceafa99..3c0ed71 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -183,7 +183,7 @@ static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah); */ static struct ath_hal * ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, - uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) + uint16_t *eepromdata, HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5210 *ahp; @@ -219,7 +219,7 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ - ah->ah_powerMode = HAL_PM_UNDEFINED; + ahp->ah_powerMode = HAL_PM_UNDEFINED; ahp->ah_staId1Defaults = 0; ahp->ah_rssiThr = INIT_RSSI_THR; ahp->ah_sifstime = (u_int) -1; diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c index 5eaa18e..8170880 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c @@ -315,7 +315,6 @@ ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) /* XXX save bssid for possible re-use on reset */ OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); - ahp->ah_associd = assocId; OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | ((assocId & 0x3fff)< %s (%s)\n", __func__, - modes[ah->ah_powerMode], modes[mode], + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); switch (mode) { case HAL_PM_AWAKE: - if (setChip) - ah->ah_powerMode = mode; status = ar5210SetPowerModeAwake(ah, setChip); break; case HAL_PM_FULL_SLEEP: ar5210SetPowerModeSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; case HAL_PM_NETWORK_SLEEP: ar5210SetPowerModeAuto(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", __func__, mode); return AH_FALSE; } - return status; + ahp->ah_powerMode = mode; + return status; } HAL_POWER_MODE diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c index 1dba729..1d50f99 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c @@ -152,12 +152,8 @@ ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode, /* Restore previous led state */ OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate); -#if 0 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); -#endif - /* BSSID, association id, ps-poll */ - ar5210WriteAssocid(ah, ahp->ah_bssid, ahp->ah_associd); OS_REG_WRITE(ah, AR_TXDP0, 0); OS_REG_WRITE(ah, AR_TXDP1, 0); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h index 6f04624..c50531e 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h @@ -119,6 +119,7 @@ struct ath_hal_5211 { uint32_t ah_txEolInterruptMask; uint32_t ah_txUrnInterruptMask; HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; + HAL_POWER_MODE ah_powerMode; HAL_ANT_SETTING ah_diversityControl; /* antenna setting */ uint32_t ah_calibrationTime; HAL_BOOL ah_bIQCalibration; diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c index 3416dc0..4549295 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c @@ -203,7 +203,7 @@ ar5211GetRadioRev(struct ath_hal *ah) static struct ath_hal * ar5211Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) + HAL_STATUS *status) { #define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5211 *ahp; diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_power.c b/sys/dev/ath/ath_hal/ar5211/ar5211_power.c index e646d90..776cfb3 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_power.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_power.c @@ -95,6 +95,7 @@ ar5211SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) HAL_BOOL ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) { + struct ath_hal_5211 *ahp = AH5211(ah); #ifdef AH_DEBUG static const char* modes[] = { "AWAKE", @@ -106,30 +107,25 @@ ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) int status = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, - modes[ah->ah_powerMode], modes[mode], + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); switch (mode) { case HAL_PM_AWAKE: - if (setChip) - ah->ah_powerMode = mode; status = ar5211SetPowerModeAwake(ah, setChip); break; case HAL_PM_FULL_SLEEP: ar5211SetPowerModeSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; case HAL_PM_NETWORK_SLEEP: ar5211SetPowerModeNetworkSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", __func__, mode); return AH_FALSE; } - return status; + ahp->ah_powerMode = mode; + return status; } HAL_POWER_MODE diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h index 938a68c..6d38d65 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h @@ -200,7 +200,6 @@ struct ar5212AniState { #define HAL_ANI_ENA 0x00000001 /* ANI operation enabled */ #define HAL_RSSI_ANI_ENA 0x00000002 /* rssi-based processing ena'd*/ -#if 0 struct ar5212Stats { uint32_t ast_ani_niup; /* ANI increased noise immunity */ uint32_t ast_ani_nidown; /* ANI decreased noise immunity */ @@ -220,7 +219,6 @@ struct ar5212Stats { HAL_MIB_STATS ast_mibstats; /* MIB counter stats */ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */ }; -#endif /* * NF Cal history buffer @@ -260,7 +258,7 @@ struct ath_hal_5212 { * Runtime state. */ uint32_t ah_maskReg; /* copy of AR_IMR */ - HAL_ANI_STATS ah_stats; /* various statistics */ + struct ar5212Stats ah_stats; /* various statistics */ RF_HAL_FUNCS *ah_rfHal; uint32_t ah_txDescMask; /* mask for TXDESC */ uint32_t ah_txOkInterruptMask; @@ -272,6 +270,7 @@ struct ath_hal_5212 { uint32_t ah_intrTxqs; /* tx q interrupt state */ /* decomp mask array */ uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE]; + HAL_POWER_MODE ah_powerMode; HAL_ANT_SETTING ah_antControl; /* antenna setting */ HAL_BOOL ah_diversity; /* fast diversity setting */ enum { @@ -321,6 +320,7 @@ struct ath_hal_5212 { struct ar5212AniParams ah_aniParams5; /* 5GHz parameters */ struct ar5212AniState *ah_curani; /* cached last reference */ struct ar5212AniState ah_ani[AH_MAXCHAN]; /* per-channel state */ + HAL_CHANNEL_SURVEY ah_chansurvey; /* channel survey */ /* AR5416 uses some of the AR5212 ANI code; these are the ANI methods */ HAL_BOOL (*ah_aniControl) (struct ath_hal *, HAL_ANI_CMD cmd, int param); @@ -345,9 +345,6 @@ struct ath_hal_5212 { uint32_t ah_txBusy; uint32_t ah_rx_chainmask; uint32_t ah_tx_chainmask; - - /* Used to return ANI statistics to the diagnostic API */ - HAL_ANI_STATS ext_ani_stats; }; #define AH5212(_ah) ((struct ath_hal_5212 *)(_ah)) @@ -630,7 +627,7 @@ extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *, HAL_BOOL ena); extern void ar5212AniDetach(struct ath_hal *); extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *); -extern HAL_ANI_STATS *ar5212AniGetCurrentStats(struct ath_hal *); +extern struct ar5212Stats *ar5212AniGetCurrentStats(struct ath_hal *); extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param); extern HAL_BOOL ar5212AniSetParams(struct ath_hal *, const struct ar5212AniParams *, const struct ar5212AniParams *); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c index c7b5932..8e87a2f 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c @@ -110,7 +110,7 @@ ar5212AniGetCurrentState(struct ath_hal *ah) /* * Return the current statistics. */ -HAL_ANI_STATS * +struct ar5212Stats * ar5212AniGetCurrentStats(struct ath_hal *ah) { struct ath_hal_5212 *ahp = AH5212(ah); @@ -869,6 +869,7 @@ ar5212AniGetListenTime(struct ath_hal *ah) int32_t listenTime = 0; int good; HAL_SURVEY_SAMPLE hs; + HAL_CHANNEL_SURVEY *cs = AH_NULL; /* * We shouldn't see ah_curchan be NULL, but just in case.. @@ -878,13 +879,21 @@ ar5212AniGetListenTime(struct ath_hal *ah) return (0); } + cs = &ahp->ah_chansurvey; + /* * Fetch the current statistics, squirrel away the current * sample, bump the sequence/sample counter. */ OS_MEMZERO(&hs, sizeof(hs)); good = ar5212GetMibCycleCounts(ah, &hs); - ath_hal_survey_add_sample(ah, &hs); + if (cs != AH_NULL) { + OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs)); + cs->samples[cs->cur_sample].seq_num = cs->cur_seq; + cs->cur_sample = + (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; + cs->cur_seq++; + } if (ANI_ENA(ah)) aniState = ahp->ah_curani; diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c index a95f244..e0af27c 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c @@ -317,7 +317,7 @@ ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev) static struct ath_hal * ar5212Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) + HAL_STATUS *status) { #define AH_EEPROM_PROTECT(ah) \ (AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT) diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c index e2f1eb7..71ee845 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c @@ -1052,7 +1052,6 @@ ar5212GetDiagState(struct ath_hal *ah, int request, void **result, uint32_t *resultsize) { struct ath_hal_5212 *ahp = AH5212(ah); - HAL_ANI_STATS *astats; (void) ahp; if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) @@ -1084,16 +1083,9 @@ ar5212GetDiagState(struct ath_hal *ah, int request, 0 : sizeof(struct ar5212AniState); return AH_TRUE; case HAL_DIAG_ANI_STATS: - OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats)); - astats = ar5212AniGetCurrentStats(ah); - if (astats == NULL) { - *result = NULL; - *resultsize = 0; - } else { - OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS)); - *result = &ahp->ext_ani_stats; - *resultsize = sizeof(ahp->ext_ani_stats); - } + *result = ar5212AniGetCurrentStats(ah); + *resultsize = (*result == AH_NULL) ? + 0 : sizeof(struct ar5212Stats); return AH_TRUE; case HAL_DIAG_ANI_CMD: if (argsize != 2*sizeof(uint32_t)) @@ -1121,6 +1113,10 @@ ar5212GetDiagState(struct ath_hal *ah, int request, return ar5212AniSetParams(ah, args, args); } break; + case HAL_DIAG_CHANSURVEY: + *result = &ahp->ah_chansurvey; + *resultsize = sizeof(HAL_CHANNEL_SURVEY); + return AH_TRUE; } return AH_FALSE; } diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_power.c b/sys/dev/ath/ath_hal/ar5212/ar5212_power.c index 3068510..3f755bd 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_power.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_power.c @@ -119,6 +119,7 @@ ar5212SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) { + struct ath_hal_5212 *ahp = AH5212(ah); #ifdef AH_DEBUG static const char* modes[] = { "AWAKE", @@ -130,29 +131,24 @@ ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) int status = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, - modes[ah->ah_powerMode], modes[mode], + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); switch (mode) { case HAL_PM_AWAKE: - if (setChip) - ah->ah_powerMode = mode; status = ar5212SetPowerModeAwake(ah, setChip); break; case HAL_PM_FULL_SLEEP: ar5212SetPowerModeSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; case HAL_PM_NETWORK_SLEEP: ar5212SetPowerModeNetworkSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n", __func__, mode); return AH_FALSE; } + ahp->ah_powerMode = mode; return status; } diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c index fd3b473..ccdccb6 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c @@ -197,8 +197,7 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, saveFrameSeqCount = 0; /* NB: silence compiler */ /* Blank the channel survey statistics */ - ath_hal_survey_clear(ah); - + OS_MEMZERO(&ahp->ah_chansurvey, sizeof(ahp->ah_chansurvey)); #if 0 /* * XXX disable for now; this appears to sometimes cause OFDM diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c index 5c84eb8..4ca1a4d 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c @@ -62,7 +62,7 @@ ar5312AniSetup(struct ath_hal *ah) static struct ath_hal * ar5312Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) + HAL_STATUS *status) { struct ath_hal_5212 *ahp = AH_NULL; struct ath_hal *ah; diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_power.c b/sys/dev/ath/ath_hal/ar5312/ar5312_power.c index 7db6d80..94a0f1c 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_power.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_power.c @@ -71,6 +71,7 @@ ar5312SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) HAL_BOOL ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) { + struct ath_hal_5212 *ahp = AH5212(ah); #ifdef AH_DEBUG static const char* modes[] = { "AWAKE", @@ -82,7 +83,7 @@ ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) int status = AH_TRUE; HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, - modes[ah->ah_powerMode], modes[mode], + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); switch (mode) { case HAL_PM_AWAKE: @@ -99,7 +100,7 @@ ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) __func__, mode); return AH_FALSE; } - ah->ah_powerMode = mode; + ahp->ah_powerMode = mode; return status; } diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c index fadd5ad..3f9bc69 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c @@ -818,6 +818,7 @@ ar5416AniGetListenTime(struct ath_hal *ah) int32_t listenTime = 0; int good; HAL_SURVEY_SAMPLE hs; + HAL_CHANNEL_SURVEY *cs = AH_NULL; /* * We shouldn't see ah_curchan be NULL, but just in case.. @@ -827,13 +828,21 @@ ar5416AniGetListenTime(struct ath_hal *ah) return (0); } + cs = &ahp->ah_chansurvey; + /* * Fetch the current statistics, squirrel away the current - * sample. + * sample, bump the sequence/sample counter. */ OS_MEMZERO(&hs, sizeof(hs)); good = ar5416GetMibCycleCounts(ah, &hs); - ath_hal_survey_add_sample(ah, &hs); + if (cs != AH_NULL) { + OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs)); + cs->samples[cs->cur_sample].seq_num = cs->cur_seq; + cs->cur_sample = + (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; + cs->cur_seq++; + } if (ANI_ENA(ah)) aniState = ahp->ah_curani; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index a20499a..99bab06 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -297,7 +297,7 @@ ar5416GetRadioRev(struct ath_hal *ah) static struct ath_hal * ar5416Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) + HAL_STATUS *status) { struct ath_hal_5416 *ahp5416; struct ath_hal_5212 *ahp; @@ -1059,11 +1059,6 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) if (! AH_PRIVATE(ah)->ah_ispcie) pCap->halSerialiseRegWar = 1; - /* - * AR5416 and later NICs support MYBEACON filtering. - */ - pCap->halRxDoMyBeacon = AH_TRUE; - return AH_TRUE; } diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c index 6691c11..e2bf6c7 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c @@ -197,25 +197,6 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) * beacon jitter; cab timeout is max time to wait for cab * after seeing the last DTIM or MORE CAB bit */ - -/* - * I've bumped these to 30TU for now. - * - * Some APs (AR933x/AR934x?) in 2GHz especially seem to not always - * transmit beacon frames at exactly the right times and with it set - * to 10TU, the NIC starts not waking up at the right times to hear - * these slightly-larger-jitering beacons. It also never recovers - * from that (it doesn't resync? I'm not sure.) - * - * So for now bump this to 30TU. Ideally we'd cap this based on - * the beacon interval so the sum of CAB+BEACON timeouts never - * exceeded the beacon interval. - * - * Now, since we're doing all the math in the ath(4) driver in TU - * rather than TSF, we may be seeing the result of dumb rounding - * errors causing the jitter to actually be a much bigger problem. - * I'll have to investigate that with a fine tooth comb. - */ #define CAB_TIMEOUT_VAL 10 /* in TU */ #define BEACON_TIMEOUT_VAL 10 /* in TU */ #define SLEEP_SLOP 3 /* in TU */ @@ -267,13 +248,6 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM); - -#define HAL_TSFOOR_THRESHOLD 0x00004240 /* TSF OOR threshold (16k us) */ - - /* TSF out of range threshold */ -// OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); - OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, HAL_TSFOOR_THRESHOLD); - HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n", __func__, bs->bs_nextdtim); HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n", diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index 35bb8d4..d51417f4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -663,7 +663,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * by the median we just loaded. This will be initial (and max) value * of next noise floor calibration the baseband does. */ - for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { + for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ @@ -676,7 +676,6 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) val |= (((uint32_t)(-50) << 1) & 0x1ff); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } - } } /* diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c index 32ce2ed..631ca2f 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c @@ -337,9 +337,6 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) /* Write the new IMR and store off our SW copy. */ HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); OS_REG_WRITE(ah, AR_IMR, mask); - /* Flush write */ - (void) OS_REG_READ(ah, AR_IMR); - mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c index dff9a85..43a9241 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c @@ -124,6 +124,7 @@ ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) { + struct ath_hal_5212 *ahp = AH5212(ah); #ifdef AH_DEBUG static const char* modes[] = { "AWAKE", @@ -133,35 +134,27 @@ ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip) }; #endif int status = AH_TRUE; - -#if 0 if (!setChip) return AH_TRUE; -#endif HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__, - modes[ah->ah_powerMode], modes[mode], setChip ? "set chip " : ""); + modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : ""); switch (mode) { case HAL_PM_AWAKE: - if (setChip) - ah->ah_powerMode = mode; status = ar5416SetPowerModeAwake(ah, setChip); break; case HAL_PM_FULL_SLEEP: ar5416SetPowerModeSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; case HAL_PM_NETWORK_SLEEP: ar5416SetPowerModeNetworkSleep(ah, setChip); - if (setChip) - ah->ah_powerMode = mode; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n", __func__, mode); return AH_FALSE; } + ahp->ah_powerMode = mode; return status; } diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index baf0ccc..eb31f08 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -120,10 +120,9 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); /* Blank the channel survey statistics */ - ath_hal_survey_clear(ah); + OS_MEMZERO(&ahp->ah_chansurvey, sizeof(ahp->ah_chansurvey)); /* XXX Turn on fast channel change for 5416 */ - /* * Preserve the bmiss rssi threshold and count threshold * across resets diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h index 0ee1e70..435599c 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h @@ -476,10 +476,10 @@ /* Sleep control */ #define AR5416_SLEEP1_ASSUME_DTIM 0x00080000 #define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */ -#define AR5416_SLEEP1_CAB_TIMEOUT_S 21 +#define AR5416_SLEEP1_CAB_TIMEOUT_S 22 #define AR5416_SLEEP2_BEACON_TIMEOUT 0xFFE00000 /* Beacon timeout (TU)*/ -#define AR5416_SLEEP2_BEACON_TIMEOUT_S 21 +#define AR5416_SLEEP2_BEACON_TIMEOUT_S 22 /* Sleep Registers */ #define AR_SLP32_HALFCLK_LATENCY 0x000FFFFF /* rising <-> falling edge */ diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c index c270bab..4f478c0 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c @@ -69,9 +69,7 @@ static HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); */ static struct ath_hal * ar9130Attach(uint16_t devid, HAL_SOFTC sc, - HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, - HAL_STATUS *status) + HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *status) { struct ath_hal_5416 *ahp5416; struct ath_hal_5212 *ahp; diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c index 5bda519..979ba1a 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c @@ -114,7 +114,6 @@ ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) static struct ath_hal * ar9160Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { struct ath_hal_5416 *ahp5416; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c index 3be3e35..2a67fe5 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c @@ -148,7 +148,6 @@ ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) static struct ath_hal * ar9280Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { struct ath_hal_9280 *ahp9280; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c index eb3490a..edb6f26 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -133,7 +133,6 @@ ar9285_eeprom_print_diversity_settings(struct ath_hal *ah) static struct ath_hal * ar9285Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { struct ath_hal_9285 *ahp9285; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c index 0ea565c..010e2c3 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -111,7 +111,6 @@ ar9287AniSetup(struct ath_hal *ah) static struct ath_hal * ar9287Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, - HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) { struct ath_hal_9287 *ahp9287; diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c index 36cd679..b3f82fa 100644 --- a/sys/dev/ath/ath_rate/sample/sample.c +++ b/sys/dev/ath/ath_rate/sample/sample.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -62,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include /* XXX for ether_sprintf */ @@ -891,8 +889,8 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (!mrr || ts->ts_finaltsi == 0) { if (!IS_RATE_DEFINED(sn, final_rix)) { - device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n", - __func__, ts->ts_rate, ts->ts_finaltsi, final_rix); + device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d\n", + __func__, ts->ts_rate, ts->ts_finaltsi); badrate(ifp, 0, ts->ts_rate, long_tries, status); return; } diff --git a/sys/dev/ath/ath_rate/sample/sample.h b/sys/dev/ath/ath_rate/sample/sample.h index 1c57dee..7438a3d 100644 --- a/sys/dev/ath/ath_rate/sample/sample.h +++ b/sys/dev/ath/ath_rate/sample/sample.h @@ -113,7 +113,7 @@ struct sample_node { #ifdef _KERNEL #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&(an)[1]) -#define IS_RATE_DEFINED(sn, rix) (((uint64_t) (sn)->ratemask & (1ULL<<((uint64_t) rix))) != 0) +#define IS_RATE_DEFINED(sn, rix) (((sn)->ratemask & (1<<(rix))) != 0) #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 3787500..6e58896 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -165,7 +164,6 @@ static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); static void ath_key_update_begin(struct ieee80211vap *); static void ath_key_update_end(struct ieee80211vap *); -static void ath_update_mcast_hw(struct ath_softc *); static void ath_update_mcast(struct ifnet *); static void ath_update_promisc(struct ifnet *); static void ath_updateslot(struct ifnet *); @@ -240,14 +238,17 @@ SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval, 0, "ANI calibration (msecs)"); int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RWTUN, &ath_rxbuf, +SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, 0, "rx buffers allocated"); +TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf); int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RWTUN, &ath_txbuf, +SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf, 0, "tx buffers allocated"); +TUNABLE_INT("hw.ath.txbuf", &ath_txbuf); int ath_txbuf_mgmt = ATH_MGMT_TXBUF; /* # mgmt tx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RWTUN, &ath_txbuf_mgmt, +SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RW, &ath_txbuf_mgmt, 0, "tx (mgmt) buffers allocated"); +TUNABLE_INT("hw.ath.txbuf_mgmt", &ath_txbuf_mgmt); int ath_bstuck_threshold = 4; /* max missed beacons */ SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold, @@ -277,293 +278,6 @@ ath_legacy_attach_comp_func(struct ath_softc *sc) } } -/* - * Set the target power mode. - * - * If this is called during a point in time where - * the hardware is being programmed elsewhere, it will - * simply store it away and update it when all current - * uses of the hardware are completed. - */ -void -_ath_power_setpower(struct ath_softc *sc, int power_state, const char *file, int line) -{ - ATH_LOCK_ASSERT(sc); - - sc->sc_target_powerstate = power_state; - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_powersave_refcnt); - - if (sc->sc_powersave_refcnt == 0 && - power_state != sc->sc_cur_powerstate) { - sc->sc_cur_powerstate = power_state; - ath_hal_setpower(sc->sc_ah, power_state); - - /* - * If the NIC is force-awake, then set the - * self-gen frame state appropriately. - * - * If the nic is in network sleep or full-sleep, - * we let the above call leave the self-gen - * state as "sleep". - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - } -} - -/* - * Set the current self-generated frames state. - * - * This is separate from the target power mode. The chip may be - * awake but the desired state is "sleep", so frames sent to the - * destination has PWRMGT=1 in the 802.11 header. The NIC also - * needs to know to set PWRMGT=1 in self-generated frames. - */ -void -_ath_power_set_selfgen(struct ath_softc *sc, int power_state, const char *file, int line) -{ - - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_target_selfgen_state); - - sc->sc_target_selfgen_state = power_state; - - /* - * If the NIC is force-awake, then set the power state. - * Network-state and full-sleep will already transition it to - * mark self-gen frames as sleeping - and we can't - * guarantee the NIC is awake to program the self-gen frame - * setting anyway. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, power_state); - } -} - -/* - * Set the hardware power mode and take a reference. - * - * This doesn't update the target power mode in the driver; - * it just updates the hardware power state. - * - * XXX it should only ever force the hardware awake; it should - * never be called to set it asleep. - */ -void -_ath_power_set_power_state(struct ath_softc *sc, int power_state, const char *file, int line) -{ - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_powersave_refcnt); - - sc->sc_powersave_refcnt++; - - if (power_state != sc->sc_cur_powerstate) { - ath_hal_setpower(sc->sc_ah, power_state); - sc->sc_cur_powerstate = power_state; - - /* - * Adjust the self-gen powerstate if appropriate. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - - } -} - -/* - * Restore the power save mode to what it once was. - * - * This will decrement the reference counter and once it hits - * zero, it'll restore the powersave state. - */ -void -_ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line) -{ - - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) refcnt=%d, target state=%d\n", - __func__, - file, - line, - sc->sc_powersave_refcnt, - sc->sc_target_powerstate); - - if (sc->sc_powersave_refcnt == 0) - device_printf(sc->sc_dev, "%s: refcnt=0?\n", __func__); - else - sc->sc_powersave_refcnt--; - - if (sc->sc_powersave_refcnt == 0 && - sc->sc_target_powerstate != sc->sc_cur_powerstate) { - sc->sc_cur_powerstate = sc->sc_target_powerstate; - ath_hal_setpower(sc->sc_ah, sc->sc_target_powerstate); - } - - /* - * Adjust the self-gen powerstate if appropriate. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - -} - -/* - * Configure the initial HAL configuration values based on bus - * specific parameters. - * - * Some PCI IDs and other information may need tweaking. - * - * XXX TODO: ath9k and the Atheros HAL only program comm2g_switch_enable - * if BT antenna diversity isn't enabled. - * - * So, let's also figure out how to enable BT diversity for AR9485. - */ -static void -ath_setup_hal_config(struct ath_softc *sc, HAL_OPS_CONFIG *ah_config) -{ - /* XXX TODO: only for PCI devices? */ - - if (sc->sc_pci_devinfo & (ATH_PCI_CUS198 | ATH_PCI_CUS230)) { - ah_config->ath_hal_ext_lna_ctl_gpio = 0x200; /* bit 9 */ - ah_config->ath_hal_ext_atten_margin_cfg = AH_TRUE; - ah_config->ath_hal_min_gainidx = AH_TRUE; - ah_config->ath_hal_ant_ctrl_comm2g_switch_enable = 0x000bbb88; - /* XXX low_rssi_thresh */ - /* XXX fast_div_bias */ - device_printf(sc->sc_dev, "configuring for %s\n", - (sc->sc_pci_devinfo & ATH_PCI_CUS198) ? - "CUS198" : "CUS230"); - } - - if (sc->sc_pci_devinfo & ATH_PCI_CUS217) - device_printf(sc->sc_dev, "CUS217 card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_CUS252) - device_printf(sc->sc_dev, "CUS252 card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT) - device_printf(sc->sc_dev, "WB335 1-ANT card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT) - device_printf(sc->sc_dev, "WB335 2-ANT card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_KILLER) - device_printf(sc->sc_dev, "Killer Wireless card detected\n"); - -#if 0 - /* - * Some WB335 cards do not support antenna diversity. Since - * we use a hardcoded value for AR9565 instead of using the - * EEPROM/OTP data, remove the combining feature from - * the HW capabilities bitmap. - */ - if (sc->sc_pci_devinfo & (ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_AR9565_2ANT)) { - if (!(sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV)) - pCap->hw_caps &= ~ATH9K_HW_CAP_ANT_DIV_COMB; - } - - if (sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV) { - pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV; - device_printf(sc->sc_dev, "Set BT/WLAN RX diversity capability\n"); - } -#endif - - if (sc->sc_pci_devinfo & ATH_PCI_D3_L1_WAR) { - ah_config->ath_hal_pcie_waen = 0x0040473b; - device_printf(sc->sc_dev, "Enable WAR for ASPM D3/L1\n"); - } - -#if 0 - if (sc->sc_pci_devinfo & ATH9K_PCI_NO_PLL_PWRSAVE) { - ah->config.no_pll_pwrsave = true; - device_printf(sc->sc_dev, "Disable PLL PowerSave\n"); - } -#endif - -} - -/* - * Attempt to fetch the MAC address from the kernel environment. - * - * Returns 0, macaddr in macaddr if successful; -1 otherwise. - */ -static int -ath_fetch_mac_kenv(struct ath_softc *sc, uint8_t *macaddr) -{ - char devid_str[32]; - int local_mac = 0; - char *local_macstr; - - /* - * Fetch from the kenv rather than using hints. - * - * Hints would be nice but the transition to dynamic - * hints/kenv doesn't happen early enough for this - * to work reliably (eg on anything embedded.) - */ - snprintf(devid_str, 32, "hint.%s.%d.macaddr", - device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev)); - - if ((local_macstr = getenv(devid_str)) != NULL) { - uint32_t tmpmac[ETHER_ADDR_LEN]; - int count; - int i; - - /* Have a MAC address; should use it */ - device_printf(sc->sc_dev, - "Overriding MAC address from environment: '%s'\n", - local_macstr); - - /* Extract out the MAC address */ - count = sscanf(local_macstr, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", - &tmpmac[0], &tmpmac[1], - &tmpmac[2], &tmpmac[3], - &tmpmac[4], &tmpmac[5]); - if (count == 6) { - /* Valid! */ - local_mac = 1; - for (i = 0; i < ETHER_ADDR_LEN; i++) - macaddr[i] = tmpmac[i]; - } - /* Done! */ - freeenv(local_macstr); - local_macstr = NULL; - } - - if (local_mac) - return (0); - return (-1); -} - #define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) #define HAL_MODE_HT40 \ (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ @@ -579,7 +293,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) u_int wmodes; uint8_t macaddr[IEEE80211_ADDR_LEN]; int rx_chainmask, tx_chainmask; - HAL_OPS_CONFIG ah_config; DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid); @@ -598,17 +311,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) device_get_unit(sc->sc_dev)); CURVNET_RESTORE(); - /* - * Configure the initial configuration data. - * - * This is stuff that may be needed early during attach - * rather than done via configuration calls later. - */ - bzero(&ah_config, sizeof(ah_config)); - ath_setup_hal_config(sc, &ah_config); - ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, - sc->sc_eepromdata, &ah_config, &status); + sc->sc_eepromdata, &status); if (ah == NULL) { if_printf(ifp, "unable to attach hardware; HAL status %u\n", status); @@ -636,10 +340,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ath_xmit_setup_legacy(sc); } - if (ath_hal_hasmybeacon(sc->sc_ah)) { - sc->sc_do_mybeacon = 1; - } - /* * Check if the MAC has multi-rate retry support. * We do this by trying to setup a fake extended @@ -904,8 +604,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) #ifdef ATH_ENABLE_DFS | IEEE80211_C_DFS /* Enable radar detection */ #endif - | IEEE80211_C_PMGT /* Station side power mgmt */ - | IEEE80211_C_SWSLEEP ; /* * Query the hal to figure out h/w crypto support. @@ -1203,14 +901,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ sc->sc_hasveol = ath_hal_hasveol(ah); - /* get mac address from kenv first, then hardware */ - if (ath_fetch_mac_kenv(sc, macaddr) == 0) { - /* Tell the HAL now about the new MAC */ - ath_hal_setmac(ah, macaddr); - } else { - ath_hal_getmac(ah, macaddr); - } - + /* get mac address from hardware */ + ath_hal_getmac(ah, macaddr); if (sc->sc_hasbmask) ath_hal_getbssidmask(ah, sc->sc_hwbssidmask); @@ -1301,14 +993,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) if (bootverbose) ieee80211_announce(ic); ath_announce(sc); - - /* - * Put it to sleep for now. - */ - ATH_LOCK(sc); - ath_power_setpower(sc, HAL_PM_FULL_SLEEP); - ATH_UNLOCK(sc); - return 0; bad2: ath_tx_cleanup(sc); @@ -1354,22 +1038,7 @@ ath_detach(struct ath_softc *sc) * it last * Other than that, it's straightforward... */ - - /* - * XXX Wake the hardware up first. ath_stop() will still - * wake it up first, but I'd rather do it here just to - * ensure it's awake. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - /* - * Stop things cleanly. - */ ath_stop(ifp); - ieee80211_ifdetach(ifp->if_l2com); taskqueue_free(sc->sc_tq); #ifdef ATH_TX99_DIAG @@ -1732,10 +1401,6 @@ ath_vap_delete(struct ieee80211vap *vap) struct ath_hal *ah = sc->sc_ah; struct ath_vap *avp = ATH_VAP(vap); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { /* @@ -1744,13 +1409,11 @@ ath_vap_delete(struct ieee80211vap *vap) * the vap state by any frames pending on the tx queues. */ ath_hal_intrset(ah, 0); /* disable interrupts */ + ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */ /* XXX Do all frames from all vaps/nodes need draining here? */ ath_stoprecv(sc, 1); /* stop recv side */ - ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */ } - /* .. leave the hardware awake for now. */ - ieee80211_vap_detach(vap); /* @@ -1838,9 +1501,6 @@ ath_vap_delete(struct ieee80211vap *vap) } ath_hal_intrset(ah, sc->sc_imask); } - - /* Ok, let the hardware asleep. */ - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); } @@ -1860,25 +1520,12 @@ ath_suspend(struct ath_softc *sc) * NB: don't worry about putting the chip in low power * mode; pci will power off our socket on suspend and * CardBus detaches the device. - * - * XXX TODO: well, that's great, except for non-cardbus - * devices! */ /* - * XXX This doesn't wait until all pending taskqueue - * items and parallel transmit/receive/other threads - * are running! - */ - ath_hal_intrset(sc->sc_ah, 0); - taskqueue_block(sc->sc_tq); - - ATH_LOCK(sc); - callout_stop(&sc->sc_cal_ch); - ATH_UNLOCK(sc); - - /* + * XXX ensure none of the taskqueues are running * XXX ensure sc_invalid is 1 + * XXX ensure the calibration callout is disabled */ /* Disable the PCIe PHY, complete with workarounds */ @@ -1899,12 +1546,8 @@ ath_reset_keycache(struct ath_softc *sc) struct ath_hal *ah = sc->sc_ah; int i; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); for (i = 0; i < sc->sc_keymax; i++) ath_hal_keyreset(ah, i); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); ieee80211_crypto_reload_keys(ic); } @@ -1956,24 +1599,11 @@ ath_resume(struct ath_softc *sc) sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan); ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); - - /* Ensure we set the current power state to on */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_hal_reset(ah, sc->sc_opmode, sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan, AH_FALSE, &status); ath_reset_keycache(sc); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, ic->ic_curchan); @@ -2001,10 +1631,6 @@ ath_resume(struct ath_softc *sc) if (sc->sc_resume_up) ieee80211_resume_all(ic); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - /* XXX beacons ? */ } @@ -2062,10 +1688,6 @@ ath_intr(void *arg) return; } - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if ((ifp->if_flags & IFF_UP) == 0 || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { HAL_INT status; @@ -2075,10 +1697,6 @@ ath_intr(void *arg) ath_hal_getisr(ah, &status); /* clear ISR */ ath_hal_intrset(ah, 0); /* disable further intr's */ ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); return; } @@ -2118,11 +1736,6 @@ ath_intr(void *arg) /* Short-circuit un-handled interrupts */ if (status == 0x0) { ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - return; } @@ -2178,46 +1791,44 @@ ath_intr(void *arg) if (status & HAL_INT_RXEOL) { int imask; ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXEOL"); - if (! sc->sc_isedma) { - ATH_PCU_LOCK(sc); - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work at - * least on older hardware revs. - */ - sc->sc_stats.ast_rxeol++; - /* - * Disable RXEOL/RXORN - prevent an interrupt - * storm until the PCU logic can be reset. - * In case the interface is reset some other - * way before "sc_kickpcu" is called, don't - * modify sc_imask - that way if it is reset - * by a call to ath_reset() somehow, the - * interrupt mask will be correctly reprogrammed. - */ - imask = sc->sc_imask; - imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); - ath_hal_intrset(ah, imask); - /* - * Only blank sc_rxlink if we've not yet kicked - * the PCU. - * - * This isn't entirely correct - the correct solution - * would be to have a PCU lock and engage that for - * the duration of the PCU fiddling; which would include - * running the RX process. Otherwise we could end up - * messing up the RX descriptor chain and making the - * RX desc list much shorter. - */ - if (! sc->sc_kickpcu) - sc->sc_rxlink = NULL; - sc->sc_kickpcu = 1; - ATH_PCU_UNLOCK(sc); - } + ATH_PCU_LOCK(sc); /* - * Enqueue an RX proc to handle whatever + * NB: the hardware should re-read the link when + * RXE bit is written, but it doesn't work at + * least on older hardware revs. + */ + sc->sc_stats.ast_rxeol++; + /* + * Disable RXEOL/RXORN - prevent an interrupt + * storm until the PCU logic can be reset. + * In case the interface is reset some other + * way before "sc_kickpcu" is called, don't + * modify sc_imask - that way if it is reset + * by a call to ath_reset() somehow, the + * interrupt mask will be correctly reprogrammed. + */ + imask = sc->sc_imask; + imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); + ath_hal_intrset(ah, imask); + /* + * Only blank sc_rxlink if we've not yet kicked + * the PCU. + * + * This isn't entirely correct - the correct solution + * would be to have a PCU lock and engage that for + * the duration of the PCU fiddling; which would include + * running the RX process. Otherwise we could end up + * messing up the RX descriptor chain and making the + * RX desc list much shorter. + */ + if (! sc->sc_kickpcu) + sc->sc_rxlink = NULL; + sc->sc_kickpcu = 1; + ATH_PCU_UNLOCK(sc); + /* + * Enqueue an RX proc, to handled whatever * is in the RX queue. - * This will then kick the PCU if required. + * This will then kick the PCU. */ sc->sc_rx.recv_sched(sc, 1); } @@ -2291,18 +1902,10 @@ ath_intr(void *arg) ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXORN"); sc->sc_stats.ast_rxorn++; } - if (status & HAL_INT_TSFOOR) { - device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__); - sc->sc_syncbeacon = 1; - } } ATH_PCU_LOCK(sc); sc->sc_intr_cnt--; ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } static void @@ -2333,8 +1936,6 @@ ath_fatal_proc(void *arg, int pending) static void ath_bmiss_vap(struct ieee80211vap *vap) { - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - /* * Workaround phantom bmiss interrupts by sanity-checking * the time of our last rx'd frame. If it is within the @@ -2343,16 +1944,6 @@ ath_bmiss_vap(struct ieee80211vap *vap) * be dispatched up for processing. Note this applies only * for h/w beacon miss events. */ - - /* - * XXX TODO: Just read the TSF during the interrupt path; - * that way we don't have to wake up again just to read it - * again. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) { struct ifnet *ifp = vap->iv_ic->ic_ifp; struct ath_softc *sc = ifp->if_softc; @@ -2370,32 +1961,12 @@ ath_bmiss_vap(struct ieee80211vap *vap) if (tsf - lastrx <= bmisstimeout) { sc->sc_stats.ast_bmiss_phantom++; - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - return; } } - - /* - * There's no need to keep the hardware awake during the call - * to av_bmiss(). - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - /* - * Attempt to force a beacon resync. - */ - sc->sc_syncbeacon = 1; - ATH_VAP(vap)->av_bmiss(vap); } -/* XXX this needs a force wakeup! */ int ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs) { @@ -2418,12 +1989,6 @@ ath_bmiss_proc(void *arg, int pending) DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - ath_beacon_miss(sc); - /* * Do a reset upon any becaon miss event. * @@ -2437,13 +2002,6 @@ ath_bmiss_proc(void *arg, int pending) ath_reset(ifp, ATH_RESET_NOLOSS); ieee80211_beacon_miss(ifp->if_l2com); } - - /* Force a beacon resync, in case they've drifted */ - sc->sc_syncbeacon = 1; - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } /* @@ -2483,13 +2041,6 @@ ath_init(void *arg) ATH_LOCK(sc); /* - * Force the sleep state awake. - */ - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - - /* * Stop anything previously setup. This is safe * whether this is the first time through or not. */ @@ -2506,19 +2057,12 @@ ath_init(void *arg) ath_update_chainmasks(sc, ic->ic_curchan); ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); - if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) { if_printf(ifp, "unable to reset hardware; hal status %u\n", status); ATH_UNLOCK(sc); return; } - - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - ath_chan_change(sc, ic->ic_curchan); /* Let DFS at it in case it's a DFS channel */ @@ -2546,11 +2090,11 @@ ath_init(void *arg) * state cached in the driver. */ sc->sc_diversity = ath_hal_getdiversity(ah); - sc->sc_lastlongcal = ticks; + sc->sc_lastlongcal = 0; sc->sc_resetcal = 1; sc->sc_lastcalreset = 0; - sc->sc_lastani = ticks; - sc->sc_lastshortcal = ticks; + sc->sc_lastani = 0; + sc->sc_lastshortcal = 0; sc->sc_doresetcal = AH_FALSE; /* * Beacon timers were cleared here; give ath_newstate() @@ -2568,7 +2112,6 @@ ath_init(void *arg) */ if (ath_startrecv(sc) != 0) { if_printf(ifp, "unable to start recv logic\n"); - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); return; } @@ -2577,7 +2120,8 @@ ath_init(void *arg) * Enable interrupts. */ sc->sc_imask = HAL_INT_RX | HAL_INT_TX - | HAL_INT_RXORN | HAL_INT_TXURN + | HAL_INT_RXEOL | HAL_INT_RXORN + | HAL_INT_TXURN | HAL_INT_FATAL | HAL_INT_GLOBAL; /* @@ -2588,29 +2132,12 @@ ath_init(void *arg) sc->sc_imask |= (HAL_INT_RXHP | HAL_INT_RXLP); /* - * If we're an EDMA NIC, we don't care about RXEOL. - * Writing a new descriptor in will simply restart - * RX DMA. - */ - if (! sc->sc_isedma) - sc->sc_imask |= HAL_INT_RXEOL; - - /* * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. */ if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA) sc->sc_imask |= HAL_INT_MIB; - /* - * XXX add capability for this. - * - * If we're in STA mode (and maybe IBSS?) then register for - * TSFOOR interrupts. - */ - if (ic->ic_opmode == IEEE80211_M_STA) - sc->sc_imask |= HAL_INT_TSFOOR; - /* Enable global TX timeout and carrier sense timeout if available */ if (ath_hal_gtxto_supported(ah)) sc->sc_imask |= HAL_INT_GTT; @@ -2622,7 +2149,6 @@ ath_init(void *arg) callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc); ath_hal_intrset(ah, sc->sc_imask); - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); #ifdef ATH_TX99_DIAG @@ -2643,12 +2169,6 @@ ath_stop_locked(struct ifnet *ifp) __func__, sc->sc_invalid, ifp->if_flags); ATH_LOCK_ASSERT(sc); - - /* - * Wake the hardware up before fiddling with it. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { /* * Shutdown the hardware and driver: @@ -2681,29 +2201,17 @@ ath_stop_locked(struct ifnet *ifp) } ath_hal_intrset(ah, 0); } - /* XXX we should stop RX regardless of whether it's valid */ + ath_draintxq(sc, ATH_RESET_DEFAULT); if (!sc->sc_invalid) { ath_stoprecv(sc, 1); ath_hal_phydisable(ah); } else sc->sc_rxlink = NULL; - ath_draintxq(sc, ATH_RESET_DEFAULT); ath_beacon_free(sc); /* XXX not needed */ } - - /* And now, restore the current power state */ - ath_power_restore_power_state(sc); } -/* - * Wait until all pending TX/RX has completed. - * - * This waits until all existing transmit, receive and interrupts - * have completed. It's assumed that the caller has first - * grabbed the reset lock so it doesn't try to do overlapping - * chip resets. - */ -#define MAX_TXRX_ITERATIONS 100 +#define MAX_TXRX_ITERATIONS 1000 static void ath_txrx_stop_locked(struct ath_softc *sc) { @@ -2722,8 +2230,7 @@ ath_txrx_stop_locked(struct ath_softc *sc) sc->sc_txstart_cnt || sc->sc_intr_cnt) { if (i <= 0) break; - msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", - msecs_to_ticks(10)); + msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", 1); i--; } @@ -2770,7 +2277,7 @@ ath_txrx_start(struct ath_softc *sc) * Another, cleaner way should be found to serialise all of * these operations. */ -#define MAX_RESET_ITERATIONS 25 +#define MAX_RESET_ITERATIONS 10 static int ath_reset_grablock(struct ath_softc *sc, int dowait) { @@ -2788,11 +2295,7 @@ ath_reset_grablock(struct ath_softc *sc, int dowait) break; } ATH_PCU_UNLOCK(sc); - /* - * 1 tick is likely not enough time for long calibrations - * to complete. So we should wait quite a while. - */ - pause("ath_reset_grablock", msecs_to_ticks(100)); + pause("ath_reset_grablock", 1); i--; ATH_PCU_LOCK(sc); } while (i > 0); @@ -2857,13 +2360,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Try to (stop any further TX/RX from occuring */ taskqueue_block(sc->sc_tq); - /* - * Wake the hardware up. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_PCU_LOCK(sc); /* @@ -2889,6 +2385,13 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ATH_PCU_UNLOCK(sc); /* + * Should now wait for pending TX/RX to complete + * and block future ones from occuring. This needs to be + * done before the TX queue is drained. + */ + ath_draintxq(sc, reset_type); /* stop xmit side */ + + /* * Regardless of whether we're doing a no-loss flush or * not, stop the PCU and handle what's in the RX queue. * That way frames aren't dropped which shouldn't be. @@ -2896,13 +2399,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS)); ath_rx_flush(sc); - /* - * Should now wait for pending TX/RX to complete - * and block future ones from occuring. This needs to be - * done before the TX queue is drained. - */ - ath_draintxq(sc, reset_type); /* stop xmit side */ - ath_settkipmic(sc); /* configure TKIP MIC handling */ /* NB: indicate channel change so we do a full reset */ ath_update_chainmasks(sc, ic->ic_curchan); @@ -2913,11 +2409,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) __func__, status); sc->sc_diversity = ath_hal_getdiversity(ah); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, ic->ic_curchan); @@ -2963,13 +2454,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) * reset counter - this way ath_intr() doesn't end up * disabling interrupts without a corresponding enable * in the rest or channel change path. - * - * Grab the TX reference in case we need to transmit. - * That way a parallel transmit doesn't. */ ATH_PCU_LOCK(sc); sc->sc_inreset_cnt--; - sc->sc_txstart_cnt++; /* XXX only do this if sc_inreset_cnt == 0? */ ath_hal_intrset(ah, sc->sc_imask); ATH_PCU_UNLOCK(sc); @@ -2986,8 +2473,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Restart TX/RX as needed */ ath_txrx_start(sc); - /* XXX TODO: we need to hold the tx refcount here! */ - /* Restart TX completion and pending TX */ if (reset_type == ATH_RESET_NOLOSS) { for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { @@ -3012,14 +2497,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; IF_UNLOCK(&ifp->if_snd); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - ATH_PCU_LOCK(sc); - sc->sc_txstart_cnt--; - ATH_PCU_UNLOCK(sc); - /* Handle any frames in the TX queue */ /* * XXX should this be done by the caller, rather than @@ -3160,7 +2637,6 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf) tbf->bf_status = bf->bf_status; tbf->bf_m = bf->bf_m; tbf->bf_node = bf->bf_node; - KASSERT((bf->bf_node != NULL), ("%s: bf_node=NULL!", __func__)); /* will be setup by the chain/setup function */ tbf->bf_lastds = NULL; /* for now, last == self */ @@ -3262,11 +2738,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - /* Wake the hardware up already */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: start"); /* * Grab the TX lock - it's ok to do this here; we haven't @@ -3375,7 +2846,7 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); sc->sc_stats.ast_tx_nofrag++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ath_freetx(m); goto bad; } @@ -3423,7 +2894,7 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) * * XXX should use atomics? */ - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; nextfrag: /* * Pass the frame to the h/w for transmission. @@ -3443,7 +2914,7 @@ nextfrag: next = m->m_nextpkt; if (ath_tx_start(sc, ni, bf, m)) { bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; reclaim: bf->bf_m = NULL; bf->bf_node = NULL; @@ -3500,11 +2971,6 @@ finish: sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); - /* Sleep the hardware if required */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: finished"); return (retval); @@ -3532,6 +2998,7 @@ ath_key_update_begin(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); + IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */ } static void @@ -3541,6 +3008,7 @@ ath_key_update_end(struct ieee80211vap *vap) struct ath_softc *sc = ifp->if_softc; DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); + IF_UNLOCK(&ifp->if_snd); taskqueue_unblock(sc->sc_tq); } @@ -3551,25 +3019,16 @@ ath_update_promisc(struct ifnet *ifp) u_int32_t rfilt; /* configure rx filter */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); rfilt = ath_calcrxfilter(sc); ath_hal_setrxfilter(sc->sc_ah, rfilt); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt); } -/* - * Driver-internal mcast update call. - * - * Assumes the hardware is already awake. - */ static void -ath_update_mcast_hw(struct ath_softc *sc) +ath_update_mcast(struct ifnet *ifp) { - struct ifnet *ifp = sc->sc_ifp; + struct ath_softc *sc = ifp->if_softc; u_int32_t mfilt[2]; /* calculate and install multicast filter */ @@ -3597,33 +3056,11 @@ ath_update_mcast_hw(struct ath_softc *sc) if_maddr_runlock(ifp); } else mfilt[0] = mfilt[1] = ~0; - ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]); - DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n", __func__, mfilt[0], mfilt[1]); } -/* - * Called from the net80211 layer - force the hardware - * awake before operating. - */ -static void -ath_update_mcast(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - ath_update_mcast_hw(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); -} - void ath_mode_init(struct ath_softc *sc) { @@ -3649,7 +3086,7 @@ ath_mode_init(struct ath_softc *sc) ath_hal_setmac(ah, IF_LLADDR(ifp)); /* calculate and install multicast filter */ - ath_update_mcast_hw(sc); + ath_update_mcast(ifp); } /* @@ -3681,13 +3118,8 @@ ath_setslottime(struct ath_softc *sc) __func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags, ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", usec); - /* Wake up the hardware first before updating the slot time */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_hal_setslottime(ah, usec); - ath_power_restore_power_state(sc); sc->sc_updateslot = OK; - ATH_UNLOCK(sc); } /* @@ -3704,8 +3136,6 @@ ath_updateslot(struct ifnet *ifp) * When not coordinating the BSS, change the hardware * immediately. For other operation we defer the change * until beacon updates have propagated to the stations. - * - * XXX sc_updateslot isn't changed behind a lock? */ if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_MBSS) @@ -4611,12 +4041,14 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf) { struct ieee80211_node *ni = bf->bf_node; + struct ath_node *an = NULL; ATH_TX_UNLOCK_ASSERT(sc); ATH_TXQ_UNLOCK_ASSERT(txq); /* If unicast frame, update general statistics */ if (ni != NULL) { + an = ATH_NODE(ni); /* update statistics */ ath_tx_update_stats(sc, ts, bf); } @@ -4825,10 +4257,6 @@ ath_tx_proc_q0(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc_q0: txqs=0x%08x", txqs); @@ -4849,10 +4277,6 @@ ath_tx_proc_q0(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } @@ -4874,10 +4298,6 @@ ath_tx_proc_q0123(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc_q0123: txqs=0x%08x", txqs); @@ -4910,10 +4330,6 @@ ath_tx_proc_q0123(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } @@ -4934,10 +4350,6 @@ ath_tx_proc(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc: txqs=0x%08x", txqs); /* @@ -4963,10 +4375,6 @@ ath_tx_proc(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } #undef TXQACTIVE @@ -4993,10 +4401,6 @@ ath_txq_sched_tasklet(void *arg, int npending) sc->sc_txproc_cnt++; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_TX_LOCK(sc); for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { @@ -5005,10 +4409,6 @@ ath_txq_sched_tasklet(void *arg, int npending) } ATH_TX_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); @@ -5516,15 +4916,14 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ATH_PCU_LOCK(sc); - /* Disable interrupts */ - ath_hal_intrset(ah, 0); - /* Stop new RX/TX/interrupt completion */ if (ath_reset_grablock(sc, 1) == 0) { device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n", __func__); } + ath_hal_intrset(ah, 0); + /* Stop pending RX/TX completion */ ath_txrx_stop_locked(sc); @@ -5568,11 +4967,6 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) } sc->sc_diversity = ath_hal_getdiversity(ah); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, chan); @@ -5662,17 +5056,6 @@ ath_calibrate(void *arg) HAL_BOOL aniCal, shortCal = AH_FALSE; int nextcal; - ATH_LOCK_ASSERT(sc); - - /* - * Force the hardware awake for ANI work. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - - /* Skip trying to do this if we're in reset */ - if (sc->sc_inreset_cnt) - goto restart; - if (ic->ic_flags & IEEE80211_F_SCAN) /* defer, off channel */ goto restart; longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz); @@ -5702,7 +5085,6 @@ ath_calibrate(void *arg) sc->sc_doresetcal = AH_TRUE; taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask); callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc); - ath_power_restore_power_state(sc); return; } /* @@ -5774,10 +5156,6 @@ restart: __func__); /* NB: don't rearm timer */ } - /* - * Restore power state now that we're done. - */ - ath_power_restore_power_state(sc); } static void @@ -5863,10 +5241,6 @@ ath_set_channel(struct ieee80211com *ic) struct ifnet *ifp = ic->ic_ifp; struct ath_softc *sc = ifp->if_softc; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - (void) ath_chan_set(sc, ic->ic_curchan); /* * If we are returning to our bss channel then mark state @@ -5877,7 +5251,6 @@ ath_set_channel(struct ieee80211com *ic) ATH_LOCK(sc); if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan) sc->sc_syncbeacon = 1; - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); } @@ -5910,7 +5283,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) int i, error, stamode; u_int32_t rfilt; int csa_run_transition = 0; - enum ieee80211_state ostate = vap->iv_state; static const HAL_LED_STATE leds[] = { HAL_LED_INIT, /* IEEE80211_S_INIT */ @@ -5924,7 +5296,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) }; DPRINTF(sc, ATH_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[ostate], + ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); /* @@ -5936,34 +5308,10 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) */ IEEE80211_LOCK_ASSERT(ic); - /* Before we touch the hardware - wake it up */ - ATH_LOCK(sc); - /* - * If the NIC is in anything other than SLEEP state, - * we need to ensure that self-generated frames are - * set for PWRMGT=0. Otherwise we may end up with - * strange situations. - * - * XXX TODO: is this actually the case? :-) - */ - if (nstate != IEEE80211_S_SLEEP) - ath_power_setselfgen(sc, HAL_PM_AWAKE); - - /* - * Now, wake the thing up. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - - /* - * And stop the calibration callout whilst we have - * ATH_LOCK held. - */ - callout_stop(&sc->sc_cal_ch); - ATH_UNLOCK(sc); - - if (ostate == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN) + if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN) csa_run_transition = 1; + callout_drain(&sc->sc_cal_ch); ath_hal_setledstate(ah, leds[nstate]); /* set LED */ if (nstate == IEEE80211_S_SCAN) { @@ -5973,13 +5321,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * [re]setup beacons. Unblock the task q thread so * deferred interrupt processing is done. */ - - /* Ensure we stay awake during scan */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_hal_intrset(ah, sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS)); sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); @@ -5992,11 +5333,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) stamode = (vap->iv_opmode == IEEE80211_M_STA || vap->iv_opmode == IEEE80211_M_AHDEMO || vap->iv_opmode == IEEE80211_M_IBSS); - - /* - * XXX Dont need to do this (and others) if we've transitioned - * from SLEEP->RUN. - */ if (stamode && nstate == IEEE80211_S_RUN) { sc->sc_curaid = ni->ni_associd; IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid); @@ -6099,14 +5435,11 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * beacon to update the beacon timer and thus we * won't get notified of the missing beacons. */ - if (ostate != IEEE80211_S_RUN && - ostate != IEEE80211_S_SLEEP) { - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: STA; syncbeacon=1\n", __func__); - sc->sc_syncbeacon = 1; - - if (csa_run_transition) - ath_beacon_config(sc, vap); + sc->sc_syncbeacon = 1; +#if 0 + if (csa_run_transition) +#endif + ath_beacon_config(sc, vap); /* * PR: kern/175227 @@ -6120,8 +5453,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * timer fires (too often), leading to a STA * disassociation. */ - sc->sc_beacons = 1; - } + sc->sc_beacons = 1; break; case IEEE80211_M_MONITOR: /* @@ -6147,14 +5479,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - - /* - * Force awake for RUN mode. - */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - /* * Finally, start any timers and the task q thread * (in case we didn't go through SCAN state). @@ -6166,8 +5490,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: calibration disabled\n", __func__); } - ATH_UNLOCK(sc); - taskqueue_unblock(sc->sc_tq); } else if (nstate == IEEE80211_S_INIT) { /* @@ -6187,43 +5509,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #ifdef IEEE80211_SUPPORT_TDMA ath_hal_setcca(ah, AH_TRUE); #endif - } else if (nstate == IEEE80211_S_SLEEP) { - /* We're going to sleep, so transition appropriately */ - /* For now, only do this if we're a single STA vap */ - if (sc->sc_nvaps == 1 && - vap->iv_opmode == IEEE80211_M_STA) { - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: syncbeacon=%d\n", __func__, sc->sc_syncbeacon); - ATH_LOCK(sc); - /* - * Always at least set the self-generated - * frame config to set PWRMGT=1. - */ - ath_power_setselfgen(sc, HAL_PM_NETWORK_SLEEP); - - /* - * If we're not syncing beacons, transition - * to NETWORK_SLEEP. - * - * We stay awake if syncbeacon > 0 in case - * we need to listen for some beacons otherwise - * our beacon timer config may be wrong. - */ - if (sc->sc_syncbeacon == 0) { - ath_power_setpower(sc, HAL_PM_NETWORK_SLEEP); - } - ATH_UNLOCK(sc); - } } bad: ieee80211_free_node(ni); - - /* - * Restore the power state - either to what it was, or - * to network_sleep if it's alright. - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); return error; } @@ -6278,16 +5566,7 @@ ath_newassoc(struct ieee80211_node *ni, int isnew) an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate); an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate); - DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: reassoc; isnew=%d, is_powersave=%d\n", - __func__, - ni->ni_macaddr, - ":", - isnew, - an->an_is_powersave); - - ATH_NODE_LOCK(an); ath_rate_newassoc(sc, an, isnew); - ATH_NODE_UNLOCK(an); if (isnew && (vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey && @@ -6527,14 +5806,10 @@ ath_watchdog(void *arg) struct ath_softc *sc = arg; int do_reset = 0; - ATH_LOCK_ASSERT(sc); - if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) { struct ifnet *ifp = sc->sc_ifp; uint32_t hangs; - ath_power_set_power_state(sc, HAL_PM_AWAKE); - if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) && hangs != 0) { if_printf(ifp, "%s hang detected (0x%x)\n", @@ -6542,10 +5817,8 @@ ath_watchdog(void *arg) } else if_printf(ifp, "device timeout\n"); do_reset = 1; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; sc->sc_stats.ast_watchdog++; - - ath_power_restore_power_state(sc); } /* @@ -6643,13 +5916,6 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) goto bad; } } - - - ATH_LOCK(sc); - if (id != HAL_DIAG_REGS) - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) { if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; @@ -6659,12 +5925,6 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) } else { error = EINVAL; } - - ATH_LOCK(sc); - if (id != HAL_DIAG_REGS) - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - bad: if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) free(indata, M_TEMP); @@ -6687,17 +5947,14 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFFLAGS: + ATH_LOCK(sc); if (IS_RUNNING(ifp)) { /* * To avoid rescanning another access point, * do not call ath_init() here. Instead, * only reflect promisc mode settings. */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_mode_init(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } else if (ifp->if_flags & IFF_UP) { /* * Beware of being called during attach/detach @@ -6711,12 +5968,14 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (!sc->sc_invalid) ath_init(sc); /* XXX lose error */ } else { - ATH_LOCK(sc); ath_stop_locked(ifp); +#ifdef notyet + /* XXX must wakeup in places like ath_vap_delete */ if (!sc->sc_invalid) - ath_power_setpower(sc, HAL_PM_FULL_SLEEP); - ATH_UNLOCK(sc); + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); +#endif } + ATH_UNLOCK(sc); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -6724,10 +5983,8 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGATHSTATS: /* NB: embed these numbers to get a consistent view */ - sc->sc_stats.ast_tx_packets = if_get_counter_default(ifp, - IFCOUNTER_OPACKETS); - sc->sc_stats.ast_rx_packets = if_get_counter_default(ifp, - IFCOUNTER_IPACKETS); + sc->sc_stats.ast_tx_packets = ifp->if_opackets; + sc->sc_stats.ast_rx_packets = ifp->if_ipackets; sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi); sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi); #ifdef IEEE80211_SUPPORT_TDMA @@ -7084,7 +6341,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni, /* * Don't bother grabbing the lock unless the queue is empty. */ - if (an->an_swq_depth != 0) + if (&an->an_swq_depth != 0) return; if (an->an_is_powersave && @@ -7254,6 +6511,6 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m) MODULE_VERSION(if_ath, 1); MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ -#if defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ) || defined(ATH_DEBUG_ALQ) +#if defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ) MODULE_DEPEND(if_ath, alq, 1, 1, 1); #endif diff --git a/sys/dev/ath/if_ath_ahb.c b/sys/dev/ath/if_ath_ahb.c index ffe825d..59593b6 100644 --- a/sys/dev/ath/if_ath_ahb.c +++ b/sys/dev/ath/if_ath_ahb.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -56,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include @@ -153,30 +151,19 @@ ath_ahb_attach(device_t dev) eepromsize = ATH_EEPROM_DATA_SIZE * 2; } + rid = 0; device_printf(sc->sc_dev, "eeprom @ %p (%d bytes)\n", (void *) eepromaddr, eepromsize); - /* - * XXX this assumes that the parent device is the nexus - * and will just pass through requests for all of memory. - * - * Later on, when this has to attach off of the actual - * AHB, this won't work. - * - * Ideally this would be done in machdep code in mips/atheros/ - * and it'd expose the EEPROM via the firmware interface, - * so the ath/ath_ahb drivers can be loaded as modules - * after boot-time. - */ - psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, - &rid, (uintptr_t) eepromaddr, - (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE); + psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, + (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE); if (psc->sc_eeprom == NULL) { device_printf(dev, "cannot map eeprom space\n"); goto bad0; } - sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr); + /* XXX uintptr_t is a bandaid for ia64; to be fixed */ + sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) @@ -361,7 +348,6 @@ static driver_t ath_ahb_driver = { }; static devclass_t ath_devclass; DRIVER_MODULE(ath, nexus, ath_ahb_driver, ath_devclass, 0, 0); -DRIVER_MODULE(ath, apb, ath_ahb_driver, ath_devclass, 0, 0); MODULE_VERSION(ath, 1); MODULE_DEPEND(ath, wlan, 1, 1, 1); /* 802.11 media layer */ MODULE_DEPEND(ath, if_ath, 1, 1, 1); /* if_ath driver */ diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c index a672c71..11b0426 100644 --- a/sys/dev/ath/if_ath_beacon.c +++ b/sys/dev/ath/if_ath_beacon.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -382,7 +381,7 @@ ath_beacon_update(struct ieee80211vap *vap, int item) /* * Handle a beacon miss. */ -void +static void ath_beacon_miss(struct ath_softc *sc) { HAL_SURVEY_SAMPLE hs; @@ -749,11 +748,6 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) * * More thought is required here. */ - /* - * XXX can we even stop TX DMA here? Check what the - * reference driver does for cabq for beacons, given - * that stopping TX requires RX is paused. - */ ath_tx_draintxq(sc, cabq); } } @@ -921,7 +915,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) struct ieee80211_node *ni; u_int32_t nexttbtt, intval, tsftu; u_int32_t nexttbtt_u8, intval_u8; - u_int64_t tsf, tsf_beacon; + u_int64_t tsf; if (vap == NULL) vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ @@ -937,17 +931,9 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) ni = ieee80211_ref_node(vap->iv_bss); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - /* extract tstamp from last beacon and convert to TU */ nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4), LE_READ_4(ni->ni_tstamp.data)); - - tsf_beacon = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32; - tsf_beacon |= LE_READ_4(ni->ni_tstamp.data); - if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_MBSS) { /* @@ -993,63 +979,14 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) */ tsf = ath_hal_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; - - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: beacon tsf=%llu, hw tsf=%llu, nexttbtt=%u, tsftu=%u\n", - __func__, - (unsigned long long) tsf_beacon, - (unsigned long long) tsf, - nexttbtt, - tsftu); - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: beacon tsf=%llu, hw tsf=%llu, tsf delta=%lld\n", - __func__, - (unsigned long long) tsf_beacon, - (unsigned long long) tsf, - (long long) tsf - - (long long) tsf_beacon); - - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: nexttbtt=%llu, beacon tsf delta=%lld\n", - __func__, - (unsigned long long) nexttbtt, - (long long) ((long long) nexttbtt * 1024LL) - (long long) tsf_beacon); - - /* XXX cfpcount? */ - - if (nexttbtt > tsftu) { - uint32_t countdiff, oldtbtt, remainder; - - oldtbtt = nexttbtt; - remainder = (nexttbtt - tsftu) % intval; - nexttbtt = tsftu + remainder; - - countdiff = (oldtbtt - nexttbtt) / intval % dtimperiod; - if (dtimcount > countdiff) { - dtimcount -= countdiff; - } else { - dtimcount += dtimperiod - countdiff; - } - } else { //nexttbtt <= tsftu - uint32_t countdiff, oldtbtt, remainder; - - oldtbtt = nexttbtt; - remainder = (tsftu - nexttbtt) % intval; - nexttbtt = tsftu - remainder + intval; - countdiff = (nexttbtt - oldtbtt) / intval % dtimperiod; - if (dtimcount > countdiff) { - dtimcount -= countdiff; - } else { - dtimcount += dtimperiod - countdiff; + do { + nexttbtt += intval; + if (--dtimcount < 0) { + dtimcount = dtimperiod - 1; + if (--cfpcount < 0) + cfpcount = cfpperiod - 1; } - } - - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: adj nexttbtt=%llu, rx tsf delta=%lld\n", - __func__, - (unsigned long long) nexttbtt, - (long long) ((long long)nexttbtt * 1024LL) - (long long)tsf); - + } while (nexttbtt < tsftu); memset(&bs, 0, sizeof(bs)); bs.bs_intval = intval; bs.bs_nexttbtt = nexttbtt; @@ -1096,12 +1033,9 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod); DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u " - "nextdtim %u bmiss %u sleep %u cfp:period %u " - "maxdur %u next %u timoffset %u\n" + "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n" , __func__ - , tsf - , tsftu + , tsf, tsftu , bs.bs_intval , bs.bs_nexttbtt , bs.bs_dtimperiod @@ -1178,11 +1112,8 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) ath_beacon_start_adhoc(sc, vap); } + sc->sc_syncbeacon = 0; ieee80211_free_node(ni); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); #undef FUDGE #undef TSF_TO_TU } diff --git a/sys/dev/ath/if_ath_beacon.h b/sys/dev/ath/if_ath_beacon.h index a940268..f3f73d7 100644 --- a/sys/dev/ath/if_ath_beacon.h +++ b/sys/dev/ath/if_ath_beacon.h @@ -48,7 +48,5 @@ extern int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni); extern void ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf); extern void ath_beacon_free(struct ath_softc *sc); extern void ath_beacon_proc(void *arg, int pending); -extern void ath_beacon_miss(struct ath_softc *sc); #endif - diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c index b78f866..fff6f3b 100644 --- a/sys/dev/ath/if_ath_btcoex.c +++ b/sys/dev/ath/if_ath_btcoex.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -55,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include /* XXX for ether_sprintf */ @@ -188,72 +186,6 @@ ath_btcoex_cfg_wb225(struct ath_softc *sc) return (0); } -/* - * Initial AR9462 / (WB222) bluetooth coexistence settings, - * just for experimentation. - * - * Return 0 for OK; errno for error. - */ -static int -ath_btcoex_cfg_wb222(struct ath_softc *sc) -{ - HAL_BT_COEX_INFO btinfo; - HAL_BT_COEX_CONFIG btconfig; - struct ath_hal *ah = sc->sc_ah; - - if (! ath_hal_btcoex_supported(ah)) - return (EINVAL); - - bzero(&btinfo, sizeof(btinfo)); - bzero(&btconfig, sizeof(btconfig)); - - device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n"); - - btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */ - btinfo.bt_coex_config = HAL_BT_COEX_CFG_MCI; - - /* - * MCI uses a completely different interface to speak - * to the bluetooth module - it's a command based - * thing over a serial line, rather than - * state pins to/from the bluetooth module. - * - * So, the GPIO configuration, polarity, etc - * doesn't matter on MCI devices; it's just - * completely ignored by the HAL. - */ - btinfo.bt_gpio_bt_active = 4; - btinfo.bt_gpio_bt_priority = 8; - btinfo.bt_gpio_wlan_active = 5; - - btinfo.bt_active_polarity = 1; /* XXX not used */ - btinfo.bt_single_ant = 0; /* 2 antenna on WB222 */ - btinfo.bt_isolation = 0; /* in dB, not used */ - - ath_hal_btcoex_set_info(ah, &btinfo); - - btconfig.bt_time_extend = 0; - btconfig.bt_txstate_extend = 1; /* true */ - btconfig.bt_txframe_extend = 1; /* true */ - btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; - btconfig.bt_quiet_collision = 1; /* true */ - btconfig.bt_rxclear_polarity = 1; /* true */ - btconfig.bt_priority_time = 2; - btconfig.bt_first_slot_time = 5; - btconfig.bt_hold_rxclear = 1; /* true */ - - ath_hal_btcoex_set_config(ah, &btconfig); - - /* - * Enable antenna diversity. - */ - ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); - - return (0); -} - - - #if 0 /* @@ -309,8 +241,6 @@ ath_btcoex_attach(struct ath_softc *sc) if (strncmp(profname, "wb195", 5) == 0) { ret = ath_btcoex_cfg_wb195(sc); - } else if (strncmp(profname, "wb222", 5) == 0) { - ret = ath_btcoex_cfg_wb222(sc); } else if (strncmp(profname, "wb225", 5) == 0) { ret = ath_btcoex_cfg_wb225(sc); } else { diff --git a/sys/dev/ath/if_ath_debug.c b/sys/dev/ath/if_ath_debug.c index d21ad6f..e3c73f5 100644 --- a/sys/dev/ath/if_ath_debug.c +++ b/sys/dev/ath/if_ath_debug.c @@ -92,8 +92,9 @@ __FBSDID("$FreeBSD$"); uint64_t ath_debug = 0; SYSCTL_DECL(_hw_ath); -SYSCTL_QUAD(_hw_ath, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_debug, +SYSCTL_QUAD(_hw_ath, OID_AUTO, debug, CTLFLAG_RW, &ath_debug, 0, "control debugging printfs"); +TUNABLE_QUAD("hw.ath.debug", &ath_debug); void ath_printrxbuf(struct ath_softc *sc, const struct ath_buf *bf, diff --git a/sys/dev/ath/if_ath_debug.h b/sys/dev/ath/if_ath_debug.h index 40c0b9a..83597af 100644 --- a/sys/dev/ath/if_ath_debug.h +++ b/sys/dev/ath/if_ath_debug.h @@ -68,7 +68,6 @@ enum { ATH_DEBUG_SW_TX_FILT = 0x400000000ULL, /* SW TX FF */ ATH_DEBUG_NODE_PWRSAVE = 0x800000000ULL, /* node powersave */ ATH_DEBUG_DIVERSITY = 0x1000000000ULL, /* Diversity logic */ - ATH_DEBUG_PWRSAVE = 0x2000000000ULL, ATH_DEBUG_ANY = 0xffffffffffffffffULL }; diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c index fe99f10..6c2749f 100644 --- a/sys/dev/ath/if_ath_keycache.c +++ b/sys/dev/ath/if_ath_keycache.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -78,7 +77,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #ifdef ATH_DEBUG static void @@ -199,7 +197,6 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap, u_int8_t gmac[IEEE80211_ADDR_LEN]; const u_int8_t *mac; HAL_KEYVAL hk; - int ret; memset(&hk, 0, sizeof(hk)); /* @@ -253,19 +250,13 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap, } else mac = k->wk_macaddr; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); if (hk.kv_type == HAL_CIPHER_TKIP && (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { - ret = ath_keyset_tkip(sc, k, &hk, mac); + return ath_keyset_tkip(sc, k, &hk, mac); } else { KEYPRINTF(sc, k->wk_keyix, &hk, mac); - ret = ath_hal_keyset(ah, k->wk_keyix, &hk, mac); + return ath_hal_keyset(ah, k->wk_keyix, &hk, mac); } - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - return (ret); #undef N } @@ -500,8 +491,6 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_hal_keyreset(ah, keyix); /* * Handle split tx/rx keying required for TKIP with h/w MIC. @@ -525,8 +514,6 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) } } } - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); return 1; } diff --git a/sys/dev/ath/if_ath_led.c b/sys/dev/ath/if_ath_led.c index a55e036..33cc512 100644 --- a/sys/dev/ath/if_ath_led.c +++ b/sys/dev/ath/if_ath_led.c @@ -122,11 +122,6 @@ __FBSDID("$FreeBSD$"); void ath_led_config(struct ath_softc *sc) { - - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - /* Software LED blinking - GPIO controlled LED */ if (sc->sc_softled) { ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin, @@ -149,10 +144,6 @@ ath_led_config(struct ath_softc *sc) ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_led_net_pin, HAL_GPIO_OUTPUT_MUX_MAC_NETWORK_LED); } - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } static void diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c index f0a33a5..4ae81a3 100644 --- a/sys/dev/ath/if_ath_lna_div.c +++ b/sys/dev/ath/if_ath_lna_div.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -55,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include /* XXX for ether_sprintf */ @@ -209,10 +207,6 @@ bad: return (error); } -/* - * XXX need to low_rssi_thresh config from ath9k, to support CUS198 - * antenna diversity correctly. - */ static HAL_BOOL ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta, int main_rssi_avg, int alt_rssi_avg, int pkt_count) diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index 711e69e8..0c99bc7 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -128,19 +128,6 @@ extern void ath_start_task(void *arg, int npending); extern void ath_tx_dump(struct ath_softc *sc, struct ath_txq *txq); /* - * Power state tracking. - */ -extern void _ath_power_setpower(struct ath_softc *sc, int power_state, const char *file, int line); -extern void _ath_power_set_selfgen(struct ath_softc *sc, int power_state, const char *file, int line); -extern void _ath_power_set_power_state(struct ath_softc *sc, int power_state, const char *file, int line); -extern void _ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line); - -#define ath_power_setpower(sc, ps) _ath_power_setpower(sc, ps, __FILE__, __LINE__) -#define ath_power_setselfgen(sc, ps) _ath_power_set_selfgen(sc, ps, __FILE__, __LINE__) -#define ath_power_set_power_state(sc, ps) _ath_power_set_power_state(sc, ps, __FILE__, __LINE__) -#define ath_power_restore_power_state(sc) _ath_power_restore_power_state(sc, __FILE__, __LINE__) - -/* * Kick the frame TX task. */ static inline void diff --git a/sys/dev/ath/if_ath_pci.c b/sys/dev/ath/if_ath_pci.c index 5610882..91cb425 100644 --- a/sys/dev/ath/if_ath_pci.c +++ b/sys/dev/ath/if_ath_pci.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -54,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include @@ -80,98 +78,6 @@ struct ath_pci_softc { void *sc_ih; /* interrupt handler */ }; -/* - * XXX eventually this should be some system level definition - * so modules will hvae probe/attach information like USB. - * But for now.. - */ -struct pci_device_id { - int vendor_id; - int device_id; - - int sub_vendor_id; - int sub_device_id; - - int driver_data; - - int match_populated:1; - int match_vendor_id:1; - int match_device_id:1; - int match_sub_vendor_id:1; - int match_sub_device_id:1; -}; - -#define PCI_VDEVICE(v, s) \ - .vendor_id = (v), \ - .device_id = (s), \ - .match_populated = 1, \ - .match_vendor_id = 1, \ - .match_device_id = 1 - -#define PCI_DEVICE_SUB(v, d, dv, ds) \ - .match_populated = 1, \ - .vendor_id = (v), .match_vendor_id = 1, \ - .device_id = (d), .match_device_id = 1, \ - .sub_vendor_id = (dv), .match_sub_vendor_id = 1, \ - .sub_device_id = (ds), .match_sub_device_id = 1 - -#define PCI_VENDOR_ID_ATHEROS 0x168c -#define PCI_VENDOR_ID_SAMSUNG 0x144d -#define PCI_VENDOR_ID_AZWAVE 0x1a3b -#define PCI_VENDOR_ID_FOXCONN 0x105b -#define PCI_VENDOR_ID_ATTANSIC 0x1969 -#define PCI_VENDOR_ID_ASUSTEK 0x1043 -#define PCI_VENDOR_ID_DELL 0x1028 -#define PCI_VENDOR_ID_QMI 0x1a32 -#define PCI_VENDOR_ID_LENOVO 0x17aa -#define PCI_VENDOR_ID_HP 0x103c - -#include "if_ath_pci_devlist.h" - -/* - * Attempt to find a match for the given device in - * the given device table. - * - * Returns the device structure or NULL if no matching - * PCI device is found. - */ -static const struct pci_device_id * -ath_pci_probe_device(device_t dev, const struct pci_device_id *dev_table, int nentries) -{ - int i; - int vendor_id, device_id; - int sub_vendor_id, sub_device_id; - - vendor_id = pci_get_vendor(dev); - device_id = pci_get_device(dev); - sub_vendor_id = pci_get_subvendor(dev); - sub_device_id = pci_get_subdevice(dev); - - for (i = 0; i < nentries; i++) { - /* Don't match on non-populated (eg empty) entries */ - if (! dev_table[i].match_populated) - continue; - - if (dev_table[i].match_vendor_id && - (dev_table[i].vendor_id != vendor_id)) - continue; - if (dev_table[i].match_device_id && - (dev_table[i].device_id != device_id)) - continue; - if (dev_table[i].match_sub_vendor_id && - (dev_table[i].sub_vendor_id != sub_vendor_id)) - continue; - if (dev_table[i].match_sub_device_id && - (dev_table[i].sub_device_id != sub_device_id)) - continue; - - /* Match */ - return (&dev_table[i]); - } - - return (NULL); -} - #define BS_BAR 0x10 #define PCIR_RETRY_TIMEOUT 0x41 #define PCIR_CFG_PMCSR 0x48 @@ -242,15 +148,9 @@ ath_pci_attach(device_t dev) const struct firmware *fw = NULL; const char *buf; #endif - const struct pci_device_id *pd; sc->sc_dev = dev; - /* Do this lookup anyway; figure out what to do with it later */ - pd = ath_pci_probe_device(dev, ath_pci_id_table, nitems(ath_pci_id_table)); - if (pd) - sc->sc_pci_devinfo = pd->driver_data; - /* * Enable bus mastering. */ @@ -271,7 +171,8 @@ ath_pci_attach(device_t dev) device_printf(dev, "cannot map register space\n"); goto bad; } - sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr); + /* XXX uintptr_t is a bandaid for ia64; to be fixed */ + sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) @@ -279,13 +180,6 @@ ath_pci_attach(device_t dev) */ sc->sc_invalid = 1; - ATH_LOCK_INIT(sc); - ATH_PCU_LOCK_INIT(sc); - ATH_RX_LOCK_INIT(sc); - ATH_TX_LOCK_INIT(sc); - ATH_TX_IC_LOCK_INIT(sc); - ATH_TXSTATUS_LOCK_INIT(sc); - /* * Arrange interrupt line. */ @@ -336,7 +230,7 @@ ath_pci_attach(device_t dev) if (fw == NULL) { device_printf(dev, "%s: couldn't find firmware\n", __func__); - goto bad4; + goto bad3; } device_printf(dev, "%s: EEPROM firmware @ %p\n", @@ -346,20 +240,30 @@ ath_pci_attach(device_t dev) if (! sc->sc_eepromdata) { device_printf(dev, "%s: can't malloc eepromdata\n", __func__); - goto bad4; + goto bad3; } memcpy(sc->sc_eepromdata, fw->data, fw->datasize); firmware_put(fw, 0); } #endif /* ATH_EEPROM_FIRMWARE */ + ATH_LOCK_INIT(sc); + ATH_PCU_LOCK_INIT(sc); + ATH_RX_LOCK_INIT(sc); + ATH_TX_LOCK_INIT(sc); + ATH_TX_IC_LOCK_INIT(sc); + ATH_TXSTATUS_LOCK_INIT(sc); + error = ath_attach(pci_get_device(dev), sc); if (error == 0) /* success */ return 0; -#ifdef ATH_EEPROM_FIRMWARE -bad4: -#endif + ATH_TXSTATUS_LOCK_DESTROY(sc); + ATH_PCU_LOCK_DESTROY(sc); + ATH_RX_LOCK_DESTROY(sc); + ATH_TX_IC_LOCK_DESTROY(sc); + ATH_TX_LOCK_DESTROY(sc); + ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); @@ -367,14 +271,6 @@ bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr); - - ATH_TXSTATUS_LOCK_DESTROY(sc); - ATH_PCU_LOCK_DESTROY(sc); - ATH_RX_LOCK_DESTROY(sc); - ATH_TX_IC_LOCK_DESTROY(sc); - ATH_TX_LOCK_DESTROY(sc); - ATH_LOCK_DESTROY(sc); - bad: return (error); } diff --git a/sys/dev/ath/if_ath_pci_devlist.h b/sys/dev/ath/if_ath_pci_devlist.h deleted file mode 100644 index ae65909..0000000 --- a/sys/dev/ath/if_ath_pci_devlist.h +++ /dev/null @@ -1,669 +0,0 @@ -/*- - * Copyright (c) 2014 Qualcomm Atheros. - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * $FreeBSD$ - */ - -static const struct pci_device_id ath_pci_id_table[] = { - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0023) }, /* PCI */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0024) }, /* PCI-E */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0027) }, /* PCI */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0029) }, /* PCI */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002A) }, /* PCI-E */ - - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - PCI_VENDOR_ID_AZWAVE, - 0x1C71), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - PCI_VENDOR_ID_FOXCONN, - 0xE01F), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x11AD, /* LITEON */ - 0x6632), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x11AD, /* LITEON */ - 0x6642), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - PCI_VENDOR_ID_QMI, - 0x0306), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x185F, /* WNC */ - 0x309D), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x10CF, /* Fujitsu */ - 0x147C), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x10CF, /* Fujitsu */ - 0x147D), - .driver_data = ATH_PCI_D3_L1_WAR }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002A, - 0x10CF, /* Fujitsu */ - 0x1536), - .driver_data = ATH_PCI_D3_L1_WAR }, - - /* AR9285 card for Asus */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x002B, - PCI_VENDOR_ID_AZWAVE, - 0x2C37), - .driver_data = ATH_PCI_BT_ANT_DIV }, - - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002B) }, /* PCI-E */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002D) }, /* PCI */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002E) }, /* PCI-E */ - - /* Killer Wireless (3x3) */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0030, - 0x1A56, - 0x2000), - .driver_data = ATH_PCI_KILLER }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0030, - 0x1A56, - 0x2001), - .driver_data = ATH_PCI_KILLER }, - - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0030) }, /* PCI-E AR9300 */ - - /* PCI-E CUS198 */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x2086), - .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x1237), - .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x2126), - .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x126A), - .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV }, - - /* PCI-E CUS230 */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x2152), - .driver_data = ATH_PCI_CUS230 | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_FOXCONN, - 0xE075), - .driver_data = ATH_PCI_CUS230 | ATH_PCI_BT_ANT_DIV }, - - /* WB225 */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_ATHEROS, - 0x3119), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_ATHEROS, - 0x3122), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x185F, /* WNC */ - 0x3119), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x185F, /* WNC */ - 0x3027), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0x4105), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0x4106), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0x410D), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0x410E), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0x410F), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0xC706), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0xC680), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_SAMSUNG, - 0xC708), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_LENOVO, - 0x3218), - .driver_data = ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_LENOVO, - 0x3219), - .driver_data = ATH_PCI_BT_ANT_DIV }, - - /* AR9485 cards with PLL power-save disabled by default. */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x2C97), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x2100), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x1C56, /* ASKEY */ - 0x4001), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x11AD, /* LITEON */ - 0x6627), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x11AD, /* LITEON */ - 0x6628), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_FOXCONN, - 0xE04E), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_FOXCONN, - 0xE04F), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x144F, /* ASKEY */ - 0x7197), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x1B9A, /* XAVI */ - 0x2000), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x1B9A, /* XAVI */ - 0x2001), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x1186), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x1F86), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x1195), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_AZWAVE, - 0x1F95), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x1B9A, /* XAVI */ - 0x1C00), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - 0x1B9A, /* XAVI */ - 0x1C01), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0032, - PCI_VENDOR_ID_ASUSTEK, - 0x850D), - .driver_data = ATH_PCI_NO_PLL_PWRSAVE }, - - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0032) }, /* PCI-E AR9485 */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0033) }, /* PCI-E AR9580 */ - - /* PCI-E CUS217 */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_AZWAVE, - 0x2116), - .driver_data = ATH_PCI_CUS217 }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x11AD, /* LITEON */ - 0x6661), - .driver_data = ATH_PCI_CUS217 }, - - /* AR9462 with WoW support */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_ATHEROS, - 0x3117), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_LENOVO, - 0x3214), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_ATTANSIC, - 0x0091), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_AZWAVE, - 0x2110), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_ASUSTEK, - 0x850E), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x11AD, /* LITEON */ - 0x6631), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x11AD, /* LITEON */ - 0x6641), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - PCI_VENDOR_ID_HP, - 0x1864), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x14CD, /* USI */ - 0x0063), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x14CD, /* USI */ - 0x0064), - .driver_data = ATH_PCI_WOW }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0034, - 0x10CF, /* Fujitsu */ - 0x1783), - .driver_data = ATH_PCI_WOW }, - - /* Killer Wireless (2x2) */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0030, - 0x1A56, - 0x2003), - .driver_data = ATH_PCI_KILLER }, - - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0034) }, /* PCI-E AR9462 */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ - - /* CUS252 */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x3028), - .driver_data = ATH_PCI_CUS252 | - ATH_PCI_AR9565_2ANT | - ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x2176), - .driver_data = ATH_PCI_CUS252 | - ATH_PCI_AR9565_2ANT | - ATH_PCI_BT_ANT_DIV }, - - /* WB335 1-ANT */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_FOXCONN, - 0xE068), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x185F, /* WNC */ - 0xA119), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0632), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x06B2), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0842), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x6671), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x1B9A, /* XAVI */ - 0x2811), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x1B9A, /* XAVI */ - 0x2812), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x1B9A, /* XAVI */ - 0x28A1), - .driver_data = ATH_PCI_AR9565_1ANT }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x218A), - .driver_data = ATH_PCI_AR9565_1ANT }, - - /* WB335 1-ANT / Antenna Diversity */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x3025), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x3026), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x302B), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_FOXCONN, - 0xE069), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x185F, /* WNC */ - 0x3028), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0622), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0672), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0662), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x06A2), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0682), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x213A), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_HP, - 0x18E3), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_HP, - 0x217F), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_HP, - 0x2005), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_DELL, - 0x020C), - .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV }, - - /* WB335 2-ANT / Antenna-Diversity */ - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_SAMSUNG, - 0x411A), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_SAMSUNG, - 0x411B), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_SAMSUNG, - 0x411C), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_SAMSUNG, - 0x411D), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_SAMSUNG, - 0x411E), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x3027), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ATHEROS, - 0x302C), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0642), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0652), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0612), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0832), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x11AD, /* LITEON */ - 0x0692), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x2130), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x213B), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_AZWAVE, - 0x2182), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x144F, /* ASKEY */ - 0x7202), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x1B9A, /* XAVI */ - 0x2810), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x1B9A, /* XAVI */ - 0x28A2), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x185F, /* WNC */ - 0x3027), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - 0x185F, /* WNC */ - 0xA120), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_FOXCONN, - 0xE07F), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_FOXCONN, - 0xE081), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_LENOVO, - 0x3026), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_LENOVO, - 0x4026), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_ASUSTEK, - 0x85F2), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, - 0x0036, - PCI_VENDOR_ID_DELL, - 0x020E), - .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV }, - - /* PCI-E AR9565 (WB335) */ - { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0036), - .driver_data = ATH_PCI_BT_ANT_DIV }, - - { 0 } -}; - diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index bed9488..d9e212b 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -166,22 +165,10 @@ ath_calcrxfilter(struct ath_softc *sc) /* XXX ic->ic_monvaps != 0? */ if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC)) rfilt |= HAL_RX_FILTER_PROM; - - /* - * Only listen to all beacons if we're scanning. - * - * Otherwise we only really need to hear beacons from - * our own BSSID. - */ if (ic->ic_opmode == IEEE80211_M_STA || - ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss) { - if (sc->sc_do_mybeacon && ! sc->sc_scanning) { - rfilt |= HAL_RX_FILTER_MYBEACON; - } else { /* scanning, non-mybeacon chips */ - rfilt |= HAL_RX_FILTER_BEACON; - } - } - + ic->ic_opmode == IEEE80211_M_IBSS || + sc->sc_swbmiss || sc->sc_scanning) + rfilt |= HAL_RX_FILTER_BEACON; /* * NB: We don't recalculate the rx filter when * ic_protmode changes; otherwise we could do @@ -245,8 +232,6 @@ ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) struct mbuf *m; struct ath_desc *ds; - /* XXX TODO: ATH_RX_LOCK_ASSERT(sc); */ - m = bf->bf_m; if (m == NULL) { /* @@ -331,23 +316,6 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, { struct ieee80211vap *vap = ni->ni_vap; struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - uint64_t tsf_beacon_old, tsf_beacon; - uint64_t nexttbtt; - int64_t tsf_delta; - int32_t tsf_delta_bmiss; - int32_t tsf_remainder; - uint64_t tsf_beacon_target; - int tsf_intval; - - tsf_beacon_old = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32; - tsf_beacon_old |= LE_READ_4(ni->ni_tstamp.data); - -#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10) - tsf_intval = 1; - if (ni->ni_intval > 0) { - tsf_intval = TU_TO_TSF(ni->ni_intval); - } -#undef TU_TO_TSF /* * Call up first so subsequent work can use information @@ -359,79 +327,14 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, /* update rssi statistics for use by the hal */ /* XXX unlocked check against vap->iv_bss? */ ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi); - - tsf_beacon = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32; - tsf_beacon |= LE_READ_4(ni->ni_tstamp.data); - - nexttbtt = ath_hal_getnexttbtt(sc->sc_ah); - - /* - * Let's calculate the delta and remainder, so we can see - * if the beacon timer from the AP is varying by more than - * a few TU. (Which would be a huge, huge problem.) - */ - tsf_delta = (long long) tsf_beacon - (long long) tsf_beacon_old; - - tsf_delta_bmiss = tsf_delta / tsf_intval; - - /* - * If our delta is greater than half the beacon interval, - * let's round the bmiss value up to the next beacon - * interval. Ie, we're running really, really early - * on the next beacon. - */ - if (tsf_delta % tsf_intval > (tsf_intval / 2)) - tsf_delta_bmiss ++; - - tsf_beacon_target = tsf_beacon_old + - (((unsigned long long) tsf_delta_bmiss) * (long long) tsf_intval); - - /* - * The remainder using '%' is between 0 .. intval-1. - * If we're actually running too fast, then the remainder - * will be some large number just under intval-1. - * So we need to look at whether we're running - * before or after the target beacon interval - * and if we are, modify how we do the remainder - * calculation. - */ - if (tsf_beacon < tsf_beacon_target) { - tsf_remainder = - -(tsf_intval - ((tsf_beacon - tsf_beacon_old) % tsf_intval)); - } else { - tsf_remainder = (tsf_beacon - tsf_beacon_old) % tsf_intval; - } - - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: old_tsf=%llu, new_tsf=%llu, target_tsf=%llu, delta=%lld, bmiss=%d, remainder=%d\n", - __func__, - (unsigned long long) tsf_beacon_old, - (unsigned long long) tsf_beacon, - (unsigned long long) tsf_beacon_target, - (long long) tsf_delta, - tsf_delta_bmiss, - tsf_remainder); - - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: tsf=%llu, nexttbtt=%llu, delta=%d\n", - __func__, - (unsigned long long) tsf_beacon, - (unsigned long long) nexttbtt, - (int32_t) tsf_beacon - (int32_t) nexttbtt + tsf_intval); - if (sc->sc_syncbeacon && - ni == vap->iv_bss && - (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) { - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: syncbeacon=1; syncing\n", - __func__); + ni == vap->iv_bss && vap->iv_state == IEEE80211_S_RUN) { /* * Resync beacon timers using the tsf of the beacon * frame we just received. */ ath_beacon_config(sc, vap); - sc->sc_syncbeacon = 0; } - - /* fall thru... */ case IEEE80211_FC0_SUBTYPE_PROBE_RESP: if (vap->iv_opmode == IEEE80211_M_IBSS && @@ -704,7 +607,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, rs->rs_keyix-32 : rs->rs_keyix); } } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; rx_error: /* * Cleanup any pending partial frame. @@ -830,7 +733,7 @@ rx_accept: rs->rs_antenna |= 0x4; } - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; sc->sc_stats.ast_ant_rx[rs->rs_antenna]++; /* @@ -976,14 +879,6 @@ rx_next: #define ATH_RX_MAX 128 -/* - * XXX TODO: break out the "get buffers" from "call ath_rx_pkt()" like - * the EDMA code does. - * - * XXX TODO: then, do all of the RX list management stuff inside - * ATH_RX_LOCK() so we don't end up potentially racing. The EDMA - * code is doing it right. - */ static void ath_rx_proc(struct ath_softc *sc, int resched) { @@ -1005,7 +900,6 @@ ath_rx_proc(struct ath_softc *sc, int resched) u_int64_t tsf; int npkts = 0; int kickpcu = 0; - int ret; /* XXX we must not hold the ATH_LOCK here */ ATH_UNLOCK_ASSERT(sc); @@ -1016,10 +910,6 @@ ath_rx_proc(struct ath_softc *sc, int resched) kickpcu = sc->sc_kickpcu; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__); ngood = 0; nf = ath_hal_getchannoise(ah, sc->sc_curchan); @@ -1105,26 +995,8 @@ ath_rx_proc(struct ath_softc *sc, int resched) if (ath_rx_pkt(sc, rs, status, tsf, nf, HAL_RX_QUEUE_HP, bf, m)) ngood++; rx_proc_next: - /* - * If there's a holding buffer, insert that onto - * the RX list; the hardware is now definitely not pointing - * to it now. - */ - ret = 0; - if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf != NULL) { - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, - sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf, - bf_list); - ret = ath_rxbuf_init(sc, - sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf); - } - /* - * Next, throw our buffer into the holding entry. The hardware - * may use the descriptor to read the link pointer before - * DMAing the next descriptor in to write out a packet. - */ - sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = bf; - } while (ret == 0); + TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); + } while (ath_rxbuf_init(sc, bf) == 0); /* rx signal state monitoring */ ath_hal_rxmonitor(ah, &sc->sc_halstats, sc->sc_curchan); @@ -1156,13 +1028,6 @@ rx_proc_next: * constantly write over the same frame, leading * the RX driver code here to get heavily confused. */ - /* - * XXX Has RX DMA stopped enough here to just call - * ath_startrecv()? - * XXX Do we need to use the holding buffer to restart - * RX DMA by appending entries to the final - * descriptor? Quite likely. - */ #if 1 ath_startrecv(sc); #else @@ -1200,13 +1065,6 @@ rx_proc_next: #undef PA2DESC /* - * Put the hardware to sleep again if we're done with it. - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - /* * If we hit the maximum number of frames in this round, * reschedule for another immediate pass. This gives * the TX and TX completion routines time to run, which @@ -1253,58 +1111,6 @@ ath_legacy_flushrecv(struct ath_softc *sc) ath_rx_proc(sc, 0); } -static void -ath_legacy_flush_rxpending(struct ath_softc *sc) -{ - - /* XXX ATH_RX_LOCK_ASSERT(sc); */ - - if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending != NULL) { - m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending); - sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; - } - if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending != NULL) { - m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending); - sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; - } -} - -static int -ath_legacy_flush_rxholdbf(struct ath_softc *sc) -{ - struct ath_buf *bf; - - /* XXX ATH_RX_LOCK_ASSERT(sc); */ - /* - * If there are RX holding buffers, free them here and return - * them to the list. - * - * XXX should just verify that bf->bf_m is NULL, as it must - * be at this point! - */ - bf = sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf; - if (bf != NULL) { - if (bf->bf_m != NULL) - m_freem(bf->bf_m); - bf->bf_m = NULL; - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); - (void) ath_rxbuf_init(sc, bf); - } - sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = NULL; - - bf = sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf; - if (bf != NULL) { - if (bf->bf_m != NULL) - m_freem(bf->bf_m); - bf->bf_m = NULL; - TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); - (void) ath_rxbuf_init(sc, bf); - } - sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf = NULL; - - return (0); -} - /* * Disable the receive h/w in preparation for a reset. */ @@ -1316,8 +1122,6 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay) ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) struct ath_hal *ah = sc->sc_ah; - ATH_RX_LOCK(sc); - ath_hal_stoppcurecv(ah); /* disable PCU */ ath_hal_setrxfilter(ah, 0); /* clear recv filter */ ath_hal_stopdmarecv(ah); /* disable DMA engine */ @@ -1351,23 +1155,22 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay) } } #endif - - (void) ath_legacy_flush_rxpending(sc); - (void) ath_legacy_flush_rxholdbf(sc); - + /* + * Free both high/low RX pending, just in case. + */ + if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending != NULL) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; + } + if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending != NULL) { + m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending); + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; + } sc->sc_rxlink = NULL; /* just in case */ - - ATH_RX_UNLOCK(sc); #undef PA2DESC } /* - * XXX TODO: something was calling startrecv without calling - * stoprecv. Let's figure out what/why. It was showing up - * as a mbuf leak (rxpending) and ath_buf leak (holdbf.) - */ - -/* * Enable the receive h/w following a reset. */ static int @@ -1376,18 +1179,9 @@ ath_legacy_startrecv(struct ath_softc *sc) struct ath_hal *ah = sc->sc_ah; struct ath_buf *bf; - ATH_RX_LOCK(sc); - - /* - * XXX should verify these are already all NULL! - */ sc->sc_rxlink = NULL; - (void) ath_legacy_flush_rxpending(sc); - (void) ath_legacy_flush_rxholdbf(sc); - - /* - * Re-chain all of the buffers in the RX buffer list. - */ + sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; + sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL; TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { int error = ath_rxbuf_init(sc, bf); if (error != 0) { @@ -1403,8 +1197,6 @@ ath_legacy_startrecv(struct ath_softc *sc) ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ - - ATH_RX_UNLOCK(sc); return 0; } diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c index 7aa818f..2be8627 100644 --- a/sys/dev/ath/if_ath_rx_edma.c +++ b/sys/dev/ath/if_ath_rx_edma.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -160,20 +159,10 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay) struct ath_hal *ah = sc->sc_ah; ATH_RX_LOCK(sc); - ath_hal_stoppcurecv(ah); ath_hal_setrxfilter(ah, 0); + ath_hal_stopdmarecv(ah); - /* - * - */ - if (ath_hal_stopdmarecv(ah) == AH_TRUE) - sc->sc_rx_stopped = 1; - - /* - * Give the various bus FIFOs (not EDMA descriptor FIFO) - * time to finish flushing out data. - */ DELAY(3000); /* Flush RX pending for each queue */ @@ -228,6 +217,10 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) /* * Start receive. + * + * XXX TODO: this needs to reallocate the FIFO entries when a reset + * occurs, in case the FIFO is filled up and no new descriptors get + * thrown into the FIFO. */ static int ath_edma_startrecv(struct ath_softc *sc) @@ -236,31 +229,35 @@ ath_edma_startrecv(struct ath_softc *sc) ATH_RX_LOCK(sc); - /* - * Sanity check - are we being called whilst RX - * isn't stopped? If so, we may end up pushing - * too many entries into the RX FIFO and - * badness occurs. - */ - /* Enable RX FIFO */ ath_hal_rxena(ah); /* - * In theory the hardware has been initialised, right? + * Entries should only be written out if the + * FIFO is empty. + * + * XXX This isn't correct. I should be looking + * at the value of AR_RXDP_SIZE (0x0070) to determine + * how many entries are in here. + * + * A warm reset will clear the registers but not the FIFO. + * + * And I believe this is actually the address of the last + * handled buffer rather than the current FIFO pointer. + * So if no frames have been (yet) seen, we'll reinit the + * FIFO. + * + * I'll chase that up at some point. */ - if (sc->sc_rx_resetted == 1) { + if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_HP) == 0) { DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Re-initing HP FIFO\n", __func__); ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP); + } + if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_LP) == 0) { DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Re-initing LP FIFO\n", __func__); ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_LP); - sc->sc_rx_resetted = 0; - } else { - device_printf(sc->sc_dev, - "%s: called without resetting chip?\n", - __func__); } /* Add up to m_fifolen entries in each queue */ @@ -268,9 +265,6 @@ ath_edma_startrecv(struct ath_softc *sc) * These must occur after the above write so the FIFO buffers * are pushed/tracked in the same order as the hardware will * process them. - * - * XXX TODO: is this really necessary? We should've stopped - * the hardware already and reinitialised it, so it's a no-op. */ ath_edma_rxfifo_alloc(sc, HAL_RX_QUEUE_HP, sc->sc_rxedma[HAL_RX_QUEUE_HP].m_fifolen); @@ -281,11 +275,6 @@ ath_edma_startrecv(struct ath_softc *sc) ath_mode_init(sc); ath_hal_startpcurecv(ah); - /* - * We're now doing RX DMA! - */ - sc->sc_rx_stopped = 0; - ATH_RX_UNLOCK(sc); return (0); @@ -296,16 +285,7 @@ ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, int dosched) { - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_edma_recv_proc_queue(sc, qtype, dosched); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); } @@ -313,17 +293,8 @@ static void ath_edma_recv_sched(struct ath_softc *sc, int dosched) { - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, dosched); ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, dosched); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); } @@ -337,10 +308,6 @@ ath_edma_recv_flush(struct ath_softc *sc) sc->sc_rxproc_cnt++; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - /* * Flush any active frames from FIFO -> deferred list */ @@ -350,18 +317,9 @@ ath_edma_recv_flush(struct ath_softc *sc) /* * Process what's in the deferred queue */ - /* - * XXX: If we read the tsf/channoise here and then pass it in, - * we could restore the power state before processing - * the deferred queue. - */ ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 0); ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 0); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ATH_PCU_LOCK(sc); sc->sc_rxproc_cnt--; ATH_PCU_UNLOCK(sc); @@ -390,21 +348,6 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, ATH_RX_LOCK(sc); -#if 1 - if (sc->sc_rx_resetted == 1) { - /* - * XXX We shouldn't ever be scheduled if - * receive has been stopped - so complain - * loudly! - */ - device_printf(sc->sc_dev, - "%s: sc_rx_resetted=1! Bad!\n", - __func__); - ATH_RX_UNLOCK(sc); - return; - } -#endif - do { bf = re->m_fifo[re->m_fifo_head]; /* This shouldn't occur! */ @@ -476,6 +419,24 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, "ath edma rx proc: npkts=%d\n", npkts); + /* Handle resched and kickpcu appropriately */ + ATH_PCU_LOCK(sc); + if (dosched && sc->sc_kickpcu) { + ATH_KTR(sc, ATH_KTR_ERROR, 0, + "ath_edma_recv_proc_queue(): kickpcu"); + if (npkts > 0) + device_printf(sc->sc_dev, + "%s: handled npkts %d\n", + __func__, npkts); + + /* + * XXX TODO: what should occur here? Just re-poke and + * re-enable the RX FIFO? + */ + sc->sc_kickpcu = 0; + } + ATH_PCU_UNLOCK(sc); + return; } @@ -488,20 +449,18 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, static void ath_edma_flush_deferred_queue(struct ath_softc *sc) { - struct ath_buf *bf; + struct ath_buf *bf, *next; ATH_RX_LOCK_ASSERT(sc); /* Free in one set, inside the lock */ - while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP])) { - bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP]); - TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf, bf_list); + TAILQ_FOREACH_SAFE(bf, + &sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf_list, next) { /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } - while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP])) { - bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP]); - TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf, bf_list); + TAILQ_FOREACH_SAFE(bf, + &sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf_list, next) { /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } @@ -535,10 +494,6 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, ATH_RX_UNLOCK(sc); /* Handle the completed descriptors */ - /* - * XXX is this SAFE call needed? The ath_buf entries - * aren't modified by ath_rx_pkt, right? - */ TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) { /* * Skip the RX descriptor status - start at the data offset @@ -564,9 +519,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, /* Free in one set, inside the lock */ ATH_RX_LOCK(sc); - while (! TAILQ_EMPTY(&rxlist)) { - bf = TAILQ_FIRST(&rxlist); - TAILQ_REMOVE(&rxlist, bf, bf_list); + TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) { /* Free the buffer/mbuf */ ath_edma_rxbuf_free(sc, bf); } @@ -598,25 +551,12 @@ ath_edma_recv_tasklet(void *arg, int npending) sc->sc_rxproc_cnt++; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1); ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1); ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 1); ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 1); - /* - * XXX: If we read the tsf/channoise here and then pass it in, - * we could restore the power state before processing - * the deferred queue. - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - /* XXX inside IF_LOCK ? */ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { #ifdef IEEE80211_SUPPORT_SUPERG @@ -895,13 +835,10 @@ ath_edma_setup_rxfifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) qtype); return (-EINVAL); } - - if (bootverbose) - device_printf(sc->sc_dev, - "%s: type=%d, FIFO depth = %d entries\n", - __func__, - qtype, - re->m_fifolen); + device_printf(sc->sc_dev, "%s: type=%d, FIFO depth = %d entries\n", + __func__, + qtype, + re->m_fifolen); /* Allocate ath_buf FIFO array, pre-zero'ed */ re->m_fifo = malloc(sizeof(struct ath_buf *) * re->m_fifolen, @@ -992,12 +929,10 @@ ath_recv_setup_edma(struct ath_softc *sc) (void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize - sc->sc_rx_statuslen); - if (bootverbose) { - device_printf(sc->sc_dev, "RX status length: %d\n", - sc->sc_rx_statuslen); - device_printf(sc->sc_dev, "RX buffer size: %d\n", - sc->sc_edma_bufsize); - } + device_printf(sc->sc_dev, "RX status length: %d\n", + sc->sc_rx_statuslen); + device_printf(sc->sc_dev, "RX buffer size: %d\n", + sc->sc_edma_bufsize); sc->sc_rx.recv_stop = ath_edma_stoprecv; sc->sc_rx.recv_start = ath_edma_startrecv; diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c index e4afdae..5cfb1a9 100644 --- a/sys/dev/ath/if_ath_spectral.c +++ b/sys/dev/ath/if_ath_spectral.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -54,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include /* XXX for ether_sprintf */ diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index 45c8ae4..0a5719a 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -108,26 +107,13 @@ static int ath_sysctl_slottime(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int slottime; + u_int slottime = ath_hal_getslottime(sc->sc_ah); int error; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - slottime = ath_hal_getslottime(sc->sc_ah); - ATH_UNLOCK(sc); - error = sysctl_handle_int(oidp, &slottime, 0, req); if (error || !req->newptr) - goto finish; - - error = !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0; - -finish: - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - return error; + return error; + return !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0; } static int @@ -413,14 +399,12 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS) ATH_RX_LOCK(sc); for (i = 0; i < 2; i++) { - printf("%d: fifolen: %d/%d; head=%d; tail=%d; m_pending=%p, m_holdbf=%p\n", + printf("%d: fifolen: %d/%d; head=%d; tail=%d\n", i, sc->sc_rxedma[i].m_fifo_depth, sc->sc_rxedma[i].m_fifolen, sc->sc_rxedma[i].m_fifo_head, - sc->sc_rxedma[i].m_fifo_tail, - sc->sc_rxedma[i].m_rxpending, - sc->sc_rxedma[i].m_holdbf); + sc->sc_rxedma[i].m_fifo_tail); } i = 0; TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { @@ -446,15 +430,7 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) return error; if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) return EINVAL; - /* - * Earlier chips (< AR5212) have up to 8 GPIO - * pins exposed. - * - * AR5416 and later chips have many more GPIO - * pins (up to 16) so the mask is expanded to - * four bits. - */ - sc->sc_rfsilentpin = rfsilent & 0x3c; + sc->sc_rfsilentpin = rfsilent & 0x1c; sc->sc_rfsilentpol = (rfsilent & 0x2) != 0; return 0; } diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c index de1a91c..c075d01 100644 --- a/sys/dev/ath/if_ath_tdma.c +++ b/sys/dev/ath/if_ath_tdma.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -477,19 +476,16 @@ ath_tdma_update(struct ieee80211_node *ni, DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, "rs->rstamp %llu rstamp %llu tsf %llu txtime %d, nextslot %llu, " "nextslottu %d, nextslottume %d\n", - (unsigned long long) rs->rs_tstamp, - (unsigned long long) rstamp, - (unsigned long long) tsf, txtime, - (unsigned long long) nextslot, - nextslottu, TSF_TO_TU(nextslot >> 32, nextslot)); + (unsigned long long) rs->rs_tstamp, rstamp, tsf, txtime, + nextslot, nextslottu, TSF_TO_TU(nextslot >> 32, nextslot)); DPRINTF(sc, ATH_DEBUG_TDMA, " beacon tstamp: %llu (0x%016llx)\n", - (unsigned long long) le64toh(ni->ni_tstamp.tsf), - (unsigned long long) le64toh(ni->ni_tstamp.tsf)); + le64toh(ni->ni_tstamp.tsf), + le64toh(ni->ni_tstamp.tsf)); DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, "nexttbtt %llu (0x%08llx) tsfdelta %d avg +%d/-%d\n", - (unsigned long long) nexttbtt, + nexttbtt, (long long) nexttbtt, tsfdelta, TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam)); @@ -583,7 +579,7 @@ ath_tdma_update(struct ieee80211_node *ni, DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, "%s: calling ath_hal_adjusttsf: TSF=%llu, tsfdelta=%d\n", __func__, - (unsigned long long) tsf, + tsf, tsfdelta); #ifdef ATH_DEBUG_ALQ diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 096278e..8bacd92 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -59,12 +59,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include -#include #include #include #include @@ -761,21 +759,37 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq, ("ath_tx_handoff_hw called for mcast queue")); /* - * XXX We should instead just verify that sc_txstart_cnt - * or ath_txproc_cnt > 0. That would mean that - * the reset is going to be waiting for us to complete. + * XXX racy, should hold the PCU lock when checking this, + * and also should ensure that the TX counter is >0! */ - if (sc->sc_txproc_cnt == 0 && sc->sc_txstart_cnt == 0) { - device_printf(sc->sc_dev, - "%s: TX dispatch without holding txcount/txstart refcnt!\n", - __func__); - } + KASSERT((sc->sc_inreset_cnt == 0), + ("%s: TX during reset?\n", __func__)); +#if 0 /* - * XXX .. this is going to cause the hardware to get upset; - * so we really should find some way to drop or queue - * things. + * This causes a LOR. Find out where the PCU lock is being + * held whilst the TXQ lock is grabbed - that shouldn't + * be occuring. */ + ATH_PCU_LOCK(sc); + if (sc->sc_inreset_cnt) { + ATH_PCU_UNLOCK(sc); + DPRINTF(sc, ATH_DEBUG_RESET, + "%s: called with sc_in_reset != 0\n", + __func__); + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: queued: TXDP[%u] = %p (%p) depth %d\n", + __func__, txq->axq_qnum, + (caddr_t)bf->bf_daddr, bf->bf_desc, + txq->axq_depth); + /* XXX axq_link needs to be set and updated! */ + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); + if (bf->bf_state.bfs_aggr) + txq->axq_aggr_depth++; + return; + } + ATH_PCU_UNLOCK(sc); +#endif ATH_TXQ_LOCK(txq); @@ -1599,7 +1613,6 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, error = ath_tx_dmasetup(sc, bf, m0); if (error != 0) return error; - KASSERT((ni != NULL), ("%s: ni=NULL!", __func__)); bf->bf_node = ni; /* NB: held reference */ m0 = bf->bf_m; /* NB: may have changed */ wh = mtod(m0, struct ieee80211_frame *); @@ -2091,7 +2104,6 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, int do_override; uint8_t type, subtype; int queue_to_head; - struct ath_node *an = ATH_NODE(ni); ATH_TX_LOCK_ASSERT(sc); @@ -2151,7 +2163,6 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, return error; m0 = bf->bf_m; /* NB: may have changed */ wh = mtod(m0, struct ieee80211_frame *); - KASSERT((ni != NULL), ("%s: ni=NULL!", __func__)); bf->bf_node = ni; /* NB: held reference */ /* Always enable CLRDMASK for raw frames for now.. */ @@ -2170,24 +2181,12 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, rt = sc->sc_currates; KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); - - /* Fetch first rate information */ rix = ath_tx_findrix(sc, params->ibp_rate0); - try0 = params->ibp_try0; - - /* - * Override EAPOL rate as appropriate. - */ - if (m0->m_flags & M_EAPOL) { - /* XXX? maybe always use long preamble? */ - rix = an->an_mgmtrix; - try0 = ATH_TXMAXTRY; /* XXX?too many? */ - } - txrate = rt->info[rix].rateCode; if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) txrate |= rt->info[rix].shortPreamble; sc->sc_txrix = rix; + try0 = params->ibp_try0; ismrr = (params->ibp_try1 != 0); txantenna = params->ibp_pri >> 2; if (txantenna == 0) /* XXX? */ @@ -2260,7 +2259,8 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, /* Blank the legacy rate array */ bzero(&bf->bf_state.bfs_rc, sizeof(bf->bf_state.bfs_rc)); - bf->bf_state.bfs_rc[0].rix = rix; + bf->bf_state.bfs_rc[0].rix = + ath_tx_findrix(sc, params->ibp_rate0); bf->bf_state.bfs_rc[0].tries = try0; bf->bf_state.bfs_rc[0].ratecode = txrate; @@ -2352,16 +2352,11 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, "%s: sc_inreset_cnt > 0; bailing\n", __func__); error = EIO; ATH_PCU_UNLOCK(sc); - goto badbad; + goto bad0; } sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - /* Wake the hardware up already */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_TX_LOCK(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { @@ -2424,7 +2419,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, } } sc->sc_wd_timer = 5; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; sc->sc_stats.ast_tx_raw++; /* @@ -2440,14 +2435,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); - - /* Put the hardware back to sleep if required */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - return 0; - bad2: ATH_KTR(sc, ATH_KTR_TX, 3, "ath_raw_xmit: bad2: m=%p, params=%p, " "bf=%p", @@ -2457,23 +2445,17 @@ bad2: ATH_TXBUF_LOCK(sc); ath_returnbuf_head(sc, bf); ATH_TXBUF_UNLOCK(sc); - bad: + ATH_TX_UNLOCK(sc); ATH_PCU_LOCK(sc); sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); - - /* Put the hardware back to sleep if required */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - -badbad: +bad0: ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p", m, params); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; sc->sc_stats.ast_tx_raw_fail++; ieee80211_free_node(ni); @@ -2766,8 +2748,8 @@ ath_tx_update_baw(struct ath_softc *sc, struct ath_node *an, INCR(tid->baw_head, ATH_TID_MAX_BUFS); } DPRINTF(sc, ATH_DEBUG_SW_TX_BAW, - "%s: tid=%d: baw is now %d:%d, baw head=%d\n", - __func__, tid->tid, tap->txa_start, tap->txa_wnd, tid->baw_head); + "%s: baw is now %d:%d, baw head=%d\n", + __func__, tap->txa_start, tap->txa_wnd, tid->baw_head); } static void @@ -3260,11 +3242,8 @@ ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid) ATH_TX_LOCK_ASSERT(sc); tid->paused++; - DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: [%6D]: tid=%d, paused = %d\n", - __func__, - tid->an->an_node.ni_macaddr, ":", - tid->tid, - tid->paused); + DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: paused = %d\n", + __func__, tid->paused); } /* @@ -3281,21 +3260,15 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid) * until it's actually resolved. */ if (tid->paused == 0) { - device_printf(sc->sc_dev, - "%s: [%6D]: tid=%d, paused=0?\n", - __func__, - tid->an->an_node.ni_macaddr, ":", - tid->tid); + DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, + "%s: %6D: paused=0?\n", __func__, + tid->an->an_node.ni_macaddr, ":"); } else { tid->paused--; } - DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, - "%s: [%6D]: tid=%d, unpaused = %d\n", - __func__, - tid->an->an_node.ni_macaddr, ":", - tid->tid, - tid->paused); + DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n", + __func__, tid->paused); if (tid->paused) return; @@ -3361,8 +3334,8 @@ ath_tx_tid_filt_comp_buf(struct ath_softc *sc, struct ath_tid *tid, ATH_TX_LOCK_ASSERT(sc); if (! tid->isfiltered) { - DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: tid=%d; filter transition\n", - __func__, tid->tid); + DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: filter transition\n", + __func__); tid->isfiltered = 1; ath_tx_tid_pause(sc, tid); } @@ -3382,20 +3355,15 @@ static void ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid) { struct ath_buf *bf; - int do_resume = 0; ATH_TX_LOCK_ASSERT(sc); if (tid->hwq_depth != 0) return; - DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: tid=%d, hwq=0, transition back\n", - __func__, tid->tid); - if (tid->isfiltered == 1) { - tid->isfiltered = 0; - do_resume = 1; - } - + DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n", + __func__); + tid->isfiltered = 0; /* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */ ath_tx_set_clrdmask(sc, tid->an); @@ -3405,21 +3373,16 @@ ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid) ATH_TID_INSERT_HEAD(tid, bf, bf_list); } - /* And only resume if we had paused before */ - if (do_resume) - ath_tx_tid_resume(sc, tid); + ath_tx_tid_resume(sc, tid); } /* * Called when a single (aggregate or otherwise) frame is completed. * - * Returns 0 if the buffer could be added to the filtered list - * (cloned or otherwise), 1 if the buffer couldn't be added to the + * Returns 1 if the buffer could be added to the filtered list + * (cloned or otherwise), 0 if the buffer couldn't be added to the * filtered list (failed clone; expired retry) and the caller should * free it and handle it like a failure (eg by sending a BAR.) - * - * since the buffer may be cloned, bf must be not touched after this - * if the return value is 0. */ static int ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid, @@ -3439,9 +3402,8 @@ ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid, "%s: bf=%p, seqno=%d, exceeded retries\n", __func__, bf, - SEQNO(bf->bf_state.bfs_seqno)); - retval = 1; /* error */ - goto finish; + bf->bf_state.bfs_seqno); + return (0); } /* @@ -3461,12 +3423,11 @@ ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid, DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: busy buffer couldn't be cloned (%p)!\n", __func__, bf); - retval = 1; /* error */ + retval = 1; } else { ath_tx_tid_filt_comp_buf(sc, tid, nbf); - retval = 0; /* ok */ + retval = 0; } -finish: ath_tx_tid_filt_comp_complete(sc, tid); return (retval); @@ -3491,11 +3452,10 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, if (bf->bf_state.bfs_retries > SWMAX_RETRIES) { sc->sc_stats.ast_tx_swretrymax++; DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, - "%s: tid=%d, bf=%p, seqno=%d, exceeded retries\n", + "%s: bf=%p, seqno=%d, exceeded retries\n", __func__, - tid->tid, bf, - SEQNO(bf->bf_state.bfs_seqno)); + bf->bf_state.bfs_seqno); TAILQ_INSERT_TAIL(bf_q, bf, bf_list); goto next; } @@ -3503,8 +3463,8 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, if (bf->bf_flags & ATH_BUF_BUSY) { nbf = ath_tx_retry_clone(sc, tid->an, tid, bf); DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, - "%s: tid=%d, busy buffer cloned: %p -> %p, seqno=%d\n", - __func__, tid->tid, bf, nbf, SEQNO(bf->bf_state.bfs_seqno)); + "%s: busy buffer cloned: %p -> %p", + __func__, bf, nbf); } else { nbf = bf; } @@ -3515,8 +3475,8 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, */ if (nbf == NULL) { DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, - "%s: tid=%d, buffer couldn't be cloned! (%p) seqno=%d\n", - __func__, tid->tid, bf, SEQNO(bf->bf_state.bfs_seqno)); + "%s: buffer couldn't be cloned! (%p)\n", + __func__, bf); TAILQ_INSERT_TAIL(bf_q, bf, bf_list); } else { ath_tx_tid_filt_comp_buf(sc, tid, nbf); @@ -3757,7 +3717,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an, txq = sc->sc_ac2q[tid->ac]; tap = ath_tx_get_tx_tid(an, tid->tid); - DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET, + DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: %s: %6D: bf=%p: addbaw=%d, dobaw=%d, " "seqno=%d, retry=%d\n", __func__, @@ -3769,7 +3729,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an, bf->bf_state.bfs_dobaw, SEQNO(bf->bf_state.bfs_seqno), bf->bf_state.bfs_retries); - DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET, + DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: %s: %6D: bf=%p: txq[%d] axq_depth=%d, axq_aggr_depth=%d\n", __func__, pfx, @@ -3779,7 +3739,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an, txq->axq_qnum, txq->axq_depth, txq->axq_aggr_depth); - DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET, + DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: %s: %6D: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, " "isfiltered=%d\n", __func__, @@ -3791,7 +3751,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an, tid->hwq_depth, tid->bar_wait, tid->isfiltered); - DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET, + DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: %s: %6D: tid %d: " "sched=%d, paused=%d, " "incomp=%d, baw_head=%d, " @@ -3851,7 +3811,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an, if (t == 0) { ath_tx_tid_drain_print(sc, an, "norm", tid, bf); -// t = 1; + t = 1; } ATH_TID_REMOVE(tid, bf, bf_list); @@ -3867,7 +3827,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an, if (t == 0) { ath_tx_tid_drain_print(sc, an, "filt", tid, bf); -// t = 1; + t = 1; } ATH_TID_FILT_REMOVE(tid, bf, bf_list); @@ -4124,19 +4084,6 @@ ath_tx_normal_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: hwq_depth < 0: %d\n", __func__, atid->hwq_depth); - /* If the TID is being cleaned up, track things */ - /* XXX refactor! */ - if (atid->cleanup_inprogress) { - atid->incomp--; - if (atid->incomp == 0) { - DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, - "%s: TID %d: cleaned up! resume!\n", - __func__, tid); - atid->cleanup_inprogress = 0; - ath_tx_tid_resume(sc, atid); - } - } - /* * If the queue is filtered, potentially mark it as complete * and reschedule it as needed. @@ -4184,16 +4131,6 @@ ath_tx_comp_cleanup_unaggr(struct ath_softc *sc, struct ath_buf *bf) ATH_TX_LOCK(sc); atid->incomp--; - - /* XXX refactor! */ - if (bf->bf_state.bfs_dobaw) { - ath_tx_update_baw(sc, an, atid, bf); - if (!bf->bf_state.bfs_addedbaw) - DPRINTF(sc, ATH_DEBUG_SW_TX, - "%s: wasn't added: seqno %d\n", - __func__, SEQNO(bf->bf_state.bfs_seqno)); - } - if (atid->incomp == 0) { DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: TID %d: cleaned up! resume!\n", @@ -4206,72 +4143,14 @@ ath_tx_comp_cleanup_unaggr(struct ath_softc *sc, struct ath_buf *bf) ath_tx_default_comp(sc, bf, 0); } - -/* - * This as it currently stands is a bit dumb. Ideally we'd just - * fail the frame the normal way and have it permanently fail - * via the normal aggregate completion path. - */ -static void -ath_tx_tid_cleanup_frame(struct ath_softc *sc, struct ath_node *an, - int tid, struct ath_buf *bf_head, ath_bufhead *bf_cq) -{ - struct ath_tid *atid = &an->an_tid[tid]; - struct ath_buf *bf, *bf_next; - - ATH_TX_LOCK_ASSERT(sc); - - /* - * Remove this frame from the queue. - */ - ATH_TID_REMOVE(atid, bf_head, bf_list); - - /* - * Loop over all the frames in the aggregate. - */ - bf = bf_head; - while (bf != NULL) { - bf_next = bf->bf_next; /* next aggregate frame, or NULL */ - - /* - * If it's been added to the BAW we need to kick - * it out of the BAW before we continue. - * - * XXX if it's an aggregate, assert that it's in the - * BAW - we shouldn't have it be in an aggregate - * otherwise! - */ - if (bf->bf_state.bfs_addedbaw) { - ath_tx_update_baw(sc, an, atid, bf); - bf->bf_state.bfs_dobaw = 0; - } - - /* - * Give it the default completion handler. - */ - bf->bf_comp = ath_tx_normal_comp; - bf->bf_next = NULL; - - /* - * Add it to the list to free. - */ - TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); - - /* - * Now advance to the next frame in the aggregate. - */ - bf = bf_next; - } -} - /* * Performs transmit side cleanup when TID changes from aggregated to - * unaggregated and during reassociation. + * unaggregated. * - * For now, this just tosses everything from the TID software queue - * whether or not it has been retried and marks the TID as - * pending completion if there's anything for this TID queued to - * the hardware. + * - Discard all retry frames from the s/w queue. + * - Fix the tx completion function for all buffers in s/w queue. + * - Count the number of unacked frames, and let transmit completion + * handle it later. * * The caller is responsible for pausing the TID and unpausing the * TID if no cleanup was required. Otherwise the cleanup path will @@ -4282,19 +4161,18 @@ ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an, int tid, ath_bufhead *bf_cq) { struct ath_tid *atid = &an->an_tid[tid]; + struct ieee80211_tx_ampdu *tap; struct ath_buf *bf, *bf_next; ATH_TX_LOCK_ASSERT(sc); DPRINTF(sc, ATH_DEBUG_SW_TX_BAW, - "%s: TID %d: called; inprogress=%d\n", __func__, tid, - atid->cleanup_inprogress); + "%s: TID %d: called\n", __func__, tid); /* * Move the filtered frames to the TX queue, before * we run off and discard/process things. */ - /* XXX this is really quite inefficient */ while ((bf = ATH_TID_FILT_LAST(atid, ath_bufhead_s)) != NULL) { ATH_TID_FILT_REMOVE(atid, bf, bf_list); @@ -4309,35 +4187,47 @@ ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an, int tid, */ bf = ATH_TID_FIRST(atid); while (bf) { - /* - * Grab the next frame in the list, we may - * be fiddling with the list. - */ - bf_next = TAILQ_NEXT(bf, bf_list); - - /* - * Free the frame and all subframes. - */ - ath_tx_tid_cleanup_frame(sc, an, tid, bf, bf_cq); - - /* - * Next frame! - */ - bf = bf_next; + if (bf->bf_state.bfs_isretried) { + bf_next = TAILQ_NEXT(bf, bf_list); + ATH_TID_REMOVE(atid, bf, bf_list); + if (bf->bf_state.bfs_dobaw) { + ath_tx_update_baw(sc, an, atid, bf); + if (!bf->bf_state.bfs_addedbaw) + DPRINTF(sc, ATH_DEBUG_SW_TX_BAW, + "%s: wasn't added: seqno %d\n", + __func__, + SEQNO(bf->bf_state.bfs_seqno)); + } + bf->bf_state.bfs_dobaw = 0; + /* + * Call the default completion handler with "fail" just + * so upper levels are suitably notified about this. + */ + TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); + bf = bf_next; + continue; + } + /* Give these the default completion handler */ + bf->bf_comp = ath_tx_normal_comp; + bf = TAILQ_NEXT(bf, bf_list); } /* - * If there's anything in the hardware queue we wait - * for the TID HWQ to empty. + * Calculate what hardware-queued frames exist based + * on the current BAW size. Ie, what frames have been + * added to the TX hardware queue for this TID but + * not yet ACKed. */ - if (atid->hwq_depth > 0) { - /* - * XXX how about we kill atid->incomp, and instead - * replace it with a macro that checks that atid->hwq_depth - * is 0? - */ - atid->incomp = atid->hwq_depth; - atid->cleanup_inprogress = 1; + tap = ath_tx_get_tx_tid(an, tid); + /* Need the lock - fiddling with BAW */ + while (atid->baw_head != atid->baw_tail) { + if (atid->tx_buf[atid->baw_head]) { + atid->incomp++; + atid->cleanup_inprogress = 1; + atid->tx_buf[atid->baw_head] = NULL; + } + INCR(atid->baw_head, ATH_TID_MAX_BUFS); + INCR(tap->txa_start, IEEE80211_SEQ_RANGE); } if (atid->cleanup_inprogress) @@ -4670,19 +4560,9 @@ ath_tx_comp_cleanup_aggr(struct ath_softc *sc, struct ath_buf *bf_first) ATH_TX_LOCK(sc); /* update incomp */ - atid->incomp--; - - /* Update the BAW */ bf = bf_first; while (bf) { - /* XXX refactor! */ - if (bf->bf_state.bfs_dobaw) { - ath_tx_update_baw(sc, an, atid, bf); - if (!bf->bf_state.bfs_addedbaw) - DPRINTF(sc, ATH_DEBUG_SW_TX, - "%s: wasn't added: seqno %d\n", - __func__, SEQNO(bf->bf_state.bfs_seqno)); - } + atid->incomp--; bf = bf->bf_next; } @@ -4705,11 +4585,10 @@ ath_tx_comp_cleanup_aggr(struct ath_softc *sc, struct ath_buf *bf_first) ATH_TX_UNLOCK(sc); - /* Handle frame completion as individual frames */ + /* Handle frame completion */ bf = bf_first; while (bf) { bf_next = bf->bf_next; - bf->bf_next = NULL; ath_tx_default_comp(sc, bf, 1); bf = bf_next; } @@ -5151,10 +5030,6 @@ ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail) "%s: isfiltered=1, fail=%d\n", __func__, fail); freeframe = ath_tx_tid_filt_comp_single(sc, atid, bf); - /* - * If freeframe=0 then bf is no longer ours; don't - * touch it. - */ if (freeframe) { /* Remove from BAW */ if (bf->bf_state.bfs_addedbaw) @@ -5190,6 +5065,7 @@ ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail) if (freeframe) ath_tx_default_comp(sc, bf, fail); + return; } /* @@ -5619,7 +5495,7 @@ ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq) * a frame; be careful. */ if (! ath_tx_tid_can_tx_or_sched(sc, tid)) { - goto loop_done; + continue; } if (ath_tx_ampdu_running(sc, tid->an, tid->tid)) ath_tx_tid_hw_queue_aggr(sc, tid->an, tid); @@ -5642,7 +5518,7 @@ ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq) if (txq->axq_depth >= sc->sc_hwq_limit_nonaggr) { break; } -loop_done: + /* * If this was the last entry on the original list, stop. * Otherwise nodes that have been rescheduled onto the end @@ -5895,26 +5771,12 @@ ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) */ TAILQ_INIT(&bf_cq); ATH_TX_LOCK(sc); - + ath_tx_tid_cleanup(sc, an, tid, &bf_cq); /* - * In case there's a followup call to this, only call it - * if we don't have a cleanup in progress. - * - * Since we've paused the queue above, we need to make - * sure we unpause if there's already a cleanup in - * progress - it means something else is also doing - * this stuff, so we don't need to also keep it paused. + * Unpause the TID if no cleanup is required. */ - if (atid->cleanup_inprogress) { + if (! atid->cleanup_inprogress) ath_tx_tid_resume(sc, atid); - } else { - ath_tx_tid_cleanup(sc, an, tid, &bf_cq); - /* - * Unpause the TID if no cleanup is required. - */ - if (! atid->cleanup_inprogress) - ath_tx_tid_resume(sc, atid); - } ATH_TX_UNLOCK(sc); /* Handle completing frames and fail them */ @@ -5948,25 +5810,19 @@ ath_tx_node_reassoc(struct ath_softc *sc, struct ath_node *an) tid = &an->an_tid[i]; if (tid->hwq_depth == 0) continue; + ath_tx_tid_pause(sc, tid); DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: TID %d: cleaning up TID\n", __func__, an->an_node.ni_macaddr, ":", i); + ath_tx_tid_cleanup(sc, an, i, &bf_cq); /* - * In case there's a followup call to this, only call it - * if we don't have a cleanup in progress. + * Unpause the TID if no cleanup is required. */ - if (! tid->cleanup_inprogress) { - ath_tx_tid_pause(sc, tid); - ath_tx_tid_cleanup(sc, an, i, &bf_cq); - /* - * Unpause the TID if no cleanup is required. - */ - if (! tid->cleanup_inprogress) - ath_tx_tid_resume(sc, tid); - } + if (! tid->cleanup_inprogress) + ath_tx_tid_resume(sc, tid); } ATH_TX_UNLOCK(sc); @@ -5996,43 +5852,19 @@ ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; int attempts = tap->txa_attempts; - int old_txa_start; DPRINTF(sc, ATH_DEBUG_SW_TX_BAR, - "%s: %6D: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d, txa_start=%d, txa_seqpending=%d\n", + "%s: %6D: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d\n", __func__, ni->ni_macaddr, ":", tap->txa_tid, atid->tid, status, - attempts, - tap->txa_start, - tap->txa_seqpending); + attempts); /* Note: This may update the BAW details */ - /* - * XXX What if this does slide the BAW along? We need to somehow - * XXX either fix things when it does happen, or prevent the - * XXX seqpending value to be anything other than exactly what - * XXX the hell we want! - * - * XXX So for now, how I do this inside the TX lock for now - * XXX and just correct it afterwards? The below condition should - * XXX never happen and if it does I need to fix all kinds of things. - */ - ATH_TX_LOCK(sc); - old_txa_start = tap->txa_start; sc->sc_bar_response(ni, tap, status); - if (tap->txa_start != old_txa_start) { - device_printf(sc->sc_dev, "%s: tid=%d; txa_start=%d, old=%d, adjusting\n", - __func__, - tid, - tap->txa_start, - old_txa_start); - } - tap->txa_start = old_txa_start; - ATH_TX_UNLOCK(sc); /* Unpause the TID */ /* diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c index 7d14920..5498dd5 100644 --- a/sys/dev/ath/if_ath_tx_edma.c +++ b/sys/dev/ath/if_ath_tx_edma.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -866,14 +865,12 @@ ath_xmit_setup_edma(struct ath_softc *sc) (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); - if (bootverbose) { - device_printf(sc->sc_dev, "TX descriptor length: %d\n", - sc->sc_tx_desclen); - device_printf(sc->sc_dev, "TX status length: %d\n", - sc->sc_tx_statuslen); - device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", - sc->sc_tx_nmaps); - } + device_printf(sc->sc_dev, "TX descriptor length: %d\n", + sc->sc_tx_desclen); + device_printf(sc->sc_dev, "TX status length: %d\n", + sc->sc_tx_statuslen); + device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", + sc->sc_tx_nmaps); sc->sc_tx.xmit_setup = ath_edma_dma_txsetup; sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown; diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index e888ca2..6b074d6 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -82,25 +82,6 @@ #define ATH_BEACON_CWMAX_DEFAULT 0 /* default cwmax for ap beacon q */ /* - * The following bits can be set during the PCI (and perhaps non-PCI - * later) device probe path. - * - * It controls some of the driver and HAL behaviour. - */ - -#define ATH_PCI_CUS198 0x0001 -#define ATH_PCI_CUS230 0x0002 -#define ATH_PCI_CUS217 0x0004 -#define ATH_PCI_CUS252 0x0008 -#define ATH_PCI_WOW 0x0010 -#define ATH_PCI_BT_ANT_DIV 0x0020 -#define ATH_PCI_D3_L1_WAR 0x0040 -#define ATH_PCI_AR9565_1ANT 0x0080 -#define ATH_PCI_AR9565_2ANT 0x0100 -#define ATH_PCI_NO_PLL_PWRSAVE 0x0200 -#define ATH_PCI_KILLER 0x0400 - -/* * The key cache is used for h/w cipher state and also for * tracking station state such as the current tx antenna. * We also setup a mapping table between key cache slot indices @@ -529,7 +510,6 @@ struct ath_rx_edma { int m_fifo_tail; int m_fifo_depth; struct mbuf *m_rxpending; - struct ath_buf *m_holdbf; }; struct ath_tx_edma_fifo { @@ -585,8 +565,6 @@ struct ath_softc { int sc_tx_statuslen; int sc_tx_nmaps; /* Number of TX maps */ int sc_edma_bufsize; - int sc_rx_stopped; /* XXX only for EDMA */ - int sc_rx_resetted; /* XXX only for EDMA */ void (*sc_node_cleanup)(struct ieee80211_node *); void (*sc_node_free)(struct ieee80211_node *); @@ -643,8 +621,7 @@ struct ath_softc { sc_resetcal : 1,/* reset cal state next trip */ sc_rxslink : 1,/* do self-linked final descriptor */ sc_rxtsf32 : 1,/* RX dec TSF is 32 bits */ - sc_isedma : 1,/* supports EDMA */ - sc_do_mybeacon : 1; /* supports mybeacon */ + sc_isedma : 1;/* supports EDMA */ /* * Second set of flags. @@ -887,25 +864,6 @@ struct ath_softc { void (*sc_bar_response)(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, int status); - - /* - * Powersave state tracking. - * - * target/cur powerstate is the chip power state. - * target selfgen state is the self-generated frames - * state. The chip can be awake but transmitted frames - * can have the PWRMGT bit set to 1 so the destination - * thinks the node is asleep. - */ - HAL_POWER_MODE sc_target_powerstate; - HAL_POWER_MODE sc_target_selfgen_state; - - HAL_POWER_MODE sc_cur_powerstate; - - int sc_powersave_refcnt; - - /* ATH_PCI_* flags */ - uint32_t sc_pci_devinfo; }; #define ATH_LOCK_INIT(_sc) \ @@ -1080,8 +1038,6 @@ void ath_intr(void *); ((*(_ah)->ah_updateTxTrigLevel)((_ah), (_inc))) #define ath_hal_setpower(_ah, _mode) \ ((*(_ah)->ah_setPowerMode)((_ah), (_mode), AH_TRUE)) -#define ath_hal_setselfgenpower(_ah, _mode) \ - ((*(_ah)->ah_setPowerMode)((_ah), (_mode), AH_FALSE)) #define ath_hal_keycachesize(_ah) \ ((*(_ah)->ah_getKeyCacheSize)((_ah))) #define ath_hal_keyreset(_ah, _ix) \ @@ -1310,8 +1266,6 @@ void ath_intr(void *); #define ath_hal_setintmit(_ah, _v) \ ath_hal_setcapability(_ah, HAL_CAP_INTMIT, \ HAL_CAP_INTMIT_ENABLE, _v, NULL) -#define ath_hal_hasmybeacon(_ah) \ - (ath_hal_getcapability(_ah, HAL_CAP_DO_MYBEACON, 1, NULL) == HAL_OK) #define ath_hal_hasenforcetxop(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 0, NULL) == HAL_OK) diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c index b6de4b6..e6ee051 100644 --- a/sys/dev/iwi/if_iwi.c +++ b/sys/dev/iwi/if_iwi.c @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -84,7 +83,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #define IWI_DEBUG #ifdef IWI_DEBUG @@ -938,13 +936,10 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr) struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; struct iwi_softc *sc = ic->ic_ifp->if_softc; - struct ieee80211_node *ni; /* read current transmission rate from adapter */ - ni = ieee80211_ref_node(vap->iv_bss); - ni->ni_txrate = + vap->iv_bss->ni_txrate = iwi_cvtrate(CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE)); - ieee80211_free_node(ni); ieee80211_media_status(ifp, imr); } @@ -1235,7 +1230,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } @@ -1256,7 +1251,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } @@ -1363,44 +1358,16 @@ iwi_checkforqos(struct ieee80211vap *vap, frm += frm[1] + 2; } - ni = ieee80211_ref_node(vap->iv_bss); + ni = vap->iv_bss; ni->ni_capinfo = capinfo; ni->ni_associd = associd & 0x3fff; if (wme != NULL) ni->ni_flags |= IEEE80211_NODE_QOS; else ni->ni_flags &= ~IEEE80211_NODE_QOS; - ieee80211_free_node(ni); #undef SUBTYPE } -static void -iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif) -{ - struct iwi_notif_link_quality *lq; - int len; - - len = le16toh(notif->len); - - DPRINTFN(5, ("Notification (%u) - len=%d, sizeof=%zu\n", - notif->type, - len, - sizeof(struct iwi_notif_link_quality) - )); - - /* enforce length */ - if (len != sizeof(struct iwi_notif_link_quality)) { - DPRINTFN(5, ("Notification: (%u) too short (%d)\n", - notif->type, - len)); - return; - } - - lq = (struct iwi_notif_link_quality *)(notif + 1); - memcpy(&sc->sc_linkqual, lq, sizeof(sc->sc_linkqual)); - sc->sc_linkqual_valid = 1; -} - /* * Task queue callbacks for iwi_notification_intr used to avoid LOR's. */ @@ -1570,11 +1537,8 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) case IWI_NOTIF_TYPE_CALIBRATION: case IWI_NOTIF_TYPE_NOISE: - /* XXX handle? */ - DPRINTFN(5, ("Notification (%u)\n", notif->type)); - break; case IWI_NOTIF_TYPE_LINK_QUALITY: - iwi_notif_link_quality(sc, notif); + DPRINTFN(5, ("Notification (%u)\n", notif->type)); break; default: @@ -1651,7 +1615,7 @@ iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq) DPRINTFN(15, ("tx done idx=%u\n", txq->next)); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; txq->queued--; txq->next = (txq->next + 1) % IWI_TX_RING_COUNT; @@ -1852,7 +1816,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, /* h/w table is full */ m_freem(m0); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return 0; } iwi_write_ibssnode(sc, @@ -2007,7 +1971,7 @@ iwi_start_locked(struct ifnet *ifp) ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; if (iwi_tx_start(ifp, m, ni, ac) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } @@ -2038,7 +2002,7 @@ iwi_watchdog(void *arg) if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_runtask(ic, &sc->sc_restarttask); } } @@ -2094,25 +2058,11 @@ iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCGIFADDR: error = ether_ioctl(ifp, cmd, data); break; - case SIOCGIWISTATS: - IWI_LOCK(sc); - /* XXX validate permissions/memory/etc? */ - error = copyout(&sc->sc_linkqual, ifr->ifr_data, - sizeof(struct iwi_notif_link_quality)); - IWI_UNLOCK(sc); - break; - case SIOCZIWISTATS: - IWI_LOCK(sc); - memset(&sc->sc_linkqual, 0, - sizeof(struct iwi_notif_link_quality)); - IWI_UNLOCK(sc); - error = 0; - break; default: error = EINVAL; break; } - return error; + return error; } static void @@ -2853,7 +2803,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; - struct ieee80211_node *ni; + struct ieee80211_node *ni = vap->iv_bss; struct iwi_configuration config; struct iwi_associate *assoc = &sc->assoc; struct iwi_rateset rs; @@ -2863,8 +2813,6 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) IWI_LOCK_ASSERT(sc); - ni = ieee80211_ref_node(vap->iv_bss); - if (sc->flags & IWI_FLAG_ASSOCIATED) { DPRINTF(("Already associated\n")); return (-1); @@ -3023,7 +2971,6 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct ieee80211vap *vap) le16toh(assoc->intval))); error = iwi_cmd(sc, IWI_CMD_ASSOCIATE, assoc, sizeof *assoc); done: - ieee80211_free_node(ni); if (error) IWI_STATE_END(sc, IWI_FW_ASSOCIATING); diff --git a/sys/dev/iwi/if_iwi_ioctl.h b/sys/dev/iwi/if_iwi_ioctl.h deleted file mode 100644 index 0f4f447..0000000 --- a/sys/dev/iwi/if_iwi_ioctl.h +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * Copyright (c) 2014 Adrian Chadd - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ -#ifndef __IF_IWI_IOCTL_H__ -#define __IF_IWI_IOCTL_H__ - -/* XXX how should I pick appropriate ioctl numbers? */ -#define SIOCGIWISTATS _IOWR('i', 147, struct ifreq) -#define SIOCZIWISTATS _IOWR('i', 148, struct ifreq) - -#endif /* __IF_IWI_IOCTL_H__ */ diff --git a/sys/dev/iwi/if_iwireg.h b/sys/dev/iwi/if_iwireg.h index bc05ad2..fb56fa5 100644 --- a/sys/dev/iwi/if_iwireg.h +++ b/sys/dev/iwi/if_iwireg.h @@ -221,7 +221,6 @@ struct iwi_notif_association { /* structure for notification IWI_NOTIF_TYPE_SCAN_CHANNEL */ struct iwi_notif_scan_channel { uint8_t nchan; - /* XXX this is iwi_cmd_stats, and a u8 reserved field */ uint8_t reserved[47]; } __packed; @@ -240,68 +239,6 @@ struct iwi_notif_beacon_state { uint32_t number; } __packed; -/* structure(s) for notification IWI_NOTIF_TYPE_LINK_QUALITY */ - -#define RX_FREE_BUFFERS 32 -#define RX_LOW_WATERMARK 8 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -// Used for passing to driver number of successes and failures per rate -struct iwi_rate_histogram { - union { - uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } success; - union { - uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } failed; -} __packed; - -/* statistics command response */ -struct iwi_cmd_stats { - uint8_t cmd_id; - uint8_t seq_num; - uint16_t good_sfd; - uint16_t bad_plcp; - uint16_t wrong_bssid; - uint16_t valid_mpdu; - uint16_t bad_mac_header; - uint16_t reserved_frame_types; - uint16_t rx_ina; - uint16_t bad_crc32; - uint16_t invalid_cts; - uint16_t invalid_acks; - uint16_t long_distance_ina_fina; - uint16_t dsp_silence_unreachable; - uint16_t accumulated_rssi; - uint16_t rx_ovfl_frame_tossed; - uint16_t rssi_silence_threshold; - uint16_t rx_ovfl_frame_supplied; - uint16_t last_rx_frame_signal; - uint16_t last_rx_frame_noise; - uint16_t rx_autodetec_no_ofdm; - uint16_t rx_autodetec_no_barker; - uint16_t reserved; -} __packed; - -#define SILENCE_OVER_THRESH (1) -#define SILENCE_UNDER_THRESH (2) - -struct iwi_notif_link_quality { - struct iwi_cmd_stats stats; - uint8_t rate; - uint8_t modulation; - struct iwi_rate_histogram histogram; - uint8_t silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ - uint16_t silence_count; -} __packed; - /* received frame header */ struct iwi_frame { uint32_t reserved1[2]; diff --git a/sys/dev/iwi/if_iwivar.h b/sys/dev/iwi/if_iwivar.h index b38bbd9..42ca92e 100644 --- a/sys/dev/iwi/if_iwivar.h +++ b/sys/dev/iwi/if_iwivar.h @@ -215,9 +215,6 @@ struct iwi_softc { struct iwi_rx_radiotap_header sc_rxtap; struct iwi_tx_radiotap_header sc_txtap; - - struct iwi_notif_link_quality sc_linkqual; - int sc_linkqual_valid; }; #define IWI_STATE_BEGIN(_sc, _state) do { \ diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index ab98204..806a408 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -1,10 +1,11 @@ /*- - * Copyright (c) 2007-2009 Damien Bergamini - * Copyright (c) 2008 Benjamin Close - * Copyright (c) 2008 Sam Leffler, Errno Consulting - * Copyright (c) 2011 Intel Corporation * Copyright (c) 2013 Cedric GROSS - * Copyright (c) 2013 Adrian Chadd + * Copyright (c) 2011 Intel Corporation + * Copyright (c) 2007-2009 + * Damien Bergamini + * Copyright (c) 2008 + * Benjamin Close + * Copyright (c) 2008 Sam Leffler, Errno Consulting * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -56,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -77,9 +77,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include struct iwn_ident { uint16_t vendor; @@ -100,19 +97,12 @@ static const struct iwn_ident iwn_ident_table[] = { { 0x8086, IWN_DID_x030_4, "Intel Centrino Advanced-N 6230" }, { 0x8086, IWN_DID_6150_1, "Intel Centrino Wireless-N + WiMAX 6150" }, { 0x8086, IWN_DID_6150_2, "Intel Centrino Wireless-N + WiMAX 6150" }, - { 0x8086, IWN_DID_2x00_1, "Intel(R) Centrino(R) Wireless-N 2200 BGN" }, - { 0x8086, IWN_DID_2x00_2, "Intel(R) Centrino(R) Wireless-N 2200 BGN" }, - /* XXX 2200D is IWN_SDID_2x00_4; there's no way to express this here! */ { 0x8086, IWN_DID_2x30_1, "Intel Centrino Wireless-N 2230" }, { 0x8086, IWN_DID_2x30_2, "Intel Centrino Wireless-N 2230" }, { 0x8086, IWN_DID_130_1, "Intel Centrino Wireless-N 130" }, { 0x8086, IWN_DID_130_2, "Intel Centrino Wireless-N 130" }, { 0x8086, IWN_DID_100_1, "Intel Centrino Wireless-N 100" }, { 0x8086, IWN_DID_100_2, "Intel Centrino Wireless-N 100" }, - { 0x8086, IWN_DID_105_1, "Intel Centrino Wireless-N 105" }, - { 0x8086, IWN_DID_105_2, "Intel Centrino Wireless-N 105" }, - { 0x8086, IWN_DID_135_1, "Intel Centrino Wireless-N 135" }, - { 0x8086, IWN_DID_135_2, "Intel Centrino Wireless-N 135" }, { 0x8086, IWN_DID_4965_1, "Intel Wireless WiFi Link 4965" }, { 0x8086, IWN_DID_6x00_1, "Intel Centrino Ultimate-N 6300" }, { 0x8086, IWN_DID_6x00_2, "Intel Centrino Advanced-N 6200" }, @@ -129,8 +119,6 @@ static const struct iwn_ident iwn_ident_table[] = { { 0x8086, IWN_DID_5x50_2, "Intel WiMAX/WiFi Link 5350" }, { 0x8086, IWN_DID_5x50_3, "Intel WiMAX/WiFi Link 5150" }, { 0x8086, IWN_DID_5x50_4, "Intel WiMAX/WiFi Link 5150" }, - { 0x8086, IWN_DID_6035_1, "Intel Centrino Advanced 6235" }, - { 0x8086, IWN_DID_6035_2, "Intel Centrino Advanced 6235" }, { 0, 0, NULL } }; @@ -138,7 +126,6 @@ static int iwn_probe(device_t); static int iwn_attach(device_t); static int iwn4965_attach(struct iwn_softc *, uint16_t); static int iwn5000_attach(struct iwn_softc *, uint16_t); -static int iwn_config_specific(struct iwn_softc *, uint16_t); static void iwn_radiotap_attach(struct iwn_softc *); static void iwn_sysctlattach(struct iwn_softc *); static struct ieee80211vap *iwn_vap_create(struct ieee80211com *, @@ -213,7 +200,7 @@ static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, uint8_t); -static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *); +static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, void *); static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_notif_intr(struct iwn_softc *); static void iwn_wakeup_intr(struct iwn_softc *); @@ -270,17 +257,14 @@ static int iwn4965_set_gains(struct iwn_softc *); static int iwn5000_set_gains(struct iwn_softc *); static void iwn_tune_sensitivity(struct iwn_softc *, const struct iwn_rx_stats *); -static void iwn_save_stats_counters(struct iwn_softc *, - const struct iwn_stats *); static int iwn_send_sensitivity(struct iwn_softc *); -static void iwn_check_rx_recovery(struct iwn_softc *, struct iwn_stats *); static int iwn_set_pslevel(struct iwn_softc *, int, int, int); static int iwn_send_btcoex(struct iwn_softc *); static int iwn_send_advanced_btcoex(struct iwn_softc *); static int iwn5000_runtime_calib(struct iwn_softc *); static int iwn_config(struct iwn_softc *); -static int iwn_scan(struct iwn_softc *, struct ieee80211vap *, - struct ieee80211_scan_state *, struct ieee80211_channel *); +static uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int); +static int iwn_scan(struct iwn_softc *); static int iwn_auth(struct iwn_softc *, struct ieee80211vap *vap); static int iwn_run(struct iwn_softc *, struct ieee80211vap *vap); static int iwn_ampdu_rx_start(struct ieee80211_node *, @@ -308,7 +292,6 @@ static int iwn5000_send_calibration(struct iwn_softc *); static int iwn5000_send_wimax_coex(struct iwn_softc *); static int iwn5000_crystal_calib(struct iwn_softc *); static int iwn5000_temp_offset_calib(struct iwn_softc *); -static int iwn5000_temp_offset_calibv2(struct iwn_softc *); static int iwn4965_post_alive(struct iwn_softc *); static int iwn5000_post_alive(struct iwn_softc *); static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *, @@ -333,7 +316,6 @@ static int iwn_hw_init(struct iwn_softc *); static void iwn_hw_stop(struct iwn_softc *); static void iwn_radio_on(void *, int); static void iwn_radio_off(void *, int); -static void iwn_panicked(void *, int); static void iwn_init_locked(struct iwn_softc *); static void iwn_init(void *); static void iwn_stop_locked(struct iwn_softc *); @@ -349,6 +331,80 @@ static char *iwn_get_csr_string(int); static void iwn_debug_register(struct iwn_softc *); #endif +#ifdef IWN_DEBUG +enum { + IWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ + IWN_DEBUG_RECV = 0x00000002, /* basic recv operation */ + IWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */ + IWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */ + IWN_DEBUG_RESET = 0x00000010, /* reset processing */ + IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */ + IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */ + IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ + IWN_DEBUG_INTR = 0x00000100, /* ISR */ + IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */ + IWN_DEBUG_NODE = 0x00000400, /* node management */ + IWN_DEBUG_LED = 0x00000800, /* led management */ + IWN_DEBUG_CMD = 0x00001000, /* cmd submission */ + IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */ + IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ + IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */ + IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */ + IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ + IWN_DEBUG_ANY = 0xffffffff +}; + +#define DPRINTF(sc, m, fmt, ...) do { \ + if (sc->sc_debug & (m)) \ + printf(fmt, __VA_ARGS__); \ +} while (0) + +static const char * +iwn_intr_str(uint8_t cmd) +{ + switch (cmd) { + /* Notifications */ + case IWN_UC_READY: return "UC_READY"; + case IWN_ADD_NODE_DONE: return "ADD_NODE_DONE"; + case IWN_TX_DONE: return "TX_DONE"; + case IWN_START_SCAN: return "START_SCAN"; + case IWN_STOP_SCAN: return "STOP_SCAN"; + case IWN_RX_STATISTICS: return "RX_STATS"; + case IWN_BEACON_STATISTICS: return "BEACON_STATS"; + case IWN_STATE_CHANGED: return "STATE_CHANGED"; + case IWN_BEACON_MISSED: return "BEACON_MISSED"; + case IWN_RX_PHY: return "RX_PHY"; + case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE"; + case IWN_RX_DONE: return "RX_DONE"; + + /* Command Notifications */ + case IWN_CMD_RXON: return "IWN_CMD_RXON"; + case IWN_CMD_RXON_ASSOC: return "IWN_CMD_RXON_ASSOC"; + case IWN_CMD_EDCA_PARAMS: return "IWN_CMD_EDCA_PARAMS"; + case IWN_CMD_TIMING: return "IWN_CMD_TIMING"; + case IWN_CMD_LINK_QUALITY: return "IWN_CMD_LINK_QUALITY"; + case IWN_CMD_SET_LED: return "IWN_CMD_SET_LED"; + case IWN5000_CMD_WIMAX_COEX: return "IWN5000_CMD_WIMAX_COEX"; + case IWN5000_CMD_CALIB_CONFIG: return "IWN5000_CMD_CALIB_CONFIG"; + case IWN5000_CMD_CALIB_RESULT: return "IWN5000_CMD_CALIB_RESULT"; + case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE"; + case IWN_CMD_SET_POWER_MODE: return "IWN_CMD_SET_POWER_MODE"; + case IWN_CMD_SCAN: return "IWN_CMD_SCAN"; + case IWN_CMD_SCAN_RESULTS: return "IWN_CMD_SCAN_RESULTS"; + case IWN_CMD_TXPOWER: return "IWN_CMD_TXPOWER"; + case IWN_CMD_TXPOWER_DBM: return "IWN_CMD_TXPOWER_DBM"; + case IWN5000_CMD_TX_ANT_CONFIG: return "IWN5000_CMD_TX_ANT_CONFIG"; + case IWN_CMD_BT_COEX: return "IWN_CMD_BT_COEX"; + case IWN_CMD_SET_CRITICAL_TEMP: return "IWN_CMD_SET_CRITICAL_TEMP"; + case IWN_CMD_SET_SENSITIVITY: return "IWN_CMD_SET_SENSITIVITY"; + case IWN_CMD_PHY_CALIB: return "IWN_CMD_PHY_CALIB"; + } + return "UNKNOWN INTR NOTIF/CMD"; +} +#else +#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0) +#endif + static device_method_t iwn_methods[] = { /* Device interface */ DEVMETHOD(device_probe, iwn_probe), @@ -392,15 +448,6 @@ iwn_probe(device_t dev) } static int -iwn_is_3stream_device(struct iwn_softc *sc) -{ - /* XXX for now only 5300, until the 5350 can be tested */ - if (sc->hw_type == IWN_HW_REV_TYPE_5300) - return (1); - return (0); -} - -static int iwn_attach(device_t dev) { struct iwn_softc *sc = (struct iwn_softc *)device_get_softc(dev); @@ -468,11 +515,6 @@ iwn_attach(device_t dev) sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT) & IWN_HW_REV_TYPE_MASK; sc->subdevice_id = pci_get_subdevice(dev); - - /* - * 4965 versus 5000 and later have different methods. - * Let's set those up first. - */ if (sc->hw_type == IWN_HW_REV_TYPE_4965) error = iwn4965_attach(sc, pci_get_device(dev)); else @@ -483,16 +525,6 @@ iwn_attach(device_t dev) goto fail; } - /* - * Next, let's setup the various parameters of each NIC. - */ - error = iwn_config_specific(sc, pci_get_device(dev)); - if (error != 0) { - device_printf(dev, "could not attach device, error %d\n", - error); - goto fail; - } - if ((error = iwn_hw_prepare(sc)) != 0) { device_printf(dev, "hardware not ready, error %d\n", error); goto fail; @@ -602,16 +634,17 @@ iwn_attach(device_t dev) ic->ic_txstream = sc->ntxchains; /* - * Some of the 3 antenna devices (ie, the 4965) only supports - * 2x2 operation. So correct the number of streams if - * it's not a 3-stream device. + * The NICs we currently support cap out at 2x2 support + * separate from the chains being used. + * + * This is a total hack to work around that until some + * per-device method is implemented to return the + * actual stream support. */ - if (! iwn_is_3stream_device(sc)) { - if (ic->ic_rxstream > 2) - ic->ic_rxstream = 2; - if (ic->ic_txstream > 2) - ic->ic_txstream = 2; - } + if (ic->ic_rxstream > 2) + ic->ic_rxstream = 2; + if (ic->ic_txstream > 2) + ic->ic_txstream = 2; ic->ic_htcaps = IEEE80211_HTCAP_SMPS_OFF /* SMPS mode disabled */ @@ -677,15 +710,6 @@ iwn_attach(device_t dev) TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc); TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc); - TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc); - - sc->sc_tq = taskqueue_create("iwn_taskq", M_WAITOK, - taskqueue_thread_enqueue, &sc->sc_tq); - error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwn_taskq"); - if (error != 0) { - device_printf(dev, "can't start threads, error %d\n", error); - goto fail; - } iwn_sysctlattach(sc); @@ -700,13 +724,6 @@ iwn_attach(device_t dev) goto fail; } -#if 0 - device_printf(sc->sc_dev, "%s: rx_stats=%d, rx_stats_bt=%d\n", - __func__, - sizeof(struct iwn_stats), - sizeof(struct iwn_stats_bt)); -#endif - if (bootverbose) ieee80211_announce(ic); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); @@ -717,488 +734,6 @@ fail: return error; } -/* - * Define specific configuration based on device id and subdevice id - * pid : PCI device id - */ -static int -iwn_config_specific(struct iwn_softc *sc, uint16_t pid) -{ - - switch (pid) { -/* 4965 series */ - case IWN_DID_4965_1: - case IWN_DID_4965_2: - case IWN_DID_4965_3: - case IWN_DID_4965_4: - sc->base_params = &iwn4965_base_params; - sc->limits = &iwn4965_sensitivity_limits; - sc->fwname = "iwn4965fw"; - /* Override chains masks, ROM is known to be broken. */ - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_ABC; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; - break; -/* 1000 Series */ - case IWN_DID_1000_1: - case IWN_DID_1000_2: - switch(sc->subdevice_id) { - case IWN_SDID_1000_1: - case IWN_SDID_1000_2: - case IWN_SDID_1000_3: - case IWN_SDID_1000_4: - case IWN_SDID_1000_5: - case IWN_SDID_1000_6: - case IWN_SDID_1000_7: - case IWN_SDID_1000_8: - case IWN_SDID_1000_9: - case IWN_SDID_1000_10: - case IWN_SDID_1000_11: - case IWN_SDID_1000_12: - sc->limits = &iwn1000_sensitivity_limits; - sc->base_params = &iwn1000_base_params; - sc->fwname = "iwn1000fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6x00 Series */ - case IWN_DID_6x00_2: - case IWN_DID_6x00_4: - case IWN_DID_6x00_1: - case IWN_DID_6x00_3: - sc->fwname = "iwn6000fw"; - sc->limits = &iwn6000_sensitivity_limits; - switch(sc->subdevice_id) { - case IWN_SDID_6x00_1: - case IWN_SDID_6x00_2: - case IWN_SDID_6x00_8: - //iwl6000_3agn_cfg - sc->base_params = &iwn_6000_base_params; - break; - case IWN_SDID_6x00_3: - case IWN_SDID_6x00_6: - case IWN_SDID_6x00_9: - ////iwl6000i_2agn - case IWN_SDID_6x00_4: - case IWN_SDID_6x00_7: - case IWN_SDID_6x00_10: - //iwl6000i_2abg_cfg - case IWN_SDID_6x00_5: - //iwl6000i_2bg_cfg - sc->base_params = &iwn_6000i_base_params; - sc->sc_flags |= IWN_FLAG_INTERNAL_PA; - sc->txchainmask = IWN_ANT_BC; - sc->rxchainmask = IWN_ANT_BC; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6x05 Series */ - case IWN_DID_6x05_1: - case IWN_DID_6x05_2: - switch(sc->subdevice_id) { - case IWN_SDID_6x05_1: - case IWN_SDID_6x05_4: - case IWN_SDID_6x05_6: - //iwl6005_2agn_cfg - case IWN_SDID_6x05_2: - case IWN_SDID_6x05_5: - case IWN_SDID_6x05_7: - //iwl6005_2abg_cfg - case IWN_SDID_6x05_3: - //iwl6005_2bg_cfg - case IWN_SDID_6x05_8: - case IWN_SDID_6x05_9: - //iwl6005_2agn_sff_cfg - case IWN_SDID_6x05_10: - //iwl6005_2agn_d_cfg - case IWN_SDID_6x05_11: - //iwl6005_2agn_mow1_cfg - case IWN_SDID_6x05_12: - //iwl6005_2agn_mow2_cfg - sc->fwname = "iwn6000g2afw"; - sc->limits = &iwn6000_sensitivity_limits; - sc->base_params = &iwn_6000g2_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6x35 Series */ - case IWN_DID_6035_1: - case IWN_DID_6035_2: - switch(sc->subdevice_id) { - case IWN_SDID_6035_1: - case IWN_SDID_6035_2: - case IWN_SDID_6035_3: - case IWN_SDID_6035_4: - sc->fwname = "iwn6000g2bfw"; - sc->limits = &iwn6235_sensitivity_limits; - sc->base_params = &iwn_6235_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6x50 WiFi/WiMax Series */ - case IWN_DID_6050_1: - case IWN_DID_6050_2: - switch(sc->subdevice_id) { - case IWN_SDID_6050_1: - case IWN_SDID_6050_3: - case IWN_SDID_6050_5: - //iwl6050_2agn_cfg - case IWN_SDID_6050_2: - case IWN_SDID_6050_4: - case IWN_SDID_6050_6: - //iwl6050_2abg_cfg - sc->fwname = "iwn6050fw"; - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_AB; - sc->limits = &iwn6000_sensitivity_limits; - sc->base_params = &iwn_6050_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6150 WiFi/WiMax Series */ - case IWN_DID_6150_1: - case IWN_DID_6150_2: - switch(sc->subdevice_id) { - case IWN_SDID_6150_1: - case IWN_SDID_6150_3: - case IWN_SDID_6150_5: - // iwl6150_bgn_cfg - case IWN_SDID_6150_2: - case IWN_SDID_6150_4: - case IWN_SDID_6150_6: - //iwl6150_bg_cfg - sc->fwname = "iwn6050fw"; - sc->limits = &iwn6000_sensitivity_limits; - sc->base_params = &iwn_6150_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 6030 Series and 1030 Series */ - case IWN_DID_x030_1: - case IWN_DID_x030_2: - case IWN_DID_x030_3: - case IWN_DID_x030_4: - switch(sc->subdevice_id) { - case IWN_SDID_x030_1: - case IWN_SDID_x030_3: - case IWN_SDID_x030_5: - // iwl1030_bgn_cfg - case IWN_SDID_x030_2: - case IWN_SDID_x030_4: - case IWN_SDID_x030_6: - //iwl1030_bg_cfg - case IWN_SDID_x030_7: - case IWN_SDID_x030_10: - case IWN_SDID_x030_14: - //iwl6030_2agn_cfg - case IWN_SDID_x030_8: - case IWN_SDID_x030_11: - case IWN_SDID_x030_15: - // iwl6030_2bgn_cfg - case IWN_SDID_x030_9: - case IWN_SDID_x030_12: - case IWN_SDID_x030_16: - // iwl6030_2abg_cfg - case IWN_SDID_x030_13: - //iwl6030_2bg_cfg - sc->fwname = "iwn6000g2bfw"; - sc->limits = &iwn6000_sensitivity_limits; - sc->base_params = &iwn_6000g2b_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 130 Series WiFi */ -/* XXX: This series will need adjustment for rate. - * see rx_with_siso_diversity in linux kernel - */ - case IWN_DID_130_1: - case IWN_DID_130_2: - switch(sc->subdevice_id) { - case IWN_SDID_130_1: - case IWN_SDID_130_3: - case IWN_SDID_130_5: - //iwl130_bgn_cfg - case IWN_SDID_130_2: - case IWN_SDID_130_4: - case IWN_SDID_130_6: - //iwl130_bg_cfg - sc->fwname = "iwn6000g2bfw"; - sc->limits = &iwn6000_sensitivity_limits; - sc->base_params = &iwn_6000g2b_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 100 Series WiFi */ - case IWN_DID_100_1: - case IWN_DID_100_2: - switch(sc->subdevice_id) { - case IWN_SDID_100_1: - case IWN_SDID_100_2: - case IWN_SDID_100_3: - case IWN_SDID_100_4: - case IWN_SDID_100_5: - case IWN_SDID_100_6: - sc->limits = &iwn1000_sensitivity_limits; - sc->base_params = &iwn1000_base_params; - sc->fwname = "iwn100fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; - -/* 105 Series */ -/* XXX: This series will need adjustment for rate. - * see rx_with_siso_diversity in linux kernel - */ - case IWN_DID_105_1: - case IWN_DID_105_2: - switch(sc->subdevice_id) { - case IWN_SDID_105_1: - case IWN_SDID_105_2: - case IWN_SDID_105_3: - //iwl105_bgn_cfg - case IWN_SDID_105_4: - //iwl105_bgn_d_cfg - sc->limits = &iwn2030_sensitivity_limits; - sc->base_params = &iwn2000_base_params; - sc->fwname = "iwn105fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; - -/* 135 Series */ -/* XXX: This series will need adjustment for rate. - * see rx_with_siso_diversity in linux kernel - */ - case IWN_DID_135_1: - case IWN_DID_135_2: - switch(sc->subdevice_id) { - case IWN_SDID_135_1: - case IWN_SDID_135_2: - case IWN_SDID_135_3: - sc->limits = &iwn2030_sensitivity_limits; - sc->base_params = &iwn2030_base_params; - sc->fwname = "iwn135fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; - -/* 2x00 Series */ - case IWN_DID_2x00_1: - case IWN_DID_2x00_2: - switch(sc->subdevice_id) { - case IWN_SDID_2x00_1: - case IWN_SDID_2x00_2: - case IWN_SDID_2x00_3: - //iwl2000_2bgn_cfg - case IWN_SDID_2x00_4: - //iwl2000_2bgn_d_cfg - sc->limits = &iwn2030_sensitivity_limits; - sc->base_params = &iwn2000_base_params; - sc->fwname = "iwn2000fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice) \n", - pid, sc->subdevice_id, sc->hw_type); - return ENOTSUP; - } - break; -/* 2x30 Series */ - case IWN_DID_2x30_1: - case IWN_DID_2x30_2: - switch(sc->subdevice_id) { - case IWN_SDID_2x30_1: - case IWN_SDID_2x30_3: - case IWN_SDID_2x30_5: - //iwl100_bgn_cfg - case IWN_SDID_2x30_2: - case IWN_SDID_2x30_4: - case IWN_SDID_2x30_6: - //iwl100_bg_cfg - sc->limits = &iwn2030_sensitivity_limits; - sc->base_params = &iwn2030_base_params; - sc->fwname = "iwn2030fw"; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 5x00 Series */ - case IWN_DID_5x00_1: - case IWN_DID_5x00_2: - case IWN_DID_5x00_3: - case IWN_DID_5x00_4: - sc->limits = &iwn5000_sensitivity_limits; - sc->base_params = &iwn5000_base_params; - sc->fwname = "iwn5000fw"; - switch(sc->subdevice_id) { - case IWN_SDID_5x00_1: - case IWN_SDID_5x00_2: - case IWN_SDID_5x00_3: - case IWN_SDID_5x00_4: - case IWN_SDID_5x00_9: - case IWN_SDID_5x00_10: - case IWN_SDID_5x00_11: - case IWN_SDID_5x00_12: - case IWN_SDID_5x00_17: - case IWN_SDID_5x00_18: - case IWN_SDID_5x00_19: - case IWN_SDID_5x00_20: - //iwl5100_agn_cfg - sc->txchainmask = IWN_ANT_B; - sc->rxchainmask = IWN_ANT_AB; - break; - case IWN_SDID_5x00_5: - case IWN_SDID_5x00_6: - case IWN_SDID_5x00_13: - case IWN_SDID_5x00_14: - case IWN_SDID_5x00_21: - case IWN_SDID_5x00_22: - //iwl5100_bgn_cfg - sc->txchainmask = IWN_ANT_B; - sc->rxchainmask = IWN_ANT_AB; - break; - case IWN_SDID_5x00_7: - case IWN_SDID_5x00_8: - case IWN_SDID_5x00_15: - case IWN_SDID_5x00_16: - case IWN_SDID_5x00_23: - case IWN_SDID_5x00_24: - //iwl5100_abg_cfg - sc->txchainmask = IWN_ANT_B; - sc->rxchainmask = IWN_ANT_AB; - break; - case IWN_SDID_5x00_25: - case IWN_SDID_5x00_26: - case IWN_SDID_5x00_27: - case IWN_SDID_5x00_28: - case IWN_SDID_5x00_29: - case IWN_SDID_5x00_30: - case IWN_SDID_5x00_31: - case IWN_SDID_5x00_32: - case IWN_SDID_5x00_33: - case IWN_SDID_5x00_34: - case IWN_SDID_5x00_35: - case IWN_SDID_5x00_36: - //iwl5300_agn_cfg - sc->txchainmask = IWN_ANT_ABC; - sc->rxchainmask = IWN_ANT_ABC; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; -/* 5x50 Series */ - case IWN_DID_5x50_1: - case IWN_DID_5x50_2: - case IWN_DID_5x50_3: - case IWN_DID_5x50_4: - sc->limits = &iwn5000_sensitivity_limits; - sc->base_params = &iwn5000_base_params; - sc->fwname = "iwn5000fw"; - switch(sc->subdevice_id) { - case IWN_SDID_5x50_1: - case IWN_SDID_5x50_2: - case IWN_SDID_5x50_3: - //iwl5350_agn_cfg - sc->limits = &iwn5000_sensitivity_limits; - sc->base_params = &iwn5000_base_params; - sc->fwname = "iwn5000fw"; - break; - case IWN_SDID_5x50_4: - case IWN_SDID_5x50_5: - case IWN_SDID_5x50_8: - case IWN_SDID_5x50_9: - case IWN_SDID_5x50_10: - case IWN_SDID_5x50_11: - //iwl5150_agn_cfg - case IWN_SDID_5x50_6: - case IWN_SDID_5x50_7: - case IWN_SDID_5x50_12: - case IWN_SDID_5x50_13: - //iwl5150_abg_cfg - sc->limits = &iwn5000_sensitivity_limits; - sc->fwname = "iwn5150fw"; - sc->base_params = &iwn_5x50_base_params; - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :" - "0x%04x rev %d not supported (subdevice)\n", pid, - sc->subdevice_id,sc->hw_type); - return ENOTSUP; - } - break; - default: - device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x" - "rev 0x%08x not supported (device)\n", pid, sc->subdevice_id, - sc->hw_type); - return ENOTSUP; - } - return 0; -} - static int iwn4965_attach(struct iwn_softc *sc, uint16_t pid) { @@ -1234,8 +769,6 @@ iwn4965_attach(struct iwn_softc *sc, uint16_t pid) /* Override chains masks, ROM is known to be broken. */ sc->txchainmask = IWN_ANT_AB; sc->rxchainmask = IWN_ANT_ABC; - /* Enable normal btcoex */ - sc->sc_flags |= IWN_FLAG_BTCOEX; DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__); @@ -1276,6 +809,58 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid) sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN; + switch (sc->hw_type) { + case IWN_HW_REV_TYPE_5100: + sc->limits = &iwn5000_sensitivity_limits; + sc->fwname = "iwn5000fw"; + /* Override chains masks, ROM is known to be broken. */ + sc->txchainmask = IWN_ANT_B; + sc->rxchainmask = IWN_ANT_AB; + break; + case IWN_HW_REV_TYPE_5150: + sc->limits = &iwn5150_sensitivity_limits; + sc->fwname = "iwn5150fw"; + break; + case IWN_HW_REV_TYPE_5300: + case IWN_HW_REV_TYPE_5350: + sc->limits = &iwn5000_sensitivity_limits; + sc->fwname = "iwn5000fw"; + break; + case IWN_HW_REV_TYPE_1000: + sc->limits = &iwn1000_sensitivity_limits; + sc->fwname = "iwn1000fw"; + break; + case IWN_HW_REV_TYPE_6000: + sc->limits = &iwn6000_sensitivity_limits; + sc->fwname = "iwn6000fw"; + if (pid == 0x422c || pid == 0x4239) { + sc->sc_flags |= IWN_FLAG_INTERNAL_PA; + /* Override chains masks, ROM is known to be broken. */ + sc->txchainmask = IWN_ANT_BC; + sc->rxchainmask = IWN_ANT_BC; + } + break; + case IWN_HW_REV_TYPE_6050: + sc->limits = &iwn6000_sensitivity_limits; + sc->fwname = "iwn6050fw"; + /* Override chains masks, ROM is known to be broken. */ + sc->txchainmask = IWN_ANT_AB; + sc->rxchainmask = IWN_ANT_AB; + break; + case IWN_HW_REV_TYPE_6005: + sc->limits = &iwn6000_sensitivity_limits; + if (pid != 0x0082 && pid != 0x0085) { + sc->fwname = "iwn6000g2bfw"; + sc->sc_flags |= IWN_FLAG_ADV_BTCOEX; + } else + sc->fwname = "iwn6000g2afw"; + break; + default: + device_printf(sc->sc_dev, "adapter type %d not supported\n", + sc->hw_type); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__); + return ENOTSUP; + } return 0; } @@ -1374,10 +959,6 @@ iwn_detach(device_t dev) ieee80211_draintask(ic, &sc->sc_radiooff_task); iwn_stop(sc); - - taskqueue_drain_all(sc->sc_tq); - taskqueue_free(sc->sc_tq); - callout_drain(&sc->watchdog_to); callout_drain(&sc->calib_to); ieee80211_ifdetach(ic); @@ -1603,7 +1184,7 @@ iwn_init_otprom(struct iwn_softc *sc) iwn_nic_unlock(sc); /* Set auto clock gate disable bit for HW with OTP shadow RAM. */ - if (sc->base_params->shadow_ram_support) { + if (sc->hw_type != IWN_HW_REV_TYPE_1000) { IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT, IWN_RESET_LINK_PWR_MGMT_DIS); } @@ -1616,12 +1197,11 @@ iwn_init_otprom(struct iwn_softc *sc) * Find the block before last block (contains the EEPROM image) * for HW without OTP shadow RAM. */ - if (! sc->base_params->shadow_ram_support) { + if (sc->hw_type == IWN_HW_REV_TYPE_1000) { /* Switch to absolute addressing mode. */ IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS); base = prev = 0; - for (count = 0; count < sc->base_params->max_ll_items; - count++) { + for (count = 0; count < IWN1000_OTP_NBLOCKS; count++) { error = iwn_read_prom_data(sc, base, &next, 2); if (error != 0) return error; @@ -1630,7 +1210,7 @@ iwn_init_otprom(struct iwn_softc *sc) prev = base; base = le16toh(next); } - if (count == 0 || count == sc->base_params->max_ll_items) + if (count == 0 || count == IWN1000_OTP_NBLOCKS) return EIO; /* Skip "next" word. */ sc->prom_base = prev + 1; @@ -1736,12 +1316,16 @@ fail: iwn_dma_contig_free(dma); static void iwn_dma_contig_free(struct iwn_dma_info *dma) { - if (dma->vaddr != NULL) { - bus_dmamap_sync(dma->tag, dma->map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(dma->tag, dma->map); - bus_dmamem_free(dma->tag, dma->vaddr, dma->map); - dma->vaddr = NULL; + if (dma->map != NULL) { + if (dma->vaddr != NULL) { + bus_dmamap_sync(dma->tag, dma->map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(dma->tag, dma->map); + bus_dmamem_free(dma->tag, dma->vaddr, dma->map); + dma->vaddr = NULL; + } + bus_dmamap_destroy(dma->tag, dma->map); + dma->map = NULL; } if (dma->tag != NULL) { bus_dma_tag_destroy(dma->tag); @@ -1875,7 +1459,7 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring) &paddr, BUS_DMA_NOWAIT); if (error != 0 && error != EFBIG) { device_printf(sc->sc_dev, - "%s: can't map mbuf, error %d\n", __func__, + "%s: can't not map mbuf, error %d\n", __func__, error); goto fail; } @@ -2036,10 +1620,6 @@ iwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring) m_freem(data->m); data->m = NULL; } - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } } /* Clear TX descriptors. */ memset(ring->desc, 0, ring->desc_dma.size); @@ -2188,7 +1768,7 @@ iwn4965_read_eeprom(struct iwn_softc *sc) iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4); /* Read the list of authorized channels (20MHz ones only). */ - for (i = 0; i < IWN_NBANDS - 1; i++) { + for (i = 0; i < 7; i++) { addr = iwn4965_regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); } @@ -2218,7 +1798,7 @@ iwn4965_read_eeprom(struct iwn_softc *sc) #ifdef IWN_DEBUG /* Print samples. */ if (sc->sc_debug & IWN_DEBUG_ANY) { - for (i = 0; i < IWN_NBANDS - 1; i++) + for (i = 0; i < IWN_NBANDS; i++) iwn4965_print_power_group(sc, i); } #endif @@ -2279,13 +1859,16 @@ iwn5000_read_eeprom(struct iwn_softc *sc) sc->eeprom_domain, 4); /* Read the list of authorized channels (20MHz ones only). */ - for (i = 0; i < IWN_NBANDS - 1; i++) { - addr = base + sc->base_params->regulatory_bands[i]; + for (i = 0; i < 7; i++) { + if (sc->hw_type >= IWN_HW_REV_TYPE_6000) + addr = base + iwn6000_regulatory_bands[i]; + else + addr = base + iwn5000_regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); } /* Read enhanced TX power information for 6000 Series. */ - if (sc->base_params->enhanced_TX_power) + if (sc->hw_type >= IWN_HW_REV_TYPE_6000) iwn_read_eeprom_enhinfo(sc); iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2); @@ -2296,14 +1879,6 @@ iwn5000_read_eeprom(struct iwn_softc *sc) hdr.version, hdr.pa_type, le16toh(hdr.volt)); sc->calib_ver = hdr.version; - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) { - sc->eeprom_voltage = le16toh(hdr.volt); - iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); - sc->eeprom_temp_high=le16toh(val); - iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2); - sc->eeprom_temp = le16toh(val); - } - if (sc->hw_type == IWN_HW_REV_TYPE_5150) { /* Compute temperature offset. */ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); @@ -2640,52 +2215,6 @@ rate2plcp(int rate) return 0; } -static int -iwn_get_1stream_tx_antmask(struct iwn_softc *sc) -{ - - return IWN_LSB(sc->txchainmask); -} - -static int -iwn_get_2stream_tx_antmask(struct iwn_softc *sc) -{ - int tx; - - /* - * The '2 stream' setup is a bit .. odd. - * - * For NICs that support only 1 antenna, default to IWN_ANT_AB or - * the firmware panics (eg Intel 5100.) - * - * For NICs that support two antennas, we use ANT_AB. - * - * For NICs that support three antennas, we use the two that - * wasn't the default one. - * - * XXX TODO: if bluetooth (full concurrent) is enabled, restrict - * this to only one antenna. - */ - - /* Default - transmit on the other antennas */ - tx = (sc->txchainmask & ~IWN_LSB(sc->txchainmask)); - - /* Now, if it's zero, set it to IWN_ANT_AB, so to not panic firmware */ - if (tx == 0) - tx = IWN_ANT_AB; - - /* - * If the NIC is a two-stream TX NIC, configure the TX mask to - * the default chainmask - */ - else if (sc->ntxchains == 2) - tx = sc->txchainmask; - - return (tx); -} - - - /* * Calculate the required PLCP value from the given rate, * to the given node. @@ -2699,14 +2228,19 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni, { #define RV(v) ((v) & IEEE80211_RATE_VAL) struct ieee80211com *ic = ni->ni_ic; + uint8_t txant1, txant2; uint32_t plcp = 0; int ridx; + /* Use the first valid TX antenna. */ + txant1 = IWN_LSB(sc->txchainmask); + txant2 = IWN_LSB(sc->txchainmask & ~txant1); + /* * If it's an MCS rate, let's set the plcp correctly * and set the relevant flags based on the node config. */ - if (rate & IEEE80211_RATE_MCS) { + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { /* * Set the initial PLCP value to be between 0->31 for * MCS 0 -> MCS 31, then set the "I'm an MCS rate!" @@ -2733,15 +2267,15 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni, } /* - * Ensure the selected rate matches the link quality - * table entries being used. + * If it's a two stream rate, enable TX on both + * antennas. + * + * XXX three stream rates? */ - if (rate > 0x8f) - plcp |= IWN_RFLAG_ANT(sc->txchainmask); - else if (rate > 0x87) - plcp |= IWN_RFLAG_ANT(iwn_get_2stream_tx_antmask(sc)); + if (rate > 0x87) + plcp |= IWN_RFLAG_ANT(txant1 | txant2); else - plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc)); + plcp |= IWN_RFLAG_ANT(txant1); } else { /* * Set the initial PLCP - fine for both @@ -2763,8 +2297,7 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni, plcp |= IWN_RFLAG_CCK; /* Set antenna configuration */ - /* XXX TODO: is this the right antenna to use for legacy? */ - plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc)); + plcp |= IWN_RFLAG_ANT(txant1); } DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n", @@ -2969,14 +2502,14 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) { DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n", __func__, flags); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } /* Discard frames that are too short. */ - if (len < sizeof (struct ieee80211_frame_ack)) { + if (len < sizeof (*wh)) { DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n", __func__, len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } @@ -2984,7 +2517,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, if (m1 == NULL) { DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n", __func__); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } bus_dmamap_unload(ring->data_dmat, data->map); @@ -3007,7 +2540,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, ring->desc[ring->cur] = htole32(paddr >> 8); bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } @@ -3025,10 +2558,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, /* Grab a reference to the source node. */ wh = mtod(m, struct ieee80211_frame *); - if (len >= sizeof(struct ieee80211_frame_min)) - ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); - else - ni = NULL; + ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); nf = (ni != NULL && ni->ni_vap->iv_state == IEEE80211_S_RUN && (ic->ic_flags & IEEE80211_F_SCAN) == 0) ? sc->noise : -95; @@ -3099,9 +2629,8 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, uint16_t ssn; uint8_t tid; int ackfailcnt = 0, i, lastidx, qid, *res, shift; - int tx_ok = 0, tx_err = 0; - DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); @@ -3131,7 +2660,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, KASSERT(ni != NULL, ("no node")); KASSERT(m != NULL, ("no mbuf")); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m); ieee80211_tx_complete(ni, m, 1); txq->queued--; @@ -3157,32 +2685,22 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, if (wn->agg[tid].nframes > (64 - shift)) return; - /* - * Walk the bitmap and calculate how many successful and failed - * attempts are made. - * - * Yes, the rate control code doesn't know these are A-MPDU - * subframes and that it's okay to fail some of these. - */ ni = tap->txa_ni; bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap; for (i = 0; bitmap; i++) { if ((bitmap & 1) == 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - tx_err ++; + ifp->if_oerrors++; ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - tx_ok ++; + ifp->if_opackets++; ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); } bitmap >>= 1; } - DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, - "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); } @@ -3210,24 +2728,25 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc, switch (calib->code) { case IWN5000_PHY_CALIB_DC: - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_DC) + if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA) == 0 && + (sc->hw_type == IWN_HW_REV_TYPE_5150 || + sc->hw_type >= IWN_HW_REV_TYPE_6000) && + sc->hw_type != IWN_HW_REV_TYPE_6050) idx = 0; break; case IWN5000_PHY_CALIB_LO: - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_LO) - idx = 1; + idx = 1; break; case IWN5000_PHY_CALIB_TX_IQ: - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ) - idx = 2; + idx = 2; break; case IWN5000_PHY_CALIB_TX_IQ_PERIODIC: - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC) + if (sc->hw_type < IWN_HW_REV_TYPE_6000 && + sc->hw_type != IWN_HW_REV_TYPE_5150) idx = 3; break; case IWN5000_PHY_CALIB_BASE_BAND: - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_BASE_BAND) - idx = 4; + idx = 4; break; } if (idx == -1) /* Ignore other results. */ @@ -3244,72 +2763,11 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc, return; } DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "saving calibration result idx=%d, code=%d len=%d\n", idx, calib->code, len); + "saving calibration result code=%d len=%d\n", calib->code, len); sc->calibcmd[idx].len = len; memcpy(sc->calibcmd[idx].buf, calib, len); } -static void -iwn_stats_update(struct iwn_softc *sc, struct iwn_calib_state *calib, - struct iwn_stats *stats, int len) -{ - struct iwn_stats_bt *stats_bt; - struct iwn_stats *lstats; - - /* - * First - check whether the length is the bluetooth or normal. - * - * If it's normal - just copy it and bump out. - * Otherwise we have to convert things. - */ - - if (len == sizeof(struct iwn_stats) + 4) { - memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats)); - sc->last_stat_valid = 1; - return; - } - - /* - * If it's not the bluetooth size - log, then just copy. - */ - if (len != sizeof(struct iwn_stats_bt) + 4) { - DPRINTF(sc, IWN_DEBUG_STATS, - "%s: size of rx statistics (%d) not an expected size!\n", - __func__, - len); - memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats)); - sc->last_stat_valid = 1; - return; - } - - /* - * Ok. Time to copy. - */ - stats_bt = (struct iwn_stats_bt *) stats; - lstats = &sc->last_stat; - - /* flags */ - lstats->flags = stats_bt->flags; - /* rx_bt */ - memcpy(&lstats->rx.ofdm, &stats_bt->rx_bt.ofdm, - sizeof(struct iwn_rx_phy_stats)); - memcpy(&lstats->rx.cck, &stats_bt->rx_bt.cck, - sizeof(struct iwn_rx_phy_stats)); - memcpy(&lstats->rx.general, &stats_bt->rx_bt.general_bt.common, - sizeof(struct iwn_rx_general_stats)); - memcpy(&lstats->rx.ht, &stats_bt->rx_bt.ht, - sizeof(struct iwn_rx_ht_phy_stats)); - /* tx */ - memcpy(&lstats->tx, &stats_bt->tx, - sizeof(struct iwn_tx_stats)); - /* general */ - memcpy(&lstats->general, &stats_bt->general, - sizeof(struct iwn_general_stats)); - - /* XXX TODO: Squirrel away the extra bluetooth stats somewhere */ - sc->last_stat_valid = 1; -} - /* * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification. * The latter is sent by the firmware after each received beacon. @@ -3324,7 +2782,6 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwn_calib_state *calib = &sc->calib; struct iwn_stats *stats = (struct iwn_stats *)(desc + 1); - struct iwn_stats *lstats; int temp; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -3339,26 +2796,12 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); - DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_STATS, - "%s: received statistics, cmd %d, len %d\n", - __func__, desc->type, le16toh(desc->len)); + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: received statistics, cmd %d\n", + __func__, desc->type); sc->calib_cnt = 0; /* Reset TX power calibration timeout. */ - /* - * Collect/track general statistics for reporting. - * - * This takes care of ensuring that the bluetooth sized message - * will be correctly converted to the legacy sized message. - */ - iwn_stats_update(sc, calib, stats, le16toh(desc->len)); - - /* - * And now, let's take a reference of it to use! - */ - lstats = &sc->last_stat; - /* Test if temperature has changed. */ - if (lstats->general.temp != sc->rawtemp) { + if (stats->general.temp != sc->rawtemp) { /* Convert "raw" temperature to degC. */ sc->rawtemp = stats->general.temp; temp = ops->get_temperature(sc); @@ -3373,51 +2816,25 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, if (desc->type != IWN_BEACON_STATISTICS) return; /* Reply to a statistics request. */ - sc->noise = iwn_get_noise(&lstats->rx.general); + sc->noise = iwn_get_noise(&stats->rx.general); DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: noise %d\n", __func__, sc->noise); /* Test that RSSI and noise are present in stats report. */ - if (le32toh(lstats->rx.general.flags) != 1) { + if (le32toh(stats->rx.general.flags) != 1) { DPRINTF(sc, IWN_DEBUG_ANY, "%s\n", "received statistics without RSSI"); return; } if (calib->state == IWN_CALIB_STATE_ASSOC) - iwn_collect_noise(sc, &lstats->rx.general); - else if (calib->state == IWN_CALIB_STATE_RUN) { - iwn_tune_sensitivity(sc, &lstats->rx); - /* - * XXX TODO: Only run the RX recovery if we're associated! - */ - iwn_check_rx_recovery(sc, lstats); - iwn_save_stats_counters(sc, lstats); - } + iwn_collect_noise(sc, &stats->rx.general); + else if (calib->state == IWN_CALIB_STATE_RUN) + iwn_tune_sensitivity(sc, &stats->rx); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); } /* - * Save the relevant statistic counters for the next calibration - * pass. - */ -static void -iwn_save_stats_counters(struct iwn_softc *sc, const struct iwn_stats *rs) -{ - struct iwn_calib_state *calib = &sc->calib; - - /* Save counters values for next call. */ - calib->bad_plcp_cck = le32toh(rs->rx.cck.bad_plcp); - calib->fa_cck = le32toh(rs->rx.cck.fa); - calib->bad_plcp_ht = le32toh(rs->rx.ht.bad_plcp); - calib->bad_plcp_ofdm = le32toh(rs->rx.ofdm.bad_plcp); - calib->fa_ofdm = le32toh(rs->rx.ofdm.fa); - - /* Last time we received these tick values */ - sc->last_calib_ticks = ticks; -} - -/* * Process a TX_DONE firmware notification. Unfortunately, the 4965AGN * and 5000 adapters have different incompatible TX status formats. */ @@ -3433,18 +2850,15 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, ring = &sc->txq[qid]; DPRINTF(sc, IWN_DEBUG_XMIT, "%s: " - "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n", - __func__, desc->qid, desc->idx, - stat->rtsfailcnt, - stat->ackfailcnt, - stat->btkillcnt, - stat->rate, le16toh(stat->duration), + "qid %d idx %d retries %d nkill %d rate %x duration %d status %x\n", + __func__, desc->qid, desc->idx, stat->ackfailcnt, + stat->btkillcnt, stat->rate, le16toh(stat->duration), le32toh(stat->status)); bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->ackfailcnt, &stat->status); + &stat->status); } else { iwn_tx_done(sc, desc, stat->ackfailcnt, le32toh(stat->status) & 0xff); @@ -3463,12 +2877,9 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, ring = &sc->txq[qid]; DPRINTF(sc, IWN_DEBUG_XMIT, "%s: " - "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n", - __func__, desc->qid, desc->idx, - stat->rtsfailcnt, - stat->ackfailcnt, - stat->btkillcnt, - stat->rate, le16toh(stat->duration), + "qid %d idx %d retries %d nkill %d rate %x duration %d status %x\n", + __func__, desc->qid, desc->idx, stat->ackfailcnt, + stat->btkillcnt, stat->rate, le16toh(stat->duration), le32toh(stat->status)); #ifdef notyet @@ -3479,7 +2890,7 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->ackfailcnt, &stat->status); + &stat->status); } else { iwn_tx_done(sc, desc, stat->ackfailcnt, le16toh(stat->status) & 0xff); @@ -3515,11 +2926,11 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, * Update rate control statistics for the node. */ if (status & IWN_TX_FAIL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); } @@ -3566,19 +2977,12 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, static void iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc) { - struct iwn_tx_ring *ring; + struct iwn_tx_ring *ring = &sc->txq[4]; struct iwn_tx_data *data; - int cmd_queue_num; - if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT) - cmd_queue_num = IWN_PAN_CMD_QUEUE; - else - cmd_queue_num = IWN_CMD_QUEUE_NUM; - - if ((desc->qid & IWN_RX_DESC_QID_MSK) != cmd_queue_num) + if ((desc->qid & 0xf) != 4) return; /* Not a command ack. */ - ring = &sc->txq[cmd_queue_num]; data = &ring->data[desc->idx]; /* If the command was mapped in an mbuf, free it. */ @@ -3594,7 +2998,7 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc) static void iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, - int ackfailcnt, void *stat) + void *stat) { struct iwn_ops *ops = &sc->ops; struct ifnet *ifp = sc->sc_ifp; @@ -3611,60 +3015,14 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, uint8_t tid; int bit, i, lastidx, *res, seqno, shift, start; - /* XXX TODO: status is le16 field! Grr */ - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: nframes=%d, status=0x%08x\n", - __func__, - nframes, - *status); - - tap = sc->qid2tap[qid]; - tid = tap->txa_tid; - wn = (void *)tap->txa_ni; - ni = tap->txa_ni; - /* - * XXX TODO: ACK and RTS failures would be nice here! - */ - - /* - * A-MPDU single frame status - if we failed to transmit it - * in A-MPDU, then it may be a permanent failure. - * - * XXX TODO: check what the Linux iwlwifi driver does here; - * there's some permanent and temporary failures that may be - * handled differently. - */ +#ifdef NOT_YET if (nframes == 1) { - if ((*status & 0xff) != 1 && (*status & 0xff) != 2) { -#ifdef NOT_YET + if ((*status & 0xff) != 1 && (*status & 0xff) != 2) printf("ieee80211_send_bar()\n"); -#endif - /* - * If we completely fail a transmit, make sure a - * notification is pushed up to the rate control - * layer. - */ - ieee80211_ratectl_tx_complete(ni->ni_vap, - ni, - IEEE80211_RATECTL_TX_FAILURE, - &ackfailcnt, - NULL); - } else { - /* - * If nframes=1, then we won't be getting a BA for - * this frame. Ensure that we correctly update the - * rate control code with how many retries were - * needed to send it. - */ - ieee80211_ratectl_tx_complete(ni->ni_vap, - ni, - IEEE80211_RATECTL_TX_SUCCESS, - &ackfailcnt, - NULL); - } } +#endif bitmap = 0; start = idx; @@ -3703,7 +3061,6 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, ssn = tap->txa_start & 0xfff; } - /* This is going nframes DWORDS into the descriptor? */ seqno = le32toh(*(status + nframes)) & 0xfff; for (lastidx = (seqno & 0xff); ring->read != lastidx;) { data = &ring->data[ring->read]; @@ -3717,7 +3074,7 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, KASSERT(ni != NULL, ("no node")); KASSERT(m != NULL, ("no mbuf")); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m); + ieee80211_tx_complete(ni, m, 1); ring->queued--; @@ -3772,12 +3129,12 @@ iwn_notif_intr(struct iwn_softc *sc) desc = mtod(data->m, struct iwn_rx_desc *); DPRINTF(sc, IWN_DEBUG_RECV, - "%s: cur=%d; qid %x idx %d flags %x type %d(%s) len %d\n", - __func__, sc->rxq.cur, desc->qid & 0xf, desc->idx, desc->flags, + "%s: qid %x idx %d flags %x type %d(%s) len %d\n", + __func__, desc->qid & 0xf, desc->idx, desc->flags, desc->type, iwn_intr_str(desc->type), le16toh(desc->len)); - if (!(desc->qid & IWN_UNSOLICITED_RX_NOTIF)) /* Reply to a command. */ + if (!(desc->qid & 0x80)) /* Reply to a command. */ iwn_cmd_done(sc, desc); switch (desc->type) { @@ -3872,8 +3229,7 @@ iwn_notif_intr(struct iwn_softc *sc) BUS_DMASYNC_POSTREAD); #ifdef IWN_DEBUG uint32_t *status = (uint32_t *)(desc + 1); - DPRINTF(sc, IWN_DEBUG_INTR | IWN_DEBUG_STATE, - "state changed to %x\n", + DPRINTF(sc, IWN_DEBUG_INTR, "state changed to %x\n", le32toh(*status)); #endif break; @@ -3898,11 +3254,11 @@ iwn_notif_intr(struct iwn_softc *sc) #ifdef IWN_DEBUG struct iwn_stop_scan *scan = (struct iwn_stop_scan *)(desc + 1); - DPRINTF(sc, IWN_DEBUG_STATE | IWN_DEBUG_SCAN, + DPRINTF(sc, IWN_DEBUG_STATE, "scan finished nchan=%d status=%d chan=%d\n", scan->nchan, scan->status, scan->chan); #endif - sc->sc_is_scanning = 0; + IWN_UNLOCK(sc); ieee80211_scan_next(vap); IWN_LOCK(sc); @@ -4054,10 +3410,8 @@ iwn_intr(void *arg) r2 = 0; /* Unused. */ } else { r1 = IWN_READ(sc, IWN_INT); - if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) { - IWN_UNLOCK(sc); + if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) return; /* Hardware gone! */ - } r2 = IWN_READ(sc, IWN_FH_INT); } @@ -4088,8 +3442,8 @@ iwn_intr(void *arg) #endif /* Dump firmware error log and stop. */ iwn_fatal_intr(sc); - - taskqueue_enqueue(sc->sc_tq, &sc->sc_panic_task); + ifp->if_flags &= ~IFF_UP; + iwn_stop_locked(sc); goto done; } if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) || @@ -4187,115 +3541,6 @@ iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx) } #endif -/* - * Check whether OFDM 11g protection will be enabled for the given rate. - * - * The original driver code only enabled protection for OFDM rates. - * It didn't check to see whether it was operating in 11a or 11bg mode. - */ -static int -iwn_check_rate_needs_protection(struct iwn_softc *sc, - struct ieee80211vap *vap, uint8_t rate) -{ - struct ieee80211com *ic = vap->iv_ic; - - /* - * Not in 2GHz mode? Then there's no need to enable OFDM - * 11bg protection. - */ - if (! IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) { - return (0); - } - - /* - * 11bg protection not enabled? Then don't use it. - */ - if ((ic->ic_flags & IEEE80211_F_USEPROT) == 0) - return (0); - - /* - * If it's an 11n rate - no protection. - * We'll do it via a specific 11n check. - */ - if (rate & IEEE80211_RATE_MCS) { - return (0); - } - - /* - * Do a rate table lookup. If the PHY is CCK, - * don't do protection. - */ - if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_CCK) - return (0); - - /* - * Yup, enable protection. - */ - return (1); -} - -/* - * return a value between 0 and IWN_MAX_TX_RETRIES-1 as an index into - * the link quality table that reflects this particular entry. - */ -static int -iwn_tx_rate_to_linkq_offset(struct iwn_softc *sc, struct ieee80211_node *ni, - uint8_t rate) -{ - struct ieee80211_rateset *rs; - int is_11n; - int nr; - int i; - uint8_t cmp_rate; - - /* - * Figure out if we're using 11n or not here. - */ - if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates > 0) - is_11n = 1; - else - is_11n = 0; - - /* - * Use the correct rate table. - */ - if (is_11n) { - rs = (struct ieee80211_rateset *) &ni->ni_htrates; - nr = ni->ni_htrates.rs_nrates; - } else { - rs = &ni->ni_rates; - nr = rs->rs_nrates; - } - - /* - * Find the relevant link quality entry in the table. - */ - for (i = 0; i < nr && i < IWN_MAX_TX_RETRIES - 1 ; i++) { - /* - * The link quality table index starts at 0 == highest - * rate, so we walk the rate table backwards. - */ - cmp_rate = rs->rs_rates[(nr - 1) - i]; - if (rate & IEEE80211_RATE_MCS) - cmp_rate |= IEEE80211_RATE_MCS; - -#if 0 - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: idx %d: nr=%d, rate=0x%02x, rateentry=0x%02x\n", - __func__, - i, - nr, - rate, - cmp_rate); -#endif - - if (cmp_rate == rate) - return (i); - } - - /* Failed? Start at the end */ - return (IWN_MAX_TX_RETRIES - 1); -} - static int iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { @@ -4316,7 +3561,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) uint16_t qos; u_int hdrlen; bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER]; - uint8_t tid, type; + uint8_t tid, ridx, txant, type; int ac, i, totlen, error, pad, nsegs = 0, rate; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -4337,7 +3582,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) } ac = M_WME_GETAC(m); if (m->m_flags & M_AMPDU_MPDU) { - uint16_t seqno; struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; if (!IEEE80211_AMPDU_RUNNING(tap)) { @@ -4345,27 +3589,9 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) return EINVAL; } - /* - * Queue this frame to the hardware ring that we've - * negotiated AMPDU TX on. - * - * Note that the sequence number must match the TX slot - * being used! - */ ac = *(int *)tap->txa_private; - seqno = ni->ni_txseqs[tid]; *(uint16_t *)wh->i_seq = - htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); - ring = &sc->txq[ac]; - if ((seqno % 256) != ring->cur) { - device_printf(sc->sc_dev, - "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n", - __func__, - m, - seqno, - seqno % 256, - ring->cur); - } + htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseqs[tid]++; } ring = &sc->txq[ac]; @@ -4380,13 +3606,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; - else if (m->m_flags & M_EAPOL) - rate = tp->mgmtrate; else { /* XXX pass pktlen */ (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } + ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, + rate & IEEE80211_RATE_VAL); /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { @@ -4443,18 +3669,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) /* NB: Group frames are sent using CCK in 802.11b/g. */ if (totlen + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) { flags |= IWN_TX_NEED_RTS; - } else if (iwn_check_rate_needs_protection(sc, vap, rate)) { + } else if ((ic->ic_flags & IEEE80211_F_USEPROT) && + ridx >= IWN_RIDX_OFDM6) { if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) flags |= IWN_TX_NEED_CTS; else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) flags |= IWN_TX_NEED_RTS; - } else if ((rate & IEEE80211_RATE_MCS) && - (ic->ic_htprotmode == IEEE80211_PROT_RTSCTS)) { - flags |= IWN_TX_NEED_RTS; } - - /* XXX HT protection? */ - if (flags & (IWN_TX_NEED_RTS | IWN_TX_NEED_CTS)) { if (sc->hw_type != IWN_HW_REV_TYPE_4965) { /* 5000 autoselects RTS/CTS or CTS-to-self. */ @@ -4501,11 +3722,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (tx->id == sc->broadcast_id) { /* Group or management frame. */ tx->linkq = 0; + /* XXX Alternate between antenna A and B? */ + txant = IWN_LSB(sc->txchainmask); + tx->rate |= htole32(IWN_RFLAG_ANT(txant)); } else { - tx->linkq = iwn_tx_rate_to_linkq_offset(sc, ni, rate); + tx->linkq = ni->ni_rates.rs_nrates - ridx - 1; flags |= IWN_TX_LINKQ; /* enable MRR */ } - /* Set physical address of "scratch area". */ tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); tx->hiaddr = IWN_HIADDR(data->scratch_paddr); @@ -4528,7 +3751,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) return error; } /* Too many DMA segments, linearize mbuf. */ - m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER - 1); + m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER); if (m1 == NULL) { device_printf(sc->sc_dev, "%s: could not defrag mbuf\n", __func__); @@ -4550,16 +3773,8 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) data->m = m; data->ni = ni; - DPRINTF(sc, IWN_DEBUG_XMIT, - "%s: qid %d idx %d len %d nsegs %d flags 0x%08x rate 0x%04x plcp 0x%08x\n", - __func__, - ring->qid, - ring->cur, - m->m_pkthdr.len, - nsegs, - flags, - rate, - tx->rate); + DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n", + __func__, ring->qid, ring->cur, m->m_pkthdr.len, nsegs); /* Fill TX descriptor. */ desc->nsegs = 1; @@ -4606,9 +3821,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { struct iwn_ops *ops = &sc->ops; -// struct ifnet *ifp = sc->sc_ifp; + struct ifnet *ifp = sc->sc_ifp; struct ieee80211vap *vap = ni->ni_vap; -// struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = ifp->if_l2com; struct iwn_tx_cmd *cmd; struct iwn_cmd_data *tx; struct ieee80211_frame *wh; @@ -4620,7 +3835,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, uint32_t flags; u_int hdrlen; int ac, totlen, error, pad, nsegs = 0, i, rate; - uint8_t type; + uint8_t ridx, type, txant; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -4636,8 +3851,16 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; - /* Choose a TX rate. */ + /* Choose a TX rate index. */ rate = params->ibp_rate0; + ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, + rate & IEEE80211_RATE_VAL); + if (ridx == (uint8_t)-1) { + /* XXX fall back to mcast/mgmt rate? */ + m_freem(m); + return EINVAL; + } + totlen = m->m_pkthdr.len; /* Prepare TX firmware command. */ @@ -4707,10 +3930,17 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, tx->rts_ntries = params->ibp_try1; tx->data_ntries = params->ibp_try0; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); - tx->rate = iwn_rate_to_plcp(sc, ni, rate); + + /* XXX should just use iwn_rate_to_plcp() */ + tx->rate = htole32(rate2plcp(rate)); + if (ridx < IWN_RIDX_OFDM6 && + IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + tx->rate |= htole32(IWN_RFLAG_CCK); /* Group or management frame. */ tx->linkq = 0; + txant = IWN_LSB(sc->txchainmask); + tx->rate |= htole32(IWN_RFLAG_ANT(txant)); /* Set physical address of "scratch area". */ tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); @@ -4734,7 +3964,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, return error; } /* Too many DMA segments, linearize mbuf. */ - m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER - 1); + m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER); if (m1 == NULL) { device_printf(sc->sc_dev, "%s: could not defrag mbuf\n", __func__); @@ -4808,7 +4038,7 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, struct iwn_softc *sc = ifp->if_softc; int error = 0; - DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { ieee80211_free_node(ni); @@ -4833,13 +4063,13 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (error != 0) { /* NB: m is reclaimed on tx failure */ ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } else - sc->sc_tx_timer = 5; + ifp->if_oerrors++; + } + sc->sc_tx_timer = 5; IWN_UNLOCK(sc); - DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); return error; } @@ -4863,8 +4093,6 @@ iwn_start_locked(struct ifnet *ifp) IWN_LOCK_ASSERT(sc); - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || (ifp->if_drv_flags & IFF_DRV_OACTIVE)) return; @@ -4880,12 +4108,11 @@ iwn_start_locked(struct ifnet *ifp) ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (iwn_tx_data(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } else - sc->sc_tx_timer = 5; + ifp->if_oerrors++; + continue; + } + sc->sc_tx_timer = 5; } - - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__); } static void @@ -4947,18 +4174,6 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); break; - case SIOCGIWNSTATS: - IWN_LOCK(sc); - /* XXX validate permissions/memory/etc? */ - error = copyout(&sc->last_stat, ifr->ifr_data, - sizeof(struct iwn_stats)); - IWN_UNLOCK(sc); - break; - case SIOCZIWNSTATS: - IWN_LOCK(sc); - memset(&sc->last_stat, 0, sizeof(struct iwn_stats)); - IWN_UNLOCK(sc); - break; default: error = EINVAL; break; @@ -4972,26 +4187,19 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) static int iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async) { - struct iwn_tx_ring *ring; + struct iwn_tx_ring *ring = &sc->txq[4]; struct iwn_tx_desc *desc; struct iwn_tx_data *data; struct iwn_tx_cmd *cmd; struct mbuf *m; bus_addr_t paddr; int totlen, error; - int cmd_queue_num; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); if (async == 0) IWN_LOCK_ASSERT(sc); - if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT) - cmd_queue_num = IWN_PAN_CMD_QUEUE; - else - cmd_queue_num = IWN_CMD_QUEUE_NUM; - - ring = &sc->txq[cmd_queue_num]; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; totlen = 4 + size; @@ -5085,87 +4293,42 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni) { #define RV(v) ((v) & IEEE80211_RATE_VAL) struct iwn_node *wn = (void *)ni; - struct ieee80211_rateset *rs; + struct ieee80211_rateset *rs = &ni->ni_rates; struct iwn_cmd_link_quality linkq; + uint8_t txant; int i, rate, txrate; - int is_11n; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); + /* Use the first valid TX antenna. */ + txant = IWN_LSB(sc->txchainmask); + memset(&linkq, 0, sizeof linkq); linkq.id = wn->id; - linkq.antmsk_1stream = iwn_get_1stream_tx_antmask(sc); - linkq.antmsk_2stream = iwn_get_2stream_tx_antmask(sc); - - linkq.ampdu_max = 32; /* XXX negotiated? */ + linkq.antmsk_1stream = txant; + linkq.antmsk_2stream = IWN_ANT_AB; + linkq.ampdu_max = 64; linkq.ampdu_threshold = 3; linkq.ampdu_limit = htole16(4000); /* 4ms */ - DPRINTF(sc, IWN_DEBUG_XMIT, - "%s: 1stream antenna=0x%02x, 2stream antenna=0x%02x, ntxstreams=%d\n", - __func__, - linkq.antmsk_1stream, - linkq.antmsk_2stream, - sc->ntxchains); - - /* - * Are we using 11n rates? Ensure the channel is - * 11n _and_ we have some 11n rates, or don't - * try. - */ - if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates > 0) { - rs = (struct ieee80211_rateset *) &ni->ni_htrates; - is_11n = 1; - } else { - rs = &ni->ni_rates; - is_11n = 0; - } - /* Start at highest available bit-rate. */ - /* - * XXX this is all very dirty! - */ - if (is_11n) + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) txrate = ni->ni_htrates.rs_nrates - 1; else txrate = rs->rs_nrates - 1; for (i = 0; i < IWN_MAX_TX_RETRIES; i++) { uint32_t plcp; - /* - * XXX TODO: ensure the last two slots are the two lowest - * rate entries, just for now. - */ - if (i == 14 || i == 15) - txrate = 0; - - if (is_11n) - rate = IEEE80211_RATE_MCS | rs->rs_rates[txrate]; + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) + rate = IEEE80211_RATE_MCS | txrate; else rate = RV(rs->rs_rates[txrate]); /* Do rate -> PLCP config mapping */ plcp = iwn_rate_to_plcp(sc, ni, rate); linkq.retry[i] = plcp; - DPRINTF(sc, IWN_DEBUG_XMIT, - "%s: i=%d, txrate=%d, rate=0x%02x, plcp=0x%08x\n", - __func__, - i, - txrate, - rate, - le32toh(plcp)); - /* - * The mimo field is an index into the table which - * indicates the first index where it and subsequent entries - * will not be using MIMO. - * - * Since we're filling linkq from 0..15 and we're filling - * from the higest MCS rates to the lowest rates, if we - * _are_ doing a dual-stream rate, set mimo to idx+1 (ie, - * the next entry.) That way if the next entry is a non-MIMO - * entry, we're already pointing at it. - */ + /* Special case for dual-stream rates? */ if ((le32toh(plcp) & IWN_RFLAG_MCS) && RV(le32toh(plcp)) > 7) linkq.mimo = i + 1; @@ -5174,15 +4337,6 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni) if (txrate > 0) txrate--; } - /* - * If we reached the end of the list and indeed we hit - * all MIMO rates (eg 5300 doing MCS23-15) then yes, - * set mimo to 15. Setting it to 16 panics the firmware. - */ - if (linkq.mimo > 15) - linkq.mimo = 15; - - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: mimo = %d\n", __func__, linkq.mimo); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); @@ -5220,14 +4374,13 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async) memset(&linkq, 0, sizeof linkq); linkq.id = sc->broadcast_id; - linkq.antmsk_1stream = iwn_get_1stream_tx_antmask(sc); - linkq.antmsk_2stream = iwn_get_2stream_tx_antmask(sc); + linkq.antmsk_1stream = txant; + linkq.antmsk_2stream = IWN_ANT_AB; linkq.ampdu_max = 64; linkq.ampdu_threshold = 3; linkq.ampdu_limit = htole16(4000); /* 4ms */ /* Use lowest mandatory bit-rate. */ - /* XXX rate table lookup? */ if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) linkq.retry[0] = htole32(0xd); else @@ -5289,12 +4442,6 @@ iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on) DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); -#if 0 - /* XXX don't set LEDs during scan? */ - if (sc->sc_is_scanning) - return; -#endif - /* Clear microcode LED ownership. */ IWN_CLRBITS(sc, IWN_LED, IWN_LED_BSM_CTRL); @@ -5534,7 +4681,6 @@ iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, int async) { struct iwn5000_cmd_txpower cmd; - int cmdid; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -5546,15 +4692,8 @@ iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, cmd.global_limit = 2 * IWN5000_TXPOWER_MAX_DBM; /* 16 dBm */ cmd.flags = IWN5000_TXPOWER_NO_CLOSED; cmd.srv_limit = IWN5000_TXPOWER_AUTO; - DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT, - "%s: setting TX power; rev=%d\n", - __func__, - IWN_UCODE_API(sc->ucode_rev)); - if (IWN_UCODE_API(sc->ucode_rev) == 1) - cmdid = IWN_CMD_TXPOWER_DBM_V1; - else - cmdid = IWN_CMD_TXPOWER_DBM; - return iwn_cmd(sc, cmdid, &cmd, sizeof cmd, async); + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: setting TX power\n", __func__); + return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM, &cmd, sizeof cmd, async); } /* @@ -5754,7 +4893,7 @@ iwn_collect_noise(struct iwn_softc *sc, for (i = 0; i < 3; i++) if (val - calib->rssi[i] > 15 * 20) sc->chainmask &= ~(1 << i); - DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT, + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: RX chains mask: theoretical=0x%x, actual=0x%x\n", __func__, sc->rxchainmask, sc->chainmask); @@ -5768,10 +4907,6 @@ iwn_collect_noise(struct iwn_softc *sc, #ifdef notyet /* XXX Disable RX chains with no antennas connected. */ sc->rxon->rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask)); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); (void)iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1); #endif @@ -5879,7 +5014,7 @@ iwn5000_set_gains(struct iwn_softc *sc) cmd.gain[i - 1] |= 1 << 2; /* sign bit */ } } - DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT, + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "setting differential gains Ant B/C: %x/%x (%x)\n", cmd.gain[0], cmd.gain[1], sc->chainmask); return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1); @@ -5929,6 +5064,10 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats) fa += le32toh(stats->ofdm.fa) - calib->fa_ofdm; fa *= 200 * IEEE80211_DUR_TU; /* 200TU */ + /* Save counters values for next call. */ + calib->bad_plcp_ofdm = le32toh(stats->ofdm.bad_plcp); + calib->fa_ofdm = le32toh(stats->ofdm.fa); + if (fa > 50 * rxena) { /* High false alarm count, decrease sensitivity. */ DPRINTF(sc, IWN_DEBUG_CALIBRATE, @@ -5982,6 +5121,10 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats) fa += le32toh(stats->cck.fa) - calib->fa_cck; fa *= 200 * IEEE80211_DUR_TU; /* 200TU */ + /* Save counters values for next call. */ + calib->bad_plcp_cck = le32toh(stats->cck.bad_plcp); + calib->fa_cck = le32toh(stats->cck.fa); + if (fa > 50 * rxena) { /* High false alarm count, decrease sensitivity. */ DPRINTF(sc, IWN_DEBUG_CALIBRATE, @@ -6062,7 +5205,7 @@ iwn_send_sensitivity(struct iwn_softc *sc) cmd.energy_cck = htole16(calib->energy_cck); /* Barker modulation: use default values. */ cmd.corr_barker = htole16(190); - cmd.corr_barker_mrc = htole16(sc->limits->barker_mrc); + cmd.corr_barker_mrc = htole16(390); DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: set sensitivity %d/%d/%d/%d/%d/%d/%d\n", __func__, @@ -6087,86 +5230,6 @@ send: } /* - * Look at the increase of PLCP errors over time; if it exceeds - * a programmed threshold then trigger an RF retune. - */ -static void -iwn_check_rx_recovery(struct iwn_softc *sc, struct iwn_stats *rs) -{ - int32_t delta_ofdm, delta_ht, delta_cck; - struct iwn_calib_state *calib = &sc->calib; - int delta_ticks, cur_ticks; - int delta_msec; - int thresh; - - /* - * Calculate the difference between the current and - * previous statistics. - */ - delta_cck = le32toh(rs->rx.cck.bad_plcp) - calib->bad_plcp_cck; - delta_ofdm = le32toh(rs->rx.ofdm.bad_plcp) - calib->bad_plcp_ofdm; - delta_ht = le32toh(rs->rx.ht.bad_plcp) - calib->bad_plcp_ht; - - /* - * Calculate the delta in time between successive statistics - * messages. Yes, it can roll over; so we make sure that - * this doesn't happen. - * - * XXX go figure out what to do about rollover - * XXX go figure out what to do if ticks rolls over to -ve instead! - * XXX go stab signed integer overflow undefined-ness in the face. - */ - cur_ticks = ticks; - delta_ticks = cur_ticks - sc->last_calib_ticks; - - /* - * If any are negative, then the firmware likely reset; so just - * bail. We'll pick this up next time. - */ - if (delta_cck < 0 || delta_ofdm < 0 || delta_ht < 0 || delta_ticks < 0) - return; - - /* - * delta_ticks is in ticks; we need to convert it up to milliseconds - * so we can do some useful math with it. - */ - delta_msec = ticks_to_msecs(delta_ticks); - - /* - * Calculate what our threshold is given the current delta_msec. - */ - thresh = sc->base_params->plcp_err_threshold * delta_msec; - - DPRINTF(sc, IWN_DEBUG_STATE, - "%s: time delta: %d; cck=%d, ofdm=%d, ht=%d, total=%d, thresh=%d\n", - __func__, - delta_msec, - delta_cck, - delta_ofdm, - delta_ht, - (delta_msec + delta_cck + delta_ofdm + delta_ht), - thresh); - - /* - * If we need a retune, then schedule a single channel scan - * to a channel that isn't the currently active one! - * - * The math from linux iwlwifi: - * - * if ((delta * 100 / msecs) > threshold) - */ - if (thresh > 0 && (delta_cck + delta_ofdm + delta_ht) * 100 > thresh) { - DPRINTF(sc, IWN_DEBUG_ANY, - "%s: PLCP error threshold raw (%d) comparison (%d) " - "over limit (%d); retune!\n", - __func__, - (delta_cck + delta_ofdm + delta_ht), - (delta_cck + delta_ofdm + delta_ht) * 100, - thresh); - } -} - -/* * Set STA mode power saving level (between 0 and 5). * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving. */ @@ -6251,73 +5314,25 @@ iwn_send_advanced_btcoex(struct iwn_softc *sc) 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000, }; struct iwn6000_btcoex_config btconfig; - struct iwn2000_btcoex_config btconfig2k; struct iwn_btcoex_priotable btprio; struct iwn_btcoex_prot btprot; int error, i; - uint8_t flags; memset(&btconfig, 0, sizeof btconfig); - memset(&btconfig2k, 0, sizeof btconfig2k); - - flags = IWN_BT_FLAG_COEX6000_MODE_3W << - IWN_BT_FLAG_COEX6000_MODE_SHIFT; // Done as is in linux kernel 3.2 - - if (sc->base_params->bt_sco_disable) - flags &= ~IWN_BT_FLAG_SYNC_2_BT_DISABLE; - else - flags |= IWN_BT_FLAG_SYNC_2_BT_DISABLE; - - flags |= IWN_BT_FLAG_COEX6000_CHAN_INHIBITION; - - /* Default flags result is 145 as old value */ - - /* - * Flags value has to be review. Values must change if we - * which to disable it - */ - if (sc->base_params->bt_session_2) { - btconfig2k.flags = flags; - btconfig2k.max_kill = 5; - btconfig2k.bt3_t7_timer = 1; - btconfig2k.kill_ack = htole32(0xffff0000); - btconfig2k.kill_cts = htole32(0xffff0000); - btconfig2k.sample_time = 2; - btconfig2k.bt3_t2_timer = 0xc; - - for (i = 0; i < 12; i++) - btconfig2k.lookup_table[i] = htole32(btcoex_3wire[i]); - btconfig2k.valid = htole16(0xff); - btconfig2k.prio_boost = htole32(0xf0); - DPRINTF(sc, IWN_DEBUG_RESET, - "%s: configuring advanced bluetooth coexistence" - " session 2, flags : 0x%x\n", - __func__, - flags); - error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig2k, - sizeof(btconfig2k), 1); - } else { - btconfig.flags = flags; - btconfig.max_kill = 5; - btconfig.bt3_t7_timer = 1; - btconfig.kill_ack = htole32(0xffff0000); - btconfig.kill_cts = htole32(0xffff0000); - btconfig.sample_time = 2; - btconfig.bt3_t2_timer = 0xc; - - for (i = 0; i < 12; i++) - btconfig.lookup_table[i] = htole32(btcoex_3wire[i]); - btconfig.valid = htole16(0xff); - btconfig.prio_boost = 0xf0; - DPRINTF(sc, IWN_DEBUG_RESET, - "%s: configuring advanced bluetooth coexistence," - " flags : 0x%x\n", - __func__, - flags); - error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, - sizeof(btconfig), 1); - } - + btconfig.flags = 145; + btconfig.max_kill = 5; + btconfig.bt3_t7_timer = 1; + btconfig.kill_ack = htole32(0xffff0000); + btconfig.kill_cts = htole32(0xffff0000); + btconfig.sample_time = 2; + btconfig.bt3_t2_timer = 0xc; + for (i = 0; i < 12; i++) + btconfig.lookup_table[i] = htole32(btcoex_3wire[i]); + btconfig.valid = htole16(0xff); + btconfig.prio_boost = 0xf0; + DPRINTF(sc, IWN_DEBUG_RESET, + "%s: configuring advanced bluetooth coexistence\n", __func__); + error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1); if (error != 0) return error; @@ -6372,32 +5387,13 @@ iwn_config(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - if ((sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) - && (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)) { - device_printf(sc->sc_dev,"%s: temp_offset and temp_offsetv2 are" - " exclusive each together. Review NIC config file. Conf" - " : 0x%08x Flags : 0x%08x \n", __func__, - sc->base_params->calib_need, - (IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET | - IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)); - return (EINVAL); - } - - /* Compute temperature calib if needed. Will be send by send calib */ - if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) { + if (sc->hw_type == IWN_HW_REV_TYPE_6005) { + /* Set radio temperature sensor offset. */ error = iwn5000_temp_offset_calib(sc); if (error != 0) { device_printf(sc->sc_dev, "%s: could not set temperature offset\n", __func__); - return (error); - } - } else if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) { - error = iwn5000_temp_offset_calibv2(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not compute temperature offset v2\n", - __func__); - return (error); + return error; } } @@ -6413,10 +5409,9 @@ iwn_config(struct iwn_softc *sc) } /* Configure valid TX chains for >=5000 Series. */ - if (sc->hw_type != IWN_HW_REV_TYPE_4965 && - IWN_UCODE_API(sc->ucode_rev) > 1) { + if (sc->hw_type != IWN_HW_REV_TYPE_4965) { txmask = htole32(sc->txchainmask); - DPRINTF(sc, IWN_DEBUG_RESET | IWN_DEBUG_XMIT, + DPRINTF(sc, IWN_DEBUG_RESET, "%s: configuring valid TX chains 0x%x\n", __func__, txmask); error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG, &txmask, sizeof txmask, 0); @@ -6429,14 +5424,10 @@ iwn_config(struct iwn_softc *sc) } /* Configure bluetooth coexistence. */ - error = 0; - - /* Configure bluetooth coexistence if needed. */ - if (sc->base_params->bt_mode == IWN_BT_ADVANCED) + if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX) error = iwn_send_advanced_btcoex(sc); - if (sc->base_params->bt_mode == IWN_BT_SIMPLE) + else error = iwn_send_btcoex(sc); - if (error != 0) { device_printf(sc->sc_dev, "%s: could not configure bluetooth coexistence, error %d\n", @@ -6472,29 +5463,12 @@ iwn_config(struct iwn_softc *sc) sc->rxon->ht_single_mask = 0xff; sc->rxon->ht_dual_mask = 0xff; sc->rxon->ht_triple_mask = 0xff; - /* - * In active association mode, ensure that - * all the receive chains are enabled. - * - * Since we're not yet doing SMPS, don't allow the - * number of idle RX chains to be less than the active - * number. - */ rxchain = IWN_RXCHAIN_VALID(sc->rxchainmask) | - IWN_RXCHAIN_MIMO_COUNT(sc->nrxchains) | - IWN_RXCHAIN_IDLE_COUNT(sc->nrxchains); + IWN_RXCHAIN_MIMO_COUNT(2) | + IWN_RXCHAIN_IDLE_COUNT(2); sc->rxon->rxchain = htole16(rxchain); - DPRINTF(sc, IWN_DEBUG_RESET | IWN_DEBUG_XMIT, - "%s: rxchainmask=0x%x, nrxchains=%d\n", - __func__, - sc->rxchainmask, - sc->nrxchains); DPRINTF(sc, IWN_DEBUG_RESET, "%s: setting configuration\n", __func__); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 0); if (error != 0) { device_printf(sc->sc_dev, "%s: RXON command failed\n", @@ -6533,109 +5507,39 @@ iwn_config(struct iwn_softc *sc) return 0; } -static uint16_t -iwn_get_active_dwell_time(struct iwn_softc *sc, - struct ieee80211_channel *c, uint8_t n_probes) -{ - /* No channel? Default to 2GHz settings */ - if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) { - return (IWN_ACTIVE_DWELL_TIME_2GHZ + - IWN_ACTIVE_DWELL_FACTOR_2GHZ * (n_probes + 1)); - } - - /* 5GHz dwell time */ - return (IWN_ACTIVE_DWELL_TIME_5GHZ + - IWN_ACTIVE_DWELL_FACTOR_5GHZ * (n_probes + 1)); -} - /* - * Limit the total dwell time to 85% of the beacon interval. - * - * Returns the dwell time in milliseconds. + * Add an ssid element to a frame. */ -static uint16_t -iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211vap *vap = NULL; - int bintval = 0; - - /* bintval is in TU (1.024mS) */ - if (! TAILQ_EMPTY(&ic->ic_vaps)) { - vap = TAILQ_FIRST(&ic->ic_vaps); - bintval = vap->iv_bss->ni_intval; - } - - /* - * If it's non-zero, we should calculate the minimum of - * it and the DWELL_BASE. - * - * XXX Yes, the math should take into account that bintval - * is 1.024mS, not 1mS.. - */ - if (bintval > 0) { - DPRINTF(sc, IWN_DEBUG_SCAN, - "%s: bintval=%d\n", - __func__, - bintval); - return (MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100))); - } - - /* No association context? Default */ - return (IWN_PASSIVE_DWELL_BASE); -} - -static uint16_t -iwn_get_passive_dwell_time(struct iwn_softc *sc, struct ieee80211_channel *c) +static uint8_t * +ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len) { - uint16_t passive; - - if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) { - passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_2GHZ; - } else { - passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_5GHZ; - } - - /* Clamp to the beacon interval if we're associated */ - return (iwn_limit_dwell(sc, passive)); + *frm++ = IEEE80211_ELEMID_SSID; + *frm++ = len; + memcpy(frm, ssid, len); + return frm + len; } static int -iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, - struct ieee80211_scan_state *ss, struct ieee80211_channel *c) +iwn_scan(struct iwn_softc *sc) { struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_node *ni = vap->iv_bss; + struct ieee80211_scan_state *ss = ic->ic_scan; /*XXX*/ + struct ieee80211_node *ni = ss->ss_vap->iv_bss; struct iwn_scan_hdr *hdr; struct iwn_cmd_data *tx; struct iwn_scan_essid *essid; struct iwn_scan_chan *chan; struct ieee80211_frame *wh; struct ieee80211_rateset *rs; + struct ieee80211_channel *c; uint8_t *buf, *frm; uint16_t rxchain; uint8_t txant; int buflen, error; - int is_active; - uint16_t dwell_active, dwell_passive; - uint32_t extra, scan_service_time; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); - /* - * We are absolutely not allowed to send a scan command when another - * scan command is pending. - */ - if (sc->sc_is_scanning) { - device_printf(sc->sc_dev, "%s: called whilst scanning!\n", - __func__); - return (EAGAIN); - } - - /* Assign the scan channel */ - c = ic->ic_curchan; - sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO); if (buf == NULL) { @@ -6651,29 +5555,13 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, */ hdr->quiet_time = htole16(10); /* timeout in milliseconds */ hdr->quiet_threshold = htole16(1); /* min # of packets */ - /* - * Max needs to be greater than active and passive and quiet! - * It's also in microseconds! - */ - hdr->max_svc = htole32(250 * 1024); - - /* - * Reset scan: interval=100 - * Normal scan: interval=becaon interval - * suspend_time: 100 (TU) - * - */ - extra = (100 /* suspend_time */ / 100 /* beacon interval */) << 22; - //scan_service_time = extra | ((100 /* susp */ % 100 /* int */) * 1024); - scan_service_time = (4 << 22) | (100 * 1024); /* Hardcode for now! */ - hdr->pause_svc = htole32(scan_service_time); /* Select antennas for scanning. */ rxchain = IWN_RXCHAIN_VALID(sc->rxchainmask) | IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask) | IWN_RXCHAIN_DRIVER_FORCE; - if (IEEE80211_IS_CHAN_A(c) && + if (IEEE80211_IS_CHAN_A(ic->ic_curchan) && sc->hw_type == IWN_HW_REV_TYPE_4965) { /* Ant A must be avoided in 5GHz because of an HW bug. */ rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B); @@ -6687,7 +5575,7 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, tx->id = sc->broadcast_id; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); - if (IEEE80211_IS_CHAN_5GHZ(c)) { + if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) { /* Send probe requests at 6Mbps. */ tx->rate = htole32(0xd); rs = &ic->ic_sup_rates[IEEE80211_MODE_11A]; @@ -6706,35 +5594,12 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, txant = IWN_LSB(sc->txchainmask); tx->rate |= htole32(IWN_RFLAG_ANT(txant)); - /* - * Only do active scanning if we're announcing a probe request - * for a given SSID (or more, if we ever add it to the driver.) - */ - is_active = 0; - - /* - * If we're scanning for a specific SSID, add it to the command. - * - * XXX maybe look at adding support for scanning multiple SSIDs? - */ essid = (struct iwn_scan_essid *)(tx + 1); - if (ss != NULL) { - if (ss->ss_ssid[0].len != 0) { - essid[0].id = IEEE80211_ELEMID_SSID; - essid[0].len = ss->ss_ssid[0].len; - memcpy(essid[0].data, ss->ss_ssid[0].ssid, ss->ss_ssid[0].len); - } - - DPRINTF(sc, IWN_DEBUG_SCAN, "%s: ssid_len=%d, ssid=%*s\n", - __func__, - ss->ss_ssid[0].len, - ss->ss_ssid[0].len, - ss->ss_ssid[0].ssid); - - if (ss->ss_nssid > 0) - is_active = 1; + if (ss->ss_ssid[0].len != 0) { + essid[0].id = IEEE80211_ELEMID_SSID; + essid[0].len = ss->ss_ssid[0].len; + memcpy(essid[0].data, ss->ss_ssid[0].ssid, ss->ss_ssid[0].len); } - /* * Build a probe request frame. Most of the following code is a * copy & paste of what is done in net80211. @@ -6760,96 +5625,53 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, /* Set length of probe request. */ tx->len = htole16(frm - (uint8_t *)wh); - /* - * If active scanning is requested but a certain channel is - * marked passive, we can do active scanning if we detect - * transmissions. - * - * There is an issue with some firmware versions that triggers - * a sysassert on a "good CRC threshold" of zero (== disabled), - * on a radar channel even though this means that we should NOT - * send probes. - * - * The "good CRC threshold" is the number of frames that we - * need to receive during our dwell time on a channel before - * sending out probes -- setting this to a huge value will - * mean we never reach it, but at the same time work around - * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER - * here instead of IWL_GOOD_CRC_TH_DISABLED. - * - * This was fixed in later versions along with some other - * scan changes, and the threshold behaves as a flag in those - * versions. - */ - - /* - * If we're doing active scanning, set the crc_threshold - * to a suitable value. This is different to active veruss - * passive scanning depending upon the channel flags; the - * firmware will obey that particular check for us. - */ - if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN) - hdr->crc_threshold = is_active ? - IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_DISABLED; - else - hdr->crc_threshold = is_active ? - IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_NEVER; - + c = ic->ic_curchan; chan = (struct iwn_scan_chan *)frm; chan->chan = htole16(ieee80211_chan2ieee(ic, c)); chan->flags = 0; if (ss->ss_nssid > 0) chan->flags |= htole32(IWN_CHAN_NPBREQS(1)); chan->dsp_gain = 0x6e; - - /* - * Set the passive/active flag depending upon the channel mode. - * XXX TODO: take the is_active flag into account as well? - */ - if (c->ic_flags & IEEE80211_CHAN_PASSIVE) - chan->flags |= htole32(IWN_CHAN_PASSIVE); - else + if (IEEE80211_IS_CHAN_5GHZ(c) && + !(c->ic_flags & IEEE80211_CHAN_PASSIVE)) { + chan->rf_gain = 0x3b; + chan->active = htole16(24); + chan->passive = htole16(110); chan->flags |= htole32(IWN_CHAN_ACTIVE); - - /* - * Calculate the active/passive dwell times. - */ - - dwell_active = iwn_get_active_dwell_time(sc, c, ss->ss_nssid); - dwell_passive = iwn_get_passive_dwell_time(sc, c); - - /* Make sure they're valid */ - if (dwell_passive <= dwell_active) - dwell_passive = dwell_active + 1; - - chan->active = htole16(dwell_active); - chan->passive = htole16(dwell_passive); - - if (IEEE80211_IS_CHAN_5GHZ(c)) + } else if (IEEE80211_IS_CHAN_5GHZ(c)) { chan->rf_gain = 0x3b; - else + chan->active = htole16(24); + if (sc->rxon->associd) + chan->passive = htole16(78); + else + chan->passive = htole16(110); + hdr->crc_threshold = 0xffff; + } else if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) { + chan->rf_gain = 0x28; + chan->active = htole16(36); + chan->passive = htole16(120); + chan->flags |= htole32(IWN_CHAN_ACTIVE); + } else { chan->rf_gain = 0x28; + chan->active = htole16(36); + if (sc->rxon->associd) + chan->passive = htole16(88); + else + chan->passive = htole16(120); + hdr->crc_threshold = 0xffff; + } DPRINTF(sc, IWN_DEBUG_STATE, "%s: chan %u flags 0x%x rf_gain 0x%x " - "dsp_gain 0x%x active %d passive %d scan_svc_time %d crc 0x%x " - "isactive=%d numssid=%d\n", __func__, + "dsp_gain 0x%x active 0x%x passive 0x%x\n", __func__, chan->chan, chan->flags, chan->rf_gain, chan->dsp_gain, - dwell_active, dwell_passive, scan_service_time, - hdr->crc_threshold, is_active, ss->ss_nssid); + chan->active, chan->passive); hdr->nchan++; chan++; buflen = (uint8_t *)chan - buf; hdr->len = htole16(buflen); - if (sc->sc_is_scanning) { - device_printf(sc->sc_dev, - "%s: called with is_scanning set!\n", - __func__); - } - sc->sc_is_scanning = 1; - DPRINTF(sc, IWN_DEBUG_STATE, "sending scan command nchan=%d\n", hdr->nchan); error = iwn_cmd(sc, IWN_CMD_SCAN, buf, buflen, 1); @@ -6890,16 +5712,12 @@ iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap) sc->rxon->ofdm_mask = 0; } else { /* Assume 802.11b/g. */ - sc->rxon->cck_mask = 0x03; + sc->rxon->cck_mask = 0x0f; sc->rxon->ofdm_mask = 0x15; } DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n", sc->rxon->chan, sc->rxon->flags, sc->rxon->cck_mask, sc->rxon->ofdm_mask); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1); if (error != 0) { device_printf(sc->sc_dev, "%s: RXON command failed, error %d\n", @@ -6995,10 +5813,6 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap) sc->rxon->filter |= htole32(IWN_FILTER_BSS); DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x\n", sc->rxon->chan, sc->rxon->flags); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1); if (error != 0) { device_printf(sc->sc_dev, @@ -7397,10 +6211,10 @@ iwn5000_query_calibration(struct iwn_softc *sc) int error; memset(&cmd, 0, sizeof cmd); - cmd.ucode.once.enable = htole32(0xffffffff); - cmd.ucode.once.start = htole32(0xffffffff); - cmd.ucode.once.send = htole32(0xffffffff); - cmd.ucode.flags = htole32(0xffffffff); + cmd.ucode.once.enable = 0xffffffff; + cmd.ucode.once.start = 0xffffffff; + cmd.ucode.once.send = 0xffffffff; + cmd.ucode.flags = 0xffffffff; DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending calibration query\n", __func__); error = iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof cmd, 0); @@ -7422,20 +6236,9 @@ iwn5000_send_calibration(struct iwn_softc *sc) { int idx, error; - for (idx = 0; idx < IWN5000_PHY_CALIB_MAX_RESULT; idx++) { - if (!(sc->base_params->calib_need & (1<calibcmd[idx].buf == NULL) { - DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "Need calib idx : %d but no available data\n", - idx); - continue; - } - + for (idx = 0; idx < 5; idx++) { + if (sc->calibcmd[idx].buf == NULL) + continue; /* No results available. */ DPRINTF(sc, IWN_DEBUG_CALIBRATE, "send calibration result idx=%d len=%d\n", idx, sc->calibcmd[idx].len); @@ -7456,7 +6259,7 @@ iwn5000_send_wimax_coex(struct iwn_softc *sc) { struct iwn5000_wimax_coex wimax; -#if 0 +#ifdef notyet if (sc->hw_type == IWN_HW_REV_TYPE_6050) { /* Enable WiMAX coexistence for combo adapters. */ wimax.flags = @@ -7512,33 +6315,6 @@ iwn5000_temp_offset_calib(struct iwn_softc *sc) return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); } -static int -iwn5000_temp_offset_calibv2(struct iwn_softc *sc) -{ - struct iwn5000_phy_calib_temp_offsetv2 cmd; - - memset(&cmd, 0, sizeof cmd); - cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET; - cmd.ngroups = 1; - cmd.isvalid = 1; - if (sc->eeprom_temp != 0) { - cmd.offset_low = htole16(sc->eeprom_temp); - cmd.offset_high = htole16(sc->eeprom_temp_high); - } else { - cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET); - cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET); - } - cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage); - - DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "setting radio sensor low offset to %d, high offset to %d, voltage to %d\n", - le16toh(cmd.offset_low), - le16toh(cmd.offset_high), - le16toh(cmd.burnt_voltage_ref)); - - return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); -} - /* * This function is called after the runtime firmware notifies us of its * readiness (called in a process context). @@ -7624,10 +6400,7 @@ iwn5000_post_alive(struct iwn_softc *sc) IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY); /* Enable chain mode for all queues, except command queue. */ - if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT) - iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffdf); - else - iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef); + iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef); iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL, 0); for (qid = 0; qid < IWN5000_NTXQUEUES; qid++) { @@ -7648,20 +6421,10 @@ iwn5000_post_alive(struct iwn_softc *sc) iwn_prph_write(sc, IWN5000_SCHED_TXFACT, 0xff); /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */ - if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT) { - /* Mark TX rings as active. */ - for (qid = 0; qid < 11; qid++) { - static uint8_t qid2fifo[] = { 3, 2, 1, 0, 0, 4, 2, 5, 4, 7, 5 }; - iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), - IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); - } - } else { - /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */ - for (qid = 0; qid < 7; qid++) { - static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 }; - iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), - IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); - } + for (qid = 0; qid < 7; qid++) { + static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 }; + iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), + IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]); } iwn_nic_unlock(sc); @@ -7906,8 +6669,6 @@ iwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw) ptr = (const uint32_t *)fw->data; rev = le32toh(*ptr++); - sc->ucode_rev = rev; - /* Check firmware API version. */ if (IWN_FW_API(rev) <= 1) { device_printf(sc->sc_dev, @@ -7973,7 +6734,6 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw, } DPRINTF(sc, IWN_DEBUG_RESET, "FW: \"%.64s\", build 0x%x\n", hdr->descr, le32toh(hdr->build)); - sc->ucode_rev = le32toh(hdr->rev); /* * Select the closest supported alternative that is less than @@ -8029,7 +6789,7 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw, sc->sc_flags |= IWN_FLAG_ENH_SENS; break; case IWN_FW_TLV_PHY_CALIB: - tmp = le32toh(*ptr); + tmp = htole32(*ptr); if (tmp < 253) { sc->reset_noise_gain = tmp; sc->noise_gain = tmp + 1; @@ -8040,16 +6800,8 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw, DPRINTF(sc, IWN_DEBUG_RESET, "PAN Support found: %d\n", 1); break; - case IWN_FW_TLV_FLAGS: - if (len < sizeof(uint32_t)) - break; - if (len % sizeof(uint32_t)) - break; - sc->tlv_feature_flags = le32toh(*ptr); - DPRINTF(sc, IWN_DEBUG_RESET, - "%s: feature: 0x%08x\n", - __func__, - sc->tlv_feature_flags); + case IWN_FW_TLV_FLAGS : + sc->tlv_feature_flags = htole32(*ptr); break; case IWN_FW_TLV_PBREQ_MAXLEN: case IWN_FW_TLV_RUNT_EVTLOG_PTR: @@ -8121,8 +6873,6 @@ iwn_read_firmware(struct iwn_softc *sc) return error; } - device_printf(sc->sc_dev, "%s: ucode rev=0x%08x\n", __func__, sc->ucode_rev); - /* Make sure text and data sections fit in hardware memory. */ if (fw->main.textsz > sc->fw_text_maxsz || fw->main.datasz > sc->fw_data_maxsz || @@ -8187,8 +6937,9 @@ iwn_apm_init(struct iwn_softc *sc) else IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA); - if (sc->base_params->pll_cfg_val) - IWN_SETBITS(sc, IWN_ANA_PLL, sc->base_params->pll_cfg_val); + if (sc->hw_type != IWN_HW_REV_TYPE_4965 && + sc->hw_type <= IWN_HW_REV_TYPE_1000) + IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT); /* Wait for clock stabilization before accessing prph. */ if ((error = iwn_clock_wait(sc)) != 0) @@ -8300,13 +7051,13 @@ iwn5000_nic_config(struct iwn_softc *sc) /* Use internal power amplifier only. */ IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA); } - if (sc->base_params->additional_nic_config && sc->calib_ver >= 6) { + if ((sc->hw_type == IWN_HW_REV_TYPE_6050 || + sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) { /* Indicate that ROM calibration version is >=6. */ IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6); } - if (sc->base_params->additional_gp_drv_bit) - IWN_SETBITS(sc, IWN_GP_DRIVER, - sc->base_params->additional_gp_drv_bit); + if (sc->hw_type == IWN_HW_REV_TYPE_6005) + IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2); return 0; } @@ -8441,7 +7192,7 @@ iwn_hw_init(struct iwn_softc *sc) IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL); /* Enable shadow registers. */ - if (sc->base_params->shadow_reg_enable) + if (sc->hw_type >= IWN_HW_REV_TYPE_6000) IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff); if ((error = ops->load_firmware(sc)) != 0) { @@ -8554,44 +7305,6 @@ iwn_radio_off(void *arg0, int pending) } static void -iwn_panicked(void *arg0, int pending) -{ - struct iwn_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - int error; - - if (vap == NULL) { - printf("%s: null vap\n", __func__); - return; - } - - device_printf(sc->sc_dev, "%s: controller panicked, iv_state = %d; " - "resetting...\n", __func__, vap->iv_state); - - IWN_LOCK(sc); - - iwn_stop_locked(sc); - iwn_init_locked(sc); - if (vap->iv_state >= IEEE80211_S_AUTH && - (error = iwn_auth(sc, vap)) != 0) { - device_printf(sc->sc_dev, - "%s: could not move to auth state\n", __func__); - } - if (vap->iv_state >= IEEE80211_S_RUN && - (error = iwn_run(sc, vap)) != 0) { - device_printf(sc->sc_dev, - "%s: could not move to run state\n", __func__); - } - - /* Only run start once the NIC is in a useful state, like associated */ - iwn_start_locked(sc->sc_ifp); - - IWN_UNLOCK(sc); -} - -static void iwn_init_locked(struct iwn_softc *sc) { struct ifnet *ifp = sc->sc_ifp; @@ -8683,7 +7396,6 @@ iwn_stop_locked(struct iwn_softc *sc) IWN_LOCK_ASSERT(sc); - sc->sc_is_scanning = 0; sc->sc_tx_timer = 0; callout_stop(&sc->watchdog_to); callout_stop(&sc->calib_to); @@ -8774,11 +7486,10 @@ iwn_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) { struct ieee80211vap *vap = ss->ss_vap; struct iwn_softc *sc = vap->iv_ic->ic_ifp->if_softc; - struct ieee80211com *ic = vap->iv_ic; int error; IWN_LOCK(sc); - error = iwn_scan(sc, vap, ss, ic->ic_curchan); + error = iwn_scan(sc); IWN_UNLOCK(sc); if (error != 0) ieee80211_cancel_scan(vap); @@ -8810,6 +7521,7 @@ iwn_hw_reset(void *arg0, int pending) } #ifdef IWN_DEBUG #define IWN_DESC(x) case x: return #x +#define COUNTOF(array) (sizeof(array) / sizeof(array[0])) /* * Translate CSR code to string @@ -8880,7 +7592,7 @@ iwn_debug_register(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_REGISTER, "CSR values: (2nd byte of IWN_INT_COALESCING is IWN_INT_PERIODIC)%s", "\n"); - for (i = 0; i < nitems(csr_tbl); i++){ + for (i = 0; i < COUNTOF(csr_tbl); i++){ DPRINTF(sc, IWN_DEBUG_REGISTER," %10s: 0x%08x ", iwn_get_csr_string(csr_tbl[i]), IWN_READ(sc, csr_tbl[i])); if ((i+1) % 3 == 0) diff --git a/sys/dev/iwn/if_iwn_chip_cfg.h b/sys/dev/iwn/if_iwn_chip_cfg.h deleted file mode 100644 index ea6f3e1..0000000 --- a/sys/dev/iwn/if_iwn_chip_cfg.h +++ /dev/null @@ -1,413 +0,0 @@ -/*- - * Copyright (c) 2013 Cedric GROSS - * Copyright (c) 2011 Intel Corporation - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef __IF_IWN_CHIP_CFG_H__ -#define __IF_IWN_CHIP_CFG_H__ - -/* ========================================================================== - * NIC PARAMETERS - * - * ========================================================================== - */ - -/* - * Flags for managing calibration result. See calib_need - * in iwn_base_params struct - * - * These are bitmasks that determine which indexes in the calibcmd - * array are pushed up. - */ -#define IWN_FLG_NEED_PHY_CALIB_DC (1<<0) -#define IWN_FLG_NEED_PHY_CALIB_LO (1<<1) -#define IWN_FLG_NEED_PHY_CALIB_TX_IQ (1<<2) -#define IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC (1<<3) -#define IWN_FLG_NEED_PHY_CALIB_BASE_BAND (1<<4) -/* - * These aren't (yet) included in the calibcmd array, but - * are used as flags for which calibrations to use. - * - * XXX I think they should be named differently and - * stuffed in a different member in the config struct! - */ -#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET (1<<5) -#define IWN_FLG_NEED_PHY_CALIB_CRYSTAL (1<<6) -#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 (1<<7) - -/* - * Each chip has a different threshold for PLCP errors that should trigger a - * retune. - */ -#define IWN_PLCP_ERR_DEFAULT_THRESHOLD 50 -#define IWN_PLCP_ERR_LONG_THRESHOLD 100 -#define IWN_PLCP_ERR_EXT_LONG_THRESHOLD 200 - -/* - * Define some parameters for managing different NIC. - * Refer to linux specific file like iwl-xxxx.c to determine correct value - * for NIC. - * - * @max_ll_items: max number of OTP blocks - * @shadow_ram_support: shadow support for OTP memory - * @shadow_reg_enable: HW shadhow register bit - * @no_idle_support: do not support idle mode - * @advanced_bt_coexist : Advanced BT management - * @bt_session_2 : NIC need a new struct for configure BT coexistence. Needed - * only if advanced_bt_coexist is true - * @bt_sco_disable : - * @additional_nic_config: For 6005 series - * @iq_invert : ? But need it for N 2000 series - * @regulatory_bands : XXX - * @enhanced_TX_power : EEPROM Has advanced TX power options. Set 'True' - * if update_enhanced_txpower = iwl_eeprom_enhanced_txpower. - * See iwl-agn-devices.c file to determine that(enhanced_txpower) - * @need_temp_offset_calib : Need to compute some temp offset for calibration. - * @calib_need : Use IWN_FLG_NEED_PHY_CALIB_* flags to specify which - * calibration data ucode need. See calib_init_cfg in iwl-xxxx.c - * linux kernel file - * @support_hostap: Define IEEE80211_C_HOSTAP for ic_caps - * @no_multi_vaps: See iwn_vap_create - * @additional_gp_drv_bit : Specific bit to defined during nic_config - * @bt_mode: BT configuration mode - */ -enum bt_mode_enum { - IWN_BT_NONE, - IWN_BT_SIMPLE, - IWN_BT_ADVANCED -}; - -struct iwn_base_params { - uint32_t pll_cfg_val; - const uint16_t max_ll_items; -#define IWN_OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ -#define IWN_OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ -#define IWN_OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ -#define IWN_OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */ - const bool shadow_ram_support; - const bool shadow_reg_enable; - const bool bt_session_2; - const bool bt_sco_disable; - const bool additional_nic_config; - const uint32_t *regulatory_bands; - const bool enhanced_TX_power; - const uint16_t calib_need; - const bool support_hostap; - const bool no_multi_vaps; - uint8_t additional_gp_drv_bit; - enum bt_mode_enum bt_mode; - uint32_t plcp_err_threshold; -}; - -static const struct iwn_base_params iwn5000_base_params = { - .pll_cfg_val = IWN_ANA_PLL_INIT, /* pll_cfg_val; */ - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, /* max_ll_items */ - .shadow_ram_support = false, /* shadow_ram_support */ - .shadow_reg_enable = false, /* shadow_reg_enable */ - .bt_session_2 = false, /* bt_session_2 */ - .bt_sco_disable = true, /* bt_sco_disable */ - .additional_nic_config = false, /* additional_nic_config */ - .regulatory_bands = iwn5000_regulatory_bands, /* regulatory_bands */ - .enhanced_TX_power = false, /* enhanced_TX_power */ - .calib_need = - ( IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, /* support_hostap */ - .no_multi_vaps = true, /* no_multi_vaps */ - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, /* additional_gp_drv_bit */ - .bt_mode = IWN_BT_NONE, /* bt_mode */ - .plcp_err_threshold = IWN_PLCP_ERR_LONG_THRESHOLD, -}; - -/* - * 4965 support - */ -static const struct iwn_base_params iwn4965_base_params = { - .pll_cfg_val = 0, /* pll_cfg_val; */ - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, /* max_ll_items - ignored for 4965 */ - .shadow_ram_support = true, /* shadow_ram_support */ - .shadow_reg_enable = false, /* shadow_reg_enable */ - .bt_session_2 = false, /* bt_session_2 XXX unknown? */ - .bt_sco_disable = true, /* bt_sco_disable XXX unknown? */ - .additional_nic_config = false, /* additional_nic_config - not for 4965 */ - .regulatory_bands = iwn5000_regulatory_bands, /* regulatory_bands */ - .enhanced_TX_power = false, /* enhanced_TX_power - not for 4965 */ - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, /* support_hostap - XXX should work on fixing! */ - .no_multi_vaps = true, /* no_multi_vaps - XXX should work on fixing! */ - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, /* additional_gp_drv_bit */ - .bt_mode = IWN_BT_SIMPLE, /* bt_mode */ - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - - -static const struct iwn_base_params iwn2000_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_2x00, - .shadow_ram_support = true, - .shadow_reg_enable = false, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn2030_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ), - .support_hostap = true, - .no_multi_vaps = false, - .additional_gp_drv_bit = IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT, - .bt_mode = IWN_BT_NONE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -static const struct iwn_base_params iwn2030_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_2x00, - .shadow_ram_support = true, - .shadow_reg_enable = false, /* XXX check? */ - .bt_session_2 = true, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn2030_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ), - .support_hostap = true, - .no_multi_vaps = false, - .additional_gp_drv_bit = IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT, - .bt_mode = IWN_BT_ADVANCED, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -static const struct iwn_base_params iwn1000_base_params = { - .pll_cfg_val = IWN_ANA_PLL_INIT, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_1000, - .shadow_ram_support = false, - .shadow_reg_enable = false, /* XXX check? */ - .bt_session_2 = false, - .bt_sco_disable = false, - .additional_nic_config = false, - .regulatory_bands = iwn5000_regulatory_bands, - .enhanced_TX_power = false, - .calib_need = - ( IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - /* XXX 1000 - no BT */ - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_EXT_LONG_THRESHOLD, -}; -static const struct iwn_base_params iwn_6000_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = false, - .additional_nic_config = false, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; -static const struct iwn_base_params iwn_6000i_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; -static const struct iwn_base_params iwn_6000g2_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = 0, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -static const struct iwn_base_params iwn_6050_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x50, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = true, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; -static const struct iwn_base_params iwn_6150_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x50, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = true, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_6050_1X2, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -/* IWL_DEVICE_6035 & IWL_DEVICE_6030 */ -static const struct iwn_base_params iwn_6000g2b_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - .bt_mode = IWN_BT_ADVANCED, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -/* - * 6235 series NICs. - */ -static const struct iwn_base_params iwn_6235_base_params = { - .pll_cfg_val = 0, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = true, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = true, - .regulatory_bands = iwn6000_regulatory_bands, - .enhanced_TX_power = true, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND - | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), - .support_hostap = false, - .no_multi_vaps = true, - /* XXX 1x2? This NIC is 2x2, right? */ - .additional_gp_drv_bit = IWN_GP_DRIVER_6050_1X2, - .bt_mode = IWN_BT_ADVANCED, - .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD, -}; - -static const struct iwn_base_params iwn_5x50_base_params = { - .pll_cfg_val = IWN_ANA_PLL_INIT, - .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .shadow_reg_enable = false, - .bt_session_2 = false, - .bt_sco_disable = true, - .additional_nic_config = false, - .regulatory_bands = iwn5000_regulatory_bands, - .enhanced_TX_power =false, - .calib_need = - (IWN_FLG_NEED_PHY_CALIB_DC - | IWN_FLG_NEED_PHY_CALIB_LO - | IWN_FLG_NEED_PHY_CALIB_TX_IQ - | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), - .support_hostap = false, - .no_multi_vaps = true, - .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, - .bt_mode = IWN_BT_SIMPLE, - .plcp_err_threshold = IWN_PLCP_ERR_LONG_THRESHOLD, -}; - -#endif /* __IF_IWN_CHIP_CFG_H__ */ diff --git a/sys/dev/iwn/if_iwn_debug.h b/sys/dev/iwn/if_iwn_debug.h deleted file mode 100644 index 2932c7e..0000000 --- a/sys/dev/iwn/if_iwn_debug.h +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * Copyright (c) 2013 Cedric GROSS - * Copyright (c) 2011 Intel Corporation - * Copyright (c) 2007-2009 - * Damien Bergamini - * Copyright (c) 2008 - * Benjamin Close - * Copyright (c) 2008 Sam Leffler, Errno Consulting - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef __IF_IWN_DEBUG_H__ -#define __IF_IWN_DEBUG_H__ - -#ifdef IWN_DEBUG -enum { - IWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - IWN_DEBUG_RECV = 0x00000002, /* basic recv operation */ - IWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */ - IWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */ - IWN_DEBUG_RESET = 0x00000010, /* reset processing */ - IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */ - IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */ - IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ - IWN_DEBUG_INTR = 0x00000100, /* ISR */ - IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */ - IWN_DEBUG_NODE = 0x00000400, /* node management */ - IWN_DEBUG_LED = 0x00000800, /* led management */ - IWN_DEBUG_CMD = 0x00001000, /* cmd submission */ - IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */ - IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ - IWN_DEBUG_SCAN = 0x00008000, /* Scan related operations */ - IWN_DEBUG_STATS = 0x00010000, /* Statistics updates */ - IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */ - IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */ - IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ - IWN_DEBUG_ANY = 0xffffffff -}; - -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) - -static const char * -iwn_intr_str(uint8_t cmd) -{ - switch (cmd) { - /* Notifications */ - case IWN_UC_READY: return "UC_READY"; - case IWN_ADD_NODE_DONE: return "ADD_NODE_DONE"; - case IWN_TX_DONE: return "TX_DONE"; - case IWN_START_SCAN: return "START_SCAN"; - case IWN_STOP_SCAN: return "STOP_SCAN"; - case IWN_RX_STATISTICS: return "RX_STATS"; - case IWN_BEACON_STATISTICS: return "BEACON_STATS"; - case IWN_STATE_CHANGED: return "STATE_CHANGED"; - case IWN_BEACON_MISSED: return "BEACON_MISSED"; - case IWN_RX_PHY: return "RX_PHY"; - case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE"; - case IWN_RX_DONE: return "RX_DONE"; - - /* Command Notifications */ - case IWN_CMD_RXON: return "IWN_CMD_RXON"; - case IWN_CMD_RXON_ASSOC: return "IWN_CMD_RXON_ASSOC"; - case IWN_CMD_EDCA_PARAMS: return "IWN_CMD_EDCA_PARAMS"; - case IWN_CMD_TIMING: return "IWN_CMD_TIMING"; - case IWN_CMD_LINK_QUALITY: return "IWN_CMD_LINK_QUALITY"; - case IWN_CMD_SET_LED: return "IWN_CMD_SET_LED"; - case IWN5000_CMD_WIMAX_COEX: return "IWN5000_CMD_WIMAX_COEX"; - case IWN5000_CMD_CALIB_CONFIG: return "IWN5000_CMD_CALIB_CONFIG"; - case IWN5000_CMD_CALIB_RESULT: return "IWN5000_CMD_CALIB_RESULT"; - case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE"; - case IWN_CMD_SET_POWER_MODE: return "IWN_CMD_SET_POWER_MODE"; - case IWN_CMD_SCAN: return "IWN_CMD_SCAN"; - case IWN_CMD_SCAN_RESULTS: return "IWN_CMD_SCAN_RESULTS"; - case IWN_CMD_TXPOWER: return "IWN_CMD_TXPOWER"; - case IWN_CMD_TXPOWER_DBM: return "IWN_CMD_TXPOWER_DBM"; - case IWN5000_CMD_TX_ANT_CONFIG: return "IWN5000_CMD_TX_ANT_CONFIG"; - case IWN_CMD_BT_COEX: return "IWN_CMD_BT_COEX"; - case IWN_CMD_SET_CRITICAL_TEMP: return "IWN_CMD_SET_CRITICAL_TEMP"; - case IWN_CMD_SET_SENSITIVITY: return "IWN_CMD_SET_SENSITIVITY"; - case IWN_CMD_PHY_CALIB: return "IWN_CMD_PHY_CALIB"; - - /* Bluetooth commands */ - case IWN_CMD_BT_COEX_PRIOTABLE: return "IWN_CMD_BT_COEX_PRIOTABLE"; - case IWN_CMD_BT_COEX_PROT: return "IWN_CMD_BT_COEX_PROT"; - case IWN_CMD_BT_COEX_NOTIF: return "IWN_CMD_BT_COEX_NOTIF"; - - /* PAN commands */ - case IWN_CMD_WIPAN_PARAMS: return "IWN_CMD_WIPAN_PARAMS"; - case IWN_CMD_WIPAN_RXON: return "IWN_CMD_WIPAN_RXON"; - case IWN_CMD_WIPAN_RXON_TIMING: return "IWN_CMD_WIPAN_RXON_TIMING"; - case IWN_CMD_WIPAN_RXON_ASSOC: return "IWN_CMD_WIPAN_RXON_ASSOC"; - case IWN_CMD_WIPAN_QOS_PARAM: return "IWN_CMD_WIPAN_QOS_PARAM"; - case IWN_CMD_WIPAN_WEPKEY: return "IWN_CMD_WIPAN_WEPKEY"; - case IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH: - return "IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH"; - case IWN_CMD_WIPAN_NOA_NOTIFICATION: - return "IWN_CMD_WIPAN_NOA_NOTIFICATION"; - case IWN_CMD_WIPAN_DEACTIVATION_COMPLETE: - return "IWN_CMD_WIPAN_DEACTIVATION_COMPLETE"; - } - return "UNKNOWN INTR NOTIF/CMD"; -} -#else -#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0) -#endif - -#endif /* __IF_IWN_DEBUG_H__ */ diff --git a/sys/dev/iwn/if_iwn_devid.h b/sys/dev/iwn/if_iwn_devid.h index dd08737..23fd0a1 100644 --- a/sys/dev/iwn/if_iwn_devid.h +++ b/sys/dev/iwn/if_iwn_devid.h @@ -41,20 +41,6 @@ * DEVICE ID BLOCK * ========================================================================== */ - -/* - * -------------------------------------------------------------------------- - * Device ID for 2x00 series - * -------------------------------------------------------------------------- - */ -#define IWN_DID_2x00_1 0x0890 -#define IWN_DID_2x00_2 0x0891 -/* SubDevice ID */ -#define IWN_SDID_2x00_1 0x4022 -#define IWN_SDID_2x00_2 0x4222 -#define IWN_SDID_2x00_3 0x4422 -#define IWN_SDID_2x00_4 0x4822 - /* * -------------------------------------------------------------------------- * Device ID for 2x30 series @@ -228,31 +214,6 @@ /* * -------------------------------------------------------------------------- - * Device ID for 105 Series - * -------------------------------------------------------------------------- - */ -#define IWN_DID_105_1 0x0894 -#define IWN_DID_105_2 0x0895 -/* SubDevice ID */ -#define IWN_SDID_105_1 0x0022 -#define IWN_SDID_105_2 0x0222 -#define IWN_SDID_105_3 0x0422 -#define IWN_SDID_105_4 0x0822 - -/* - * -------------------------------------------------------------------------- - * Device ID for 135 Series - * -------------------------------------------------------------------------- - */ -#define IWN_DID_135_1 0x0892 -#define IWN_DID_135_2 0x0893 -/* SubDevice ID */ -#define IWN_SDID_135_1 0x0062 -#define IWN_SDID_135_2 0x0262 -#define IWN_SDID_135_3 0x0462 - -/* - * -------------------------------------------------------------------------- * Device ID for 5x00 Series * -------------------------------------------------------------------------- */ diff --git a/sys/dev/iwn/if_iwn_ioctl.h b/sys/dev/iwn/if_iwn_ioctl.h deleted file mode 100644 index 1acf464..0000000 --- a/sys/dev/iwn/if_iwn_ioctl.h +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * Copyright (c) 2014 Adrian Chadd - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ -#ifndef __IF_IWN_IOCTL_H__ -#define __IF_IWN_IOCTL_H__ - -/* XXX how should I pick appropriate ioctl numbers? */ -#define SIOCGIWNSTATS _IOWR('i', 145, struct ifreq) -#define SIOCZIWNSTATS _IOWR('i', 146, struct ifreq) - -#endif /* __IF_IWN_IOCTL_H__ */ diff --git a/sys/dev/iwn/if_iwnreg.h b/sys/dev/iwn/if_iwnreg.h index ed65c0b..e61d0fd 100644 --- a/sys/dev/iwn/if_iwnreg.h +++ b/sys/dev/iwn/if_iwnreg.h @@ -17,8 +17,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef __IF_IWNREG_H__ -#define __IF_IWNREG_H__ #define IWN_CT_KILL_THRESHOLD 114 /* in Celsius */ #define IWN_CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */ @@ -224,7 +222,6 @@ #define IWN_GP_DRIVER_CALIB_VER6 (1 << 2) #define IWN_GP_DRIVER_6050_1X2 (1 << 3) #define IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT (1 << 7) -#define IWN_GP_DRIVER_NONE 0 /* Possible flags for register IWN_UCODE_GP1_CLR. */ #define IWN_UCODE_GP1_RFKILL (1 << 1) @@ -489,7 +486,6 @@ struct iwn_tx_cmd { #define IWN_CMD_TXPOWER_DBM 149 #define IWN_CMD_TXPOWER 151 #define IWN5000_CMD_TX_ANT_CONFIG 152 -#define IWN_CMD_TXPOWER_DBM_V1 152 #define IWN_CMD_BT_COEX 155 #define IWN_CMD_GET_STATISTICS 156 #define IWN_CMD_SET_CRITICAL_TEMP 164 @@ -886,7 +882,7 @@ struct iwn_scan_essid { struct iwn_scan_hdr { uint16_t len; - uint8_t scan_flags; + uint8_t reserved1; uint8_t nchan; uint16_t quiet_time; uint16_t quiet_threshold; @@ -923,53 +919,17 @@ struct iwn_scan_chan { /* Maximum size of a scan command. */ #define IWN_SCAN_MAXSZ (MCLBYTES - 4) -/* - * For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after - * sending probe req. This should be set long enough to hear probe responses - * from more than one AP. - */ -#define IWN_ACTIVE_DWELL_TIME_2GHZ (30) /* all times in msec */ -#define IWN_ACTIVE_DWELL_TIME_5GHZ (20) -#define IWN_ACTIVE_DWELL_FACTOR_2GHZ (3) -#define IWN_ACTIVE_DWELL_FACTOR_5GHZ (2) +#define IWN_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ +#define IWN_ACTIVE_DWELL_TIME_52 (20) +#define IWN_ACTIVE_DWELL_FACTOR_24 (3) +#define IWN_ACTIVE_DWELL_FACTOR_52 (2) -/* - * For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. - * Must be set longer than active dwell time. - * For the most reliable scan, set > AP beacon interval (typically 100msec). - */ -#define IWN_PASSIVE_DWELL_TIME_2GHZ (20) /* all times in msec */ -#define IWN_PASSIVE_DWELL_TIME_5GHZ (10) +#define IWN_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ +#define IWN_PASSIVE_DWELL_TIME_52 (10) #define IWN_PASSIVE_DWELL_BASE (100) #define IWN_CHANNEL_TUNE_TIME (5) #define IWN_SCAN_CHAN_TIMEOUT 2 -#define IWN_MAX_SCAN_CHANNEL 50 - -/* - * If active scanning is requested but a certain channel is - * marked passive, we can do active scanning if we detect - * transmissions. - * - * There is an issue with some firmware versions that triggers - * a sysassert on a "good CRC threshold" of zero (== disabled), - * on a radar channel even though this means that we should NOT - * send probes. - * - * The "good CRC threshold" is the number of frames that we - * need to receive during our dwell time on a channel before - * sending out probes -- setting this to a huge value will - * mean we never reach it, but at the same time work around - * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER - * here instead of IWL_GOOD_CRC_TH_DISABLED. - * - * This was fixed in later versions along with some other - * scan changes, and the threshold behaves as a flag in those - * versions. - */ -#define IWN_GOOD_CRC_TH_DISABLED 0 -#define IWN_GOOD_CRC_TH_DEFAULT htole16(1) -#define IWN_GOOD_CRC_TH_NEVER htole16(0xffff) /* Structure for command IWN_CMD_TXPOWER (4965AGN only.) */ #define IWN_RIDX_MAX 32 @@ -1142,12 +1102,6 @@ struct iwn_enhanced_sensitivity_cmd { uint16_t reserved; } __packed; -/* - * Define maximal number of calib result send to runtime firmware - * PS: TEMP_OFFSET count for 2 (std and v2) - */ -#define IWN5000_PHY_CALIB_MAX_RESULT 8 - /* Structures for command IWN_CMD_PHY_CALIB. */ struct iwn_phy_calib { uint8_t code; @@ -1267,91 +1221,17 @@ struct iwn_ucode_info { } __packed; /* Structures for IWN_TX_DONE notification. */ - -/* - * TX command response is sent after *agn* transmission attempts. - * - * both postpone and abort status are expected behavior from uCode. there is - * no special operation required from driver; except for RFKILL_FLUSH, - * which required tx flush host command to flush all the tx frames in queues - */ -#define IWN_TX_STATUS_MSK 0x000000ff -#define IWN_TX_STATUS_DELAY_MSK 0x00000040 -#define IWN_TX_STATUS_ABORT_MSK 0x00000080 -#define IWN_TX_PACKET_MODE_MSK 0x0000ff00 -#define IWN_TX_FIFO_NUMBER_MSK 0x00070000 -#define IWN_TX_RESERVED 0x00780000 -#define IWN_TX_POWER_PA_DETECT_MSK 0x7f800000 -#define IWN_TX_ABORT_REQUIRED_MSK 0x80000000 - -/* Success status */ -#define IWN_TX_STATUS_SUCCESS 0x01 -#define IWN_TX_STATUS_DIRECT_DONE 0x02 - -/* postpone TX */ -#define IWN_TX_STATUS_POSTPONE_DELAY 0x40 -#define IWN_TX_STATUS_POSTPONE_FEW_BYTES 0x41 -#define IWN_TX_STATUS_POSTPONE_BT_PRIO 0x42 -#define IWN_TX_STATUS_POSTPONE_QUIET_PERIOD 0x43 -#define IWN_TX_STATUS_POSTPONE_CALC_TTAK 0x44 - -/* Failures */ -#define IWN_TX_FAIL 0x80 /* all failures have 0x80 set */ -#define IWN_TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY 0x81 -#define IWN_TX_FAIL_SHORT_LIMIT 0x82 /* too many RTS retries */ -#define IWN_TX_FAIL_LONG_LIMIT 0x83 /* too many retries */ -#define IWN_TX_FAIL_FIFO_UNDERRRUN 0x84 /* tx fifo not kept running */ -#define IWN_TX_STATUS_FAIL_DRAIN_FLOW 0x85 -#define IWN_TX_STATUS_FAIL_RFKILL_FLUSH 0x86 -#define IWN_TX_STATUS_FAIL_LIFE_EXPIRE 0x87 -#define IWN_TX_FAIL_DEST_IN_PS 0x88 /* sta found in power save */ -#define IWN_TX_STATUS_FAIL_HOST_ABORTED 0x89 -#define IWN_TX_STATUS_FAIL_BT_RETRY 0x8a -#define IWN_TX_FAIL_STA_INVALID 0x8b /* XXX STA invalid (???) */ -#define IWN_TX_STATUS_FAIL_FRAG_DROPPED 0x8c -#define IWN_TX_STATUS_FAIL_TID_DISABLE 0x8d -#define IWN_TX_STATUS_FAIL_FIFO_FLUSHED 0x8e -#define IWN_TX_STATUS_FAIL_INSUFFICIENT_CF_POLL 0x8f -#define IWN_TX_FAIL_TX_LOCKED 0x90 /* waiting to see traffic */ -#define IWN_TX_STATUS_FAIL_NO_BEACON_ON_RADAR 0x91 - -/* - * TX command response for A-MPDU packet responses. - * - * The status response is different to the non A-MPDU responses. - * In addition, the sequence number is treated as the sequence - * number of the TX command, NOT the 802.11 sequence number! - */ -#define IWN_AGG_TX_STATE_TRANSMITTED 0x00 -#define IWN_AGG_TX_STATE_UNDERRUN_MSK 0x01 -#define IWN_AGG_TX_STATE_FEW_BYTES_MSK 0x04 -#define IWN_AGG_TX_STATE_ABORT_MSK 0x08 - -#define IWN_AGG_TX_STATE_LAST_SENT_TTL_MSK 0x10 -#define IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK 0x20 - -#define IWN_AGG_TX_STATE_SCD_QUERY_MSK 0x80 - -#define IWN_AGG_TX_STATE_TEST_BAD_CRC32_MSK 0x100 - -#define IWN_AGG_TX_STATE_RESPONSE_MSK 0x1ff -#define IWN_AGG_TX_STATE_DUMP_TX_MSK 0x200 -#define IWN_AGG_TX_STATE_DELAY_TX_MSK 0x400 - -#define IWN_AGG_TX_STATUS_MSK 0x00000fff -#define IWN_AGG_TX_TRY_MSK 0x0000f000 - -#define IWN_AGG_TX_STATE_LAST_SENT_MSK \ - (IWN_AGG_TX_STATE_LAST_SENT_TTL_MSK | \ - IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK) - -/* # tx attempts for first frame in aggregation */ -#define IWN_AGG_TX_STATE_TRY_CNT_POS 12 -#define IWN_AGG_TX_STATE_TRY_CNT_MSK 0xf000 - -/* Command ID and sequence number of Tx command for this frame */ -#define IWN_AGG_TX_STATE_SEQ_NUM_POS 16 -#define IWN_AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000 +#define IWN_TX_STATUS_MSK 0xff +#define TX_STATUS_SUCCESS 0x01 +#define TX_STATUS_DIRECT_DONE 0x02 + +#define IWN_TX_SUCCESS 0x00 +#define IWN_TX_FAIL 0x80 /* all failures have 0x80 set */ +#define IWN_TX_FAIL_SHORT_LIMIT 0x82 /* too many RTS retries */ +#define IWN_TX_FAIL_LONG_LIMIT 0x83 /* too many retries */ +#define IWN_TX_FAIL_FIFO_UNDERRRUN 0x84 /* tx fifo not kept running */ +#define IWN_TX_FAIL_DEST_IN_PS 0x88 /* sta found in power save */ +#define IWN_TX_FAIL_TX_LOCKED 0x90 /* waiting to see traffic */ struct iwn4965_tx_stat { uint8_t nframes; @@ -1478,12 +1358,6 @@ struct iwn_compressed_ba { uint64_t bitmap; uint16_t qid; uint16_t ssn; - /* extra fields starting with iwn5000 */ -#if 0 - uint8_t txed; /* number of frames sent */ - uint8_t txed_2_done; /* number of frames acked */ - uint16_t reserved1; -#endif } __packed; /* Structure for IWN_START_SCAN notification. */ @@ -1589,7 +1463,7 @@ struct iwn_rx_ht_phy_stats { uint32_t good_ampdu_crc32; uint32_t ampdu; uint32_t fragment; - uint32_t unsupport_mcs; + uint32_t reserved; } __packed; struct iwn_rx_stats { @@ -1599,20 +1473,6 @@ struct iwn_rx_stats { struct iwn_rx_ht_phy_stats ht; } __packed; -struct iwn_rx_general_stats_bt { - struct iwn_rx_general_stats common; - /* additional stats for bt */ - uint32_t num_bt_kills; - uint32_t reserved[2]; -} __packed; - -struct iwn_rx_stats_bt { - struct iwn_rx_phy_stats ofdm; - struct iwn_rx_phy_stats cck; - struct iwn_rx_general_stats_bt general_bt; - struct iwn_rx_ht_phy_stats ht; -} __packed; - struct iwn_tx_stats { uint32_t preamble; uint32_t rx_detected; @@ -1624,7 +1484,7 @@ struct iwn_tx_stats { uint32_t exp_ack; uint32_t ack; uint32_t msdu; - uint32_t burst_err1; + uint32_t busrt_err1; uint32_t burst_err2; uint32_t cts_collision; uint32_t ack_collision; @@ -1638,21 +1498,15 @@ struct iwn_tx_stats { uint32_t underrun; uint32_t bt_ht_kill; uint32_t rx_ba_resp; - /* - * 6000 series only - LSB=ant A, ant B, ant C, MSB=reserved - * TX power on chain in 1/2 dBm. - */ - uint32_t tx_power; - uint32_t reserved[1]; + uint32_t reserved[2]; } __packed; struct iwn_general_stats { - uint32_t temp; /* radio temperature */ - uint32_t temp_m; /* radio voltage */ + uint32_t temp; + uint32_t temp_m; uint32_t burst_check; uint32_t burst; - uint32_t wait_for_silence_timeout_cnt; - uint32_t reserved1[3]; + uint32_t reserved1[4]; uint32_t sleep; uint32_t slot_out; uint32_t slot_idle; @@ -1663,11 +1517,7 @@ struct iwn_general_stats { uint32_t probe; uint32_t reserved2[2]; uint32_t rx_enabled; - /* - * This is the number of times we have to re-tune - * in order to get out of bad PHY status. - */ - uint32_t num_of_sos_states; + uint32_t reserved3[3]; } __packed; struct iwn_stats { @@ -1675,30 +1525,8 @@ struct iwn_stats { struct iwn_rx_stats rx; struct iwn_tx_stats tx; struct iwn_general_stats general; - uint32_t reserved1[2]; } __packed; -struct iwn_bt_activity_stats { - /* Tx statistics */ - uint32_t hi_priority_tx_req_cnt; - uint32_t hi_priority_tx_denied_cnt; - uint32_t lo_priority_tx_req_cnt; - uint32_t lo_priority_tx_denied_cnt; - /* Rx statistics */ - uint32_t hi_priority_rx_req_cnt; - uint32_t hi_priority_rx_denied_cnt; - uint32_t lo_priority_rx_req_cnt; - uint32_t lo_priority_rx_denied_cnt; -} __packed; - -struct iwn_stats_bt { - uint32_t flags; - struct iwn_rx_stats_bt rx_bt; - struct iwn_tx_stats tx; - struct iwn_general_stats general; - struct iwn_bt_activity_stats activity; - uint32_t reserved1[2]; -}; /* Firmware error dump. */ struct iwn_fw_dump { @@ -1736,7 +1564,7 @@ struct iwn_fw_tlv { #define IWN_FW_TLV_INIT_DATA 4 #define IWN_FW_TLV_BOOT_TEXT 5 #define IWN_FW_TLV_PBREQ_MAXLEN 6 -#define IWN_FW_TLV_PAN 7 +#define IWN_FW_TLV_PAN 7 #define IWN_FW_TLV_RUNT_EVTLOG_PTR 8 #define IWN_FW_TLV_RUNT_EVTLOG_SIZE 9 #define IWN_FW_TLV_RUNT_ERRLOG_PTR 10 @@ -1747,7 +1575,7 @@ struct iwn_fw_tlv { #define IWN_FW_TLV_PHY_CALIB 15 #define IWN_FW_TLV_WOWLAN_INST 16 #define IWN_FW_TLV_WOWLAN_DATA 17 -#define IWN_FW_TLV_FLAGS 18 +#define IWN_FW_TLV_FLAGS 18 uint16_t alt; uint32_t len; @@ -1762,60 +1590,6 @@ struct iwn_fw_tlv { #define IWN5000_FWSZ IWN5000_FW_TEXT_MAXSZ /* - * Microcode flags TLV (18.) - */ - -/** - * enum iwn_ucode_tlv_flag - ucode API flags - * @IWN_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously - * was a separate TLV but moved here to save space. - * @IWN_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, - * treats good CRC threshold as a boolean - * @IWN_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). - * @IWN_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. - * @IWN_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS - * @IWN_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD - * @IWN_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan - * offload profile config command. - * @IWN_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api - * @IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. - * @IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six - * (rather than two) IPv6 addresses - * @IWN_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API - * @IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element - * from the probe request template. - * @IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping - * connection when going back to D0 - * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version) - * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) - * @IWN_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan. - * @IWN_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API - * @IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command - * containing CAM (Continuous Active Mode) indication. - */ -enum iwn_ucode_tlv_flag { - IWN_UCODE_TLV_FLAGS_PAN = (1 << 0), - IWN_UCODE_TLV_FLAGS_NEWSCAN = (1 << 1), - IWN_UCODE_TLV_FLAGS_MFP = (1 << 2), - IWN_UCODE_TLV_FLAGS_P2P = (1 << 3), - IWN_UCODE_TLV_FLAGS_DW_BC_TABLE = (1 << 4), - IWN_UCODE_TLV_FLAGS_NEWBT_COEX = (1 << 5), - IWN_UCODE_TLV_FLAGS_UAPSD = (1 << 6), - IWN_UCODE_TLV_FLAGS_SHORT_BL = (1 << 7), - IWN_UCODE_TLV_FLAGS_RX_ENERGY_API = (1 << 8), - IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = (1 << 9), - IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = (1 << 10), - IWN_UCODE_TLV_FLAGS_BF_UPDATED = (1 << 11), - IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID = (1 << 12), - IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API = (1 << 14), - IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = (1 << 15), - IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = (1 << 16), - IWN_UCODE_TLV_FLAGS_SCHED_SCAN = (1 << 17), - IWN_UCODE_TLV_FLAGS_STA_KEY_CMD = (1 << 19), - IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD = (1 << 20), -}; - -/* * Offsets into EEPROM. */ #define IWN_EEPROM_MAC 0x015 @@ -1957,16 +1731,6 @@ static const uint32_t iwn1000_regulatory_bands[IWN_NBANDS] = { IWN5000_EEPROM_NO_HT40, }; -static const uint32_t iwn2030_regulatory_bands[IWN_NBANDS] = { - IWN5000_EEPROM_BAND1, - IWN5000_EEPROM_BAND2, - IWN5000_EEPROM_BAND3, - IWN5000_EEPROM_BAND4, - IWN5000_EEPROM_BAND5, - IWN6000_EEPROM_BAND6, - IWN5000_EEPROM_BAND7 -}; - #define IWN_CHAN_BANDS_COUNT 7 #define IWN_MAX_CHAN_PER_BAND 14 static const struct iwn_chan_band { @@ -1993,8 +1757,8 @@ static const uint8_t iwn_bss_ac_to_queue[] = { static const uint8_t iwn_pan_ac_to_queue[] = { 5, 4, 6, 7, }; -#define IWN1000_OTP_NBLOCKS 3 -#define IWN6000_OTP_NBLOCKS 4 +#define IWN1000_OTP_NBLOCKS 3 +#define IWN6000_OTP_NBLOCKS 4 #define IWN6050_OTP_NBLOCKS 7 /* HW rate indices. */ @@ -2127,7 +1891,6 @@ struct iwn_sensitivity_limits { uint32_t min_energy_cck; uint32_t energy_cck; uint32_t energy_ofdm; - uint32_t barker_mrc; }; /* @@ -2142,8 +1905,7 @@ static const struct iwn_sensitivity_limits iwn4965_sensitivity_limits = { 200, 400, 97, 100, - 100, - 390 + 100 }; static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = { @@ -2155,8 +1917,7 @@ static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = { 170, 400, 95, 95, - 95, - 390 + 95 }; static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = { @@ -2168,8 +1929,7 @@ static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = { 170, 400, 95, 95, - 95, - 390, + 95 }; static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = { @@ -2181,8 +1941,7 @@ static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = { 170, 400, 95, 95, - 95, - 390, + 95 }; static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = { @@ -2194,24 +1953,9 @@ static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = { 160, 310, 97, 97, - 100, - 390 -}; - -static const struct iwn_sensitivity_limits iwn6235_sensitivity_limits = { - 105, 110, - 192, 232, - 80, 145, - 128, 232, - 125, 175, - 160, 310, - 100, - 110, - 110, - 336 + 100 }; - /* Get value from linux kernel 3.2.+ in Drivers/net/wireless/iwlwifi/iwl-2000.c*/ static const struct iwn_sensitivity_limits iwn2030_sensitivity_limits = { 105,110, @@ -2308,5 +2052,3 @@ static const char * const iwn_fw_errmsg[] = { #define IWN_BARRIER_READ_WRITE(sc) \ bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) - -#endif /* __IF_IWNREG_H__ */ diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h index b14158b..11a233d 100644 --- a/sys/dev/iwn/if_iwnvar.h +++ b/sys/dev/iwn/if_iwnvar.h @@ -163,7 +163,6 @@ struct iwn_calib_state { uint32_t bad_plcp_cck; uint32_t fa_cck; uint32_t low_fa; - uint32_t bad_plcp_ht; uint8_t cck_state; #define IWN_CCK_STATE_INIT 0 #define IWN_CCK_STATE_LOFA 1 @@ -250,7 +249,6 @@ struct iwn_softc { #define IWN_FLAG_ENH_SENS (1 << 7) #define IWN_FLAG_ADV_BTCOEX (1 << 8) #define IWN_FLAG_PAN_SUPPORT (1 << 9) -#define IWN_FLAG_BTCOEX (1 << 10) uint8_t hw_type; /* subdevice_id used to adjust configuration */ @@ -308,20 +306,14 @@ struct iwn_softc { struct task sc_reinit_task; struct task sc_radioon_task; struct task sc_radiooff_task; - struct task sc_panic_task; - /* Taskqueue */ - struct taskqueue *sc_tq; - - /* Calibration information */ struct callout calib_to; int calib_cnt; struct iwn_calib_state calib; - int last_calib_ticks; struct callout watchdog_to; struct callout ct_kill_exit_to; struct iwn_fw_info fw; - struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT]; + struct iwn_calib_info calibcmd[5]; uint32_t errptr; struct iwn_rx_stat last_rx_stat; @@ -332,22 +324,6 @@ struct iwn_softc { int ctx; struct ieee80211vap *ivap[IWN_NUM_RXON_CTX]; - /* General statistics */ - /* - * The statistics are reset after each channel - * change. So it may be zeroed after things like - * a background scan. - * - * So for now, this is just a cheap hack to - * expose the last received statistics dump - * via an ioctl(). Later versions of this - * could expose the last 'n' messages, or just - * provide a pipeline for the firmware responses - * via something like BPF. - */ - struct iwn_stats last_stat; - int last_stat_valid; - uint8_t uc_scan_progress; uint32_t rawtemp; int temp; @@ -382,9 +358,6 @@ struct iwn_softc { int sc_tx_timer; int sc_scan_timer; - /* Are we doing a scan? */ - int sc_is_scanning; - struct ieee80211_tx_ampdu *qid2tap[IWN5000_NTXQUEUES]; int (*sc_ampdu_rx_start)(struct ieee80211_node *, @@ -412,11 +385,8 @@ struct iwn_softc { */ int current_pwrsave_level; - /* For specific params */ - const struct iwn_base_params *base_params; - -#define IWN_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) - uint32_t ucode_rev; + /* For specifique params */ + struct iwn_base_params *base_params; }; #define IWN_LOCK_INIT(_sc) \ diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 02c9310..1bda391 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -959,7 +958,7 @@ rt2560_tx_intr(struct rt2560_softc *sc) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; break; case RT2560_TX_SUCCESS_RETRY: @@ -971,7 +970,7 @@ rt2560_tx_intr(struct rt2560_softc *sc) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; break; case RT2560_TX_FAIL_RETRY: @@ -983,7 +982,7 @@ rt2560_tx_intr(struct rt2560_softc *sc) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; case RT2560_TX_FAIL_INVALID: @@ -991,7 +990,7 @@ rt2560_tx_intr(struct rt2560_softc *sc) default: device_printf(sc->sc_dev, "sending data frame failed " "0x%08x\n", flags); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } bus_dmamap_sync(sc->txq.data_dmat, data->map, @@ -1144,13 +1143,13 @@ rt2560_decryption_intr(struct rt2560_softc *sc) break; if (data->drop) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 && (le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1163,7 +1162,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc) */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1186,7 +1185,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc) panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1936,7 +1935,7 @@ rt2560_start_locked(struct ifnet *ifp) ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; if (rt2560_tx_data(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } @@ -1973,7 +1972,7 @@ rt2560_watchdog(void *arg) if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { if_printf(ifp, "device timeout\n"); rt2560_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; /* NB: callout is reset in rt2560_init() */ return; } @@ -2796,7 +2795,7 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return ENOBUFS; /* XXX */ } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (params == NULL) { /* @@ -2819,7 +2818,7 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 448ba57..a0fb158 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -909,7 +908,7 @@ rt2661_tx_intr(struct rt2661_softc *sc) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; break; case RT2661_TX_RETRY_FAIL: @@ -921,14 +920,14 @@ rt2661_tx_intr(struct rt2661_softc *sc) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; default: /* other failure */ device_printf(sc->sc_dev, "sending data frame failed 0x%08x\n", val); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat); @@ -1015,12 +1014,12 @@ rt2661_rx_intr(struct rt2661_softc *sc) */ DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n", le32toh(desc->flags)); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1033,7 +1032,7 @@ rt2661_rx_intr(struct rt2661_softc *sc) */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1056,7 +1055,7 @@ rt2661_rx_intr(struct rt2661_softc *sc) panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1631,7 +1630,7 @@ rt2661_start_locked(struct ifnet *ifp) ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; if (rt2661_tx_data(sc, m, ni, ac) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } @@ -1674,7 +1673,7 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return ENOBUFS; /* XXX */ } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; /* * Legacy path; interpret frame contents to decide @@ -1689,7 +1688,7 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ @@ -1711,7 +1710,7 @@ rt2661_watchdog(void *arg) if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { if_printf(ifp, "device timeout\n"); rt2661_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; /* NB: callout is reset in rt2661_init() */ return; } diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c index b29a0eb..3eb7187 100644 --- a/sys/dev/ral/rt2860.c +++ b/sys/dev/ral/rt2860.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -1135,7 +1134,7 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc) } else { ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } } } @@ -1169,7 +1168,7 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid) SLIST_INSERT_HEAD(&sc->data_pool, data, next); ring->data[ring->next] = NULL; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } ring->queued--; ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; @@ -1232,7 +1231,7 @@ rt2860_rx_intr(struct rt2860_softc *sc) if (__predict_false(rxd->flags & htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1241,14 +1240,14 @@ rt2860_rx_intr(struct rt2860_softc *sc) /* report MIC failures to net80211 for TKIP */ ic->ic_stats.is_rx_locmicfail++; ieee80211_michael_mic_failure(ic, 0/* XXX */); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } #endif m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m1 == NULL)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1272,7 +1271,7 @@ rt2860_rx_intr(struct rt2860_softc *sc) } /* physical address may have changed */ rxd->sdp0 = htole32(physaddr); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto skip; } @@ -1752,7 +1751,7 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (error != 0) { /* NB: m is reclaimed on tx failure */ ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } sc->sc_tx_timer = 5; RAL_UNLOCK(sc); @@ -2005,7 +2004,7 @@ rt2860_start_locked(struct ifnet *ifp) ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (rt2860_tx(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; continue; } sc->sc_tx_timer = 5; @@ -2029,7 +2028,7 @@ rt2860_watchdog(void *arg) if_printf(ifp, "device timeout\n"); rt2860_stop_locked(sc); rt2860_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index a6b5ebd..4ad6ab5 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -72,7 +71,7 @@ __FBSDID("$FreeBSD$"); #ifdef USB_DEBUG static int rsu_debug = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, rsu, CTLFLAG_RW, 0, "USB rsu"); -SYSCTL_INT(_hw_usb_rsu, OID_AUTO, debug, CTLFLAG_RWTUN, &rsu_debug, 0, +SYSCTL_INT(_hw_usb_rsu, OID_AUTO, debug, CTLFLAG_RW, &rsu_debug, 0, "Debug level"); #endif @@ -121,7 +120,6 @@ static const STRUCT_USB_HOST_ID rsu_devs[] = { RSU_DEV_HT(SITECOMEU, WL349V1), RSU_DEV_HT(SITECOMEU, WL353), RSU_DEV_HT(SWEEX2, LW154), - //RSU_DEV_HT(TRENDNET, TEW646UBH), #undef RSU_DEV_HT #undef RSU_DEV }; @@ -1155,9 +1153,16 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len) pktlen = sizeof(*wh) + le32toh(bss->ieslen); if (__predict_false(pktlen > MCLBYTES)) return; - m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR); + MGETHDR(m, M_NOWAIT, MT_DATA); if (__predict_false(m == NULL)) return; + if (pktlen > MHLEN) { + MCLGET(m, M_NOWAIT); + if (!(m->m_flags & M_EXT)) { + m_free(m); + return; + } + } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON; @@ -1353,11 +1358,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi) rxdw3 = le32toh(stat->rxdw3); if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return NULL; } if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return NULL; } @@ -1373,11 +1378,19 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi) DPRINTFN(5, "Rx frame len=%d rate=%d infosz=%d rssi=%d\n", pktlen, rate, infosz, *rssi); - m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR); + MGETHDR(m, M_NOWAIT, MT_DATA); if (__predict_false(m == NULL)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return NULL; } + if (pktlen > MHLEN) { + MCLGET(m, M_NOWAIT); + if (__predict_false(!(m->m_flags & M_EXT))) { + ifp->if_ierrors++; + m_freem(m); + return NULL; + } + } /* Finalize mbuf. */ m->m_pkthdr.rcvif = ifp; /* Hardware does Rx TCP checksum offload. */ @@ -1484,7 +1497,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi) if (__predict_false(len < sizeof(*stat))) { DPRINTF("xfer too short %d\n", len); - if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); + sc->sc_ifp->if_ierrors++; return (NULL); } /* Determine if it is a firmware C2H event or an 802.11 frame. */ @@ -1562,7 +1575,7 @@ tr_setup: } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } break; @@ -1597,7 +1610,7 @@ rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data) ieee80211_free_node(data->ni); data->ni = NULL; } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } @@ -1641,7 +1654,7 @@ tr_setup: rsu_txeof(xfer, data); STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); @@ -1802,11 +1815,11 @@ rsu_start_locked(struct ifnet *ifp) bf = rsu_getbuf(sc); if (bf == NULL) { - if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + ifp->if_iqdrops++; m_freem(m); ieee80211_free_node(ni); } else if (rsu_tx_start(sc, ni, m, bf) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); ieee80211_free_node(ni); } @@ -2312,10 +2325,10 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, RSU_UNLOCK(sc); return (ENOBUFS); } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (rsu_tx_start(sc, ni, m, bf) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); RSU_UNLOCK(sc); return (EIO); diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index a3dc562..e1e8f2e 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -82,7 +81,7 @@ __FBSDID("$FreeBSD$"); static int rum_debug = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum"); -SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RWTUN, &rum_debug, 0, +SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0, "Debug level"); #endif @@ -797,7 +796,7 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) rum_tx_free(data, 0); usbd_xfer_set_priv(xfer, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* FALLTHROUGH */ @@ -851,7 +850,7 @@ tr_setup: DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error)); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; data = usbd_xfer_get_priv(xfer); if (data != NULL) { rum_tx_free(data, error); @@ -897,7 +896,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { DPRINTF("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } @@ -914,14 +913,14 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) * filled RUM_TXRX_CSR2: */ DPRINTFN(5, "PHY or CRC error\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } usbd_copy_out(pc, RT2573_RX_DESC_SIZE, @@ -1321,7 +1320,7 @@ rum_start(struct ifnet *ifp) ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; if (rum_tx_data(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } } @@ -2205,7 +2204,7 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return EIO; } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (params == NULL) { /* @@ -2226,7 +2225,7 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; RUM_UNLOCK(sc); ieee80211_free_node(ni); return EIO; @@ -2281,7 +2280,7 @@ rum_ratectl_task(void *arg, int pending) (void) ieee80211_ratectl_rate(ni, NULL, 0); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */ + ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); RUM_UNLOCK(sc); diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index eeb46d3..c4b09a0 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -84,7 +83,7 @@ __FBSDID("$FreeBSD$"); #ifdef RUN_DEBUG int run_debug = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, run, CTLFLAG_RW, 0, "USB run"); -SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, CTLFLAG_RWTUN, &run_debug, 0, +SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, CTLFLAG_RW, &run_debug, 0, "run debug level"); #endif @@ -319,7 +318,6 @@ static const STRUCT_USB_HOST_ID run_devs[] = { RUN_DEV(ZINWELL, RT3072_2), RUN_DEV(ZYXEL, RT2870_1), RUN_DEV(ZYXEL, RT2870_2), - RUN_DEV(ZYXEL, RT3070), RUN_DEV_EJECT(ZYXEL, NWD2705), RUN_DEV_EJECT(RALINK, RT_STOR), #undef RUN_DEV_EJECT @@ -2576,7 +2574,7 @@ run_drain_fifo(void *arg) if (stat & RT2860_TXQ_OK) (*wstat)[RUN_SUCCESS]++; else - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; /* * Check if there were retries, ie if the Tx success rate is * different from the requested rate. Note that it works only @@ -2622,7 +2620,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni) goto fail; /* count failed TX as errors */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail)); + ifp->if_oerrors += le16toh(sta[0].error.fail); retrycnt = le16toh(sta[1].tx.retry); success = le16toh(sta[1].tx.success); @@ -2788,7 +2786,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) rxwisize += sizeof(uint32_t); if (__predict_false(len > dmalen)) { m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF("bad RXWI length %u > %u\n", len, dmalen); return; } @@ -2798,7 +2796,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV"); return; } @@ -2827,7 +2825,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) ieee80211_notify_michael_failure(ni->ni_vap, wh, rxwi->keyidx); m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF("MIC error. Someone is lying.\n"); return; } @@ -2927,7 +2925,7 @@ tr_setup: } if (sc->rx_m == NULL) { DPRINTF("could not allocate mbuf - idle with stall\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; usbd_xfer_set_stall(xfer); usbd_xfer_set_frames(xfer, 0); } else { @@ -2951,7 +2949,7 @@ tr_setup: if (error == USB_ERR_TIMEOUT) device_printf(sc->sc_dev, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } @@ -3000,7 +2998,7 @@ tr_setup: m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m0 == NULL)) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; break; } m_copydata(m, 4 /* skip 32-bit DMA-len header */, @@ -3072,7 +3070,7 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) usbd_xfer_set_priv(xfer, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; /* FALLTHROUGH */ case USB_ST_SETUP: @@ -3091,7 +3089,7 @@ tr_setup: DPRINTF("data overflow, %u bytes\n", m->m_pkthdr.len); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; run_tx_free(pq, data, 1); @@ -3146,7 +3144,7 @@ tr_setup: data = usbd_xfer_get_priv(xfer); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; if (data != NULL) { if(data->ni != NULL) @@ -3569,7 +3567,7 @@ run_sendprot(struct run_softc *sc, mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); } if (mprot == NULL) { - if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); + sc->sc_ifp->if_oerrors++; DPRINTF("could not allocate mbuf\n"); return (ENOBUFS); } @@ -3705,20 +3703,20 @@ run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (params == NULL) { /* tx mgt packet */ if ((error = run_tx_mgt(sc, m, ni)) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; DPRINTF("mgt tx failed\n"); goto done; } } else { /* tx raw packet with param */ if ((error = run_tx_param(sc, m, ni, params)) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; DPRINTF("tx with param failed\n"); goto done; } } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; done: RUN_UNLOCK(sc); diff --git a/sys/dev/usb/wlan/if_runreg.h b/sys/dev/usb/wlan/if_runreg.h index aa54a72..3ca01cd 100644 --- a/sys/dev/usb/wlan/if_runreg.h +++ b/sys/dev/usb/wlan/if_runreg.h @@ -962,6 +962,31 @@ struct rt2860_rxwi { #define RT2860_RIDX_MAX 12 /* + * Control and status registers access macros. + */ +#define RAL_READ(sc, reg) \ + bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) + +#define RAL_WRITE(sc, reg, val) \ + bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) + +#define RAL_BARRIER_WRITE(sc) \ + bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \ + BUS_SPACE_BARRIER_WRITE) + +#define RAL_BARRIER_READ_WRITE(sc) \ + bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \ + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) + +#define RAL_WRITE_REGION_1(sc, offset, datap, count) \ + bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset), \ + (datap), (count)) + +#define RAL_SET_REGION_4(sc, offset, val, count) \ + bus_space_set_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \ + (val), (count)) + +/* * EEPROM access macro. */ #define RT2860_EEPROM_CTL(sc, val) do { \ diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 0796fbe..6806c33 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -86,7 +86,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -115,16 +114,18 @@ __FBSDID("$FreeBSD$"); static SYSCTL_NODE(_hw_usb, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros"); static int uath_countrycode = CTRY_DEFAULT; /* country code */ -SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RWTUN, &uath_countrycode, +SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RW | CTLFLAG_TUN, &uath_countrycode, 0, "country code"); +TUNABLE_INT("hw.usb.uath.countrycode", &uath_countrycode); static int uath_regdomain = 0; /* regulatory domain */ SYSCTL_INT(_hw_usb_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain, 0, "regulatory domain"); #ifdef UATH_DEBUG int uath_debug = 0; -SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RWTUN, &uath_debug, 0, +SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &uath_debug, 0, "uath debug level"); +TUNABLE_INT("hw.usb.uath.debug", &uath_debug); enum { UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */ @@ -1333,7 +1334,7 @@ uath_watchdog(void *arg) if (--sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "device timeout\n"); /*uath_init(ifp); XXX needs a process context! */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); @@ -1814,7 +1815,7 @@ uath_start(struct ifnet *ifp) next = m->m_nextpkt; if (uath_tx_start(sc, m, ni, bf) != 0) { bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; reclaim: STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); @@ -1878,7 +1879,7 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, sc->sc_seqnum = 0; if (uath_tx_start(sc, m, ni, bf) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); UATH_UNLOCK(sc); @@ -2553,14 +2554,14 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, if (actlen < (int)UATH_MIN_RXBUFSZ) { DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: wrong xfer size (len=%d)\n", __func__, actlen); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } chunk = (struct uath_chunk *)data->buf; if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) { device_printf(sc->sc_dev, "%s: strange response\n", __func__); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; UATH_RESET_INTRX(sc); return (NULL); } @@ -2593,7 +2594,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) + chunklen) > UATH_MAX_INTRX_SIZE) { UATH_STAT_INC(sc, st_invalidlen); - if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + ifp->if_iqdrops++; if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); @@ -2618,7 +2619,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, if (mnew == NULL) { DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: can't get new mbuf, drop frame\n", __func__); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); @@ -2659,7 +2660,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: bad descriptor (len=%d)\n", __func__, be32toh(desc->len)); - if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + ifp->if_iqdrops++; UATH_STAT_INC(sc, st_toobigrxpkt); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); @@ -2703,7 +2704,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, tap->wr_antnoise = -95; } - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; UATH_RESET_INTRX(sc); return (m); @@ -2790,7 +2791,7 @@ setup: } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto setup; } break; @@ -2826,7 +2827,7 @@ uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data) data->ni = NULL; } sc->sc_tx_timer = 0; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } @@ -2878,7 +2879,7 @@ setup: if ((sc->sc_flags & UATH_FLAG_INVALID) == 0) ieee80211_free_node(data->ni); data->ni = NULL; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index dc6dc1b..1f60ebc 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -76,8 +75,9 @@ static SYSCTL_NODE(_hw, OID_AUTO, upgt, CTLFLAG_RD, 0, #ifdef UPGT_DEBUG int upgt_debug = 0; -SYSCTL_INT(_hw_upgt, OID_AUTO, debug, CTLFLAG_RWTUN, &upgt_debug, +SYSCTL_INT(_hw_upgt, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &upgt_debug, 0, "control debugging printfs"); +TUNABLE_INT("hw.upgt.debug", &upgt_debug); enum { UPGT_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ UPGT_DEBUG_RECV = 0x00000002, /* basic recv operation */ @@ -182,7 +182,7 @@ static const STRUCT_USB_HOST_ID upgt_devs[] = { UPGT_DEV(FSC, E5400), UPGT_DEV(GLOBESPAN, PRISM_GT_1), UPGT_DEV(GLOBESPAN, PRISM_GT_2), - //UPGT_DEV(NETGEAR, WG111V1_2), + UPGT_DEV(NETGEAR, WG111V2_2), UPGT_DEV(INTERSIL, PRISM_GT), UPGT_DEV(SMC, 2862WG), UPGT_DEV(USR, USR5422), @@ -416,7 +416,7 @@ upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data) ieee80211_free_node(data->ni); data->ni = NULL; } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } static void @@ -854,7 +854,7 @@ upgt_start(struct ifnet *ifp) STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next); UPGT_STAT_INC(sc, st_tx_inactive); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; continue; } sc->sc_tx_timer = 5; @@ -891,7 +891,7 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next); UPGT_STAT_INC(sc, st_tx_inactive); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; UPGT_UNLOCK(sc); return (EIO); } @@ -911,7 +911,7 @@ upgt_watchdog(void *arg) if (--sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "watchdog timeout\n"); /* upgt_init(ifp); XXX needs a process context ? */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); @@ -1552,7 +1552,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi) tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate); tap->wr_antsignal = rxdesc->rssi; } - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__); *rssi = rxdesc->rssi; @@ -2293,8 +2293,7 @@ done: * will stall. It's strange, but it works, so we keep reading * the statistics here. *shrug* */ - if (!(if_get_counter_default(ifp, IFCOUNTER_OPACKETS) % - UPGT_TX_STAT_INTERVAL)) + if (!(ifp->if_opackets % UPGT_TX_STAT_INTERVAL)) upgt_get_stats(sc); return (error); @@ -2367,7 +2366,7 @@ setup: } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto setup; } break; @@ -2419,7 +2418,7 @@ setup: if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index c81b708..69b41dd 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -83,7 +82,7 @@ __FBSDID("$FreeBSD$"); static int ural_debug = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural"); -SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RWTUN, &ural_debug, 0, +SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0, "Debug level"); #endif @@ -805,7 +804,7 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) ural_tx_free(data, 0); usbd_xfer_set_priv(xfer, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* FALLTHROUGH */ @@ -859,7 +858,7 @@ tr_setup: DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error)); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; data = usbd_xfer_get_priv(xfer); if (data != NULL) { ural_tx_free(data, error); @@ -900,7 +899,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { DPRINTF("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } @@ -919,14 +918,14 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) * filled RAL_TXRX_CSR2: */ DPRINTFN(5, "PHY or CRC error\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } usbd_copy_out(pc, 0, mtod(m, uint8_t *), len); @@ -1370,7 +1369,7 @@ ural_start(struct ifnet *ifp) ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; if (ural_tx_data(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } } @@ -2210,7 +2209,7 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return EIO; } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (params == NULL) { /* @@ -2230,7 +2229,7 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, RAL_UNLOCK(sc); return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; RAL_UNLOCK(sc); ieee80211_free_node(ni); return EIO; /* XXX */ @@ -2284,7 +2283,7 @@ ural_ratectl_task(void *arg, int pending) ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); (void) ieee80211_ratectl_rate(ni, NULL, 0); - if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */ + ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); RAL_UNLOCK(sc); diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index d2c6ef9..5612f19 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -65,8 +64,9 @@ __FBSDID("$FreeBSD$"); static SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L"); #ifdef URTW_DEBUG int urtw_debug = 0; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RWTUN, &urtw_debug, 0, +SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &urtw_debug, 0, "control debugging printfs"); +TUNABLE_INT("hw.usb.urtw.debug", &urtw_debug); enum { URTW_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ URTW_DEBUG_RECV = 0x00000002, /* basic recv operation */ @@ -89,8 +89,9 @@ enum { } while (0) #endif static int urtw_preamble_mode = URTW_PREAMBLE_MODE_LONG; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RWTUN, +SYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RW | CTLFLAG_TUN, &urtw_preamble_mode, 0, "set the preable mode (long or short)"); +TUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode); /* recognized device vendors/products */ #define urtw_lookup(v, p) \ @@ -1472,7 +1473,7 @@ urtw_start(struct ifnet *ifp) m->m_pkthdr.rcvif = NULL; if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); ieee80211_free_node(ni); break; @@ -1582,10 +1583,10 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return (ENOBUFS); /* XXX */ } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); URTW_UNLOCK(sc); return (EIO); @@ -1918,7 +1919,7 @@ urtw_watchdog(void *arg) if (sc->sc_txtimer > 0) { if (--sc->sc_txtimer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); @@ -3993,7 +3994,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); if (actlen < (int)URTW_MIN_RXBUFSZ) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } @@ -4004,7 +4005,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, (actlen - (sizeof(struct urtw_8187b_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; if (flen > actlen) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; @@ -4018,7 +4019,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, (actlen - (sizeof(struct urtw_8187l_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; if (flen > actlen) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } @@ -4030,7 +4031,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } @@ -4127,7 +4128,7 @@ setup: } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto setup; } break; @@ -4156,7 +4157,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer) pktretry = val & 0xff; seq = (val >> 16) & 0xff; if (pktretry == URTW_TX_MAXRETRY) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", pktretry, seq); } @@ -4184,7 +4185,7 @@ setup: default: if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto setup; } break; @@ -4218,7 +4219,7 @@ urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data) data->ni = NULL; } sc->sc_txtimer = 0; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } @@ -4265,7 +4266,7 @@ setup: if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/usb/wlan/if_urtwn.c index 28bf713..2475727 100644 --- a/sys/dev/usb/wlan/if_urtwn.c +++ b/sys/dev/usb/wlan/if_urtwn.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -78,7 +77,7 @@ __FBSDID("$FreeBSD$"); static int urtwn_debug = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, urtwn, CTLFLAG_RW, 0, "USB urtwn"); -SYSCTL_INT(_hw_usb_urtwn, OID_AUTO, debug, CTLFLAG_RWTUN, &urtwn_debug, 0, +SYSCTL_INT(_hw_usb_urtwn, OID_AUTO, debug, CTLFLAG_RW, &urtwn_debug, 0, "Debug level"); #endif @@ -153,9 +152,7 @@ static const STRUCT_USB_HOST_ID urtwn_devs[] = { URTWN_DEV(TRENDNET, RTL8192CU), URTWN_DEV(ZYXEL, RTL8192CU), /* URTWN_RTL8188E */ - //URTWN_RTL8188E_DEV(DLINK, DWA123D1), URTWN_RTL8188E_DEV(DLINK, DWA125D1), - //URTWN_RTL8188E_DEV(ELECOM, WDC150SU2M), URTWN_RTL8188E_DEV(REALTEK, RTL8188ETV), URTWN_RTL8188E_DEV(REALTEK, RTL8188EU), #undef URTWN_RTL8188E_DEV @@ -176,12 +173,12 @@ static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void urtwn_vap_delete(struct ieee80211vap *); -static struct mbuf * urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int, +static struct mbuf * urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int, int *); -static struct mbuf * urtwn_rxeof(struct usb_xfer *, struct urtwn_data *, +static struct mbuf * urtwn_rxeof(struct usb_xfer *, struct urtwn_data *, int *, int8_t *); static void urtwn_txeof(struct usb_xfer *, struct urtwn_data *); -static int urtwn_alloc_list(struct urtwn_softc *, +static int urtwn_alloc_list(struct urtwn_softc *, struct urtwn_data[], int, int); static int urtwn_alloc_rx_list(struct urtwn_softc *); static int urtwn_alloc_tx_list(struct urtwn_softc *); @@ -191,24 +188,24 @@ static void urtwn_free_list(struct urtwn_softc *, struct urtwn_data data[], int); static struct urtwn_data * _urtwn_getbuf(struct urtwn_softc *); static struct urtwn_data * urtwn_getbuf(struct urtwn_softc *); -static int urtwn_write_region_1(struct urtwn_softc *, uint16_t, +static int urtwn_write_region_1(struct urtwn_softc *, uint16_t, uint8_t *, int); static void urtwn_write_1(struct urtwn_softc *, uint16_t, uint8_t); static void urtwn_write_2(struct urtwn_softc *, uint16_t, uint16_t); static void urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t); -static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, +static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *, int); static uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t); static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t); static uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t); -static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, +static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int); static void urtwn_r92c_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t); -static void urtwn_r88e_rf_write(struct urtwn_softc *, int, +static void urtwn_r88e_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t); static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t); -static int urtwn_llt_write(struct urtwn_softc *, uint32_t, +static int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t); static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t); static void urtwn_efuse_read(struct urtwn_softc *); @@ -219,7 +216,7 @@ static void urtwn_r88e_read_rom(struct urtwn_softc *); static int urtwn_ra_init(struct urtwn_softc *); static void urtwn_tsf_sync_enable(struct urtwn_softc *); static void urtwn_set_led(struct urtwn_softc *, int, int); -static int urtwn_newstate(struct ieee80211vap *, +static int urtwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void urtwn_watchdog(void *); static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t); @@ -237,7 +234,7 @@ static int urtwn_r88e_power_on(struct urtwn_softc *); static int urtwn_llt_init(struct urtwn_softc *); static void urtwn_fw_reset(struct urtwn_softc *); static void urtwn_r88e_fw_reset(struct urtwn_softc *); -static int urtwn_fw_loadpage(struct urtwn_softc *, int, +static int urtwn_fw_loadpage(struct urtwn_softc *, int, const uint8_t *, int); static int urtwn_load_firmware(struct urtwn_softc *); static int urtwn_r92c_dma_init(struct urtwn_softc *); @@ -249,22 +246,22 @@ static void urtwn_cam_init(struct urtwn_softc *); static void urtwn_pa_bias_init(struct urtwn_softc *); static void urtwn_rxfilter_init(struct urtwn_softc *); static void urtwn_edca_init(struct urtwn_softc *); -static void urtwn_write_txpower(struct urtwn_softc *, int, +static void urtwn_write_txpower(struct urtwn_softc *, int, uint16_t[]); static void urtwn_get_txpower(struct urtwn_softc *, int, - struct ieee80211_channel *, + struct ieee80211_channel *, struct ieee80211_channel *, uint16_t[]); static void urtwn_r88e_get_txpower(struct urtwn_softc *, int, - struct ieee80211_channel *, + struct ieee80211_channel *, struct ieee80211_channel *, uint16_t[]); static void urtwn_set_txpower(struct urtwn_softc *, - struct ieee80211_channel *, + struct ieee80211_channel *, struct ieee80211_channel *); static void urtwn_scan_start(struct ieee80211com *); static void urtwn_scan_end(struct ieee80211com *); static void urtwn_set_channel(struct ieee80211com *); static void urtwn_set_chan(struct urtwn_softc *, - struct ieee80211_channel *, + struct ieee80211_channel *, struct ieee80211_channel *); static void urtwn_update_mcast(struct ifnet *); static void urtwn_iq_calib(struct urtwn_softc *); @@ -470,7 +467,7 @@ urtwn_attach(device_t self) ic->ic_vap_delete = urtwn_vap_delete; ic->ic_update_mcast = urtwn_update_mcast; - ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, + ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT, &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), URTWN_RX_RADIOTAP_PRESENT); @@ -492,7 +489,7 @@ urtwn_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; unsigned int x; - + /* Prevent further ioctls. */ URTWN_LOCK(sc); sc->sc_flags |= URTWN_DETACHED; @@ -604,7 +601,7 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, vap = &uvp->vap; /* enable s/w bmiss handling for sta mode */ - if (ieee80211_vap_setup(ic, vap, name, unit, opmode, + if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) { /* out of memory */ free(uvp, M_80211_VAP); @@ -660,11 +657,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p) * This should not happen since we setup our Rx filter * to not receive these frames. */ - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - return (NULL); - } - if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } @@ -673,7 +666,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p) /* Get RSSI from PHY status descriptor if present. */ if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { - if (sc->chip & URTWN_CHIP_88E) + if (sc->chip & URTWN_CHIP_88E) rssi = urtwn_r88e_get_rssi(sc, rate, &stat[1]); else rssi = urtwn_get_rssi(sc, rate, &stat[1]); @@ -749,7 +742,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi, usbd_xfer_status(xfer, &len, NULL, NULL, NULL); if (len < sizeof(*stat)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return (NULL); } @@ -864,7 +857,7 @@ tr_setup: } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; goto tr_setup; } break; @@ -898,7 +891,7 @@ urtwn_txeof(struct usb_xfer *xfer, struct urtwn_data *data) data->ni = NULL; } sc->sc_txtimer = 0; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } @@ -940,7 +933,7 @@ tr_setup: if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); @@ -1184,7 +1177,7 @@ urtwn_efuse_read_1(struct urtwn_softc *sc, uint16_t addr) return (MS(reg, R92C_EFUSE_CTRL_DATA)); urtwn_ms_delay(sc); } - device_printf(sc->sc_dev, + device_printf(sc->sc_dev, "could not read efuse byte at address 0x%x\n", addr); return (0xff); } @@ -1195,7 +1188,7 @@ urtwn_efuse_read(struct urtwn_softc *sc) uint8_t *rom = (uint8_t *)&sc->rom; uint16_t addr = 0; uint32_t reg; - uint8_t off, msk; + uint8_t off, msk, vol; int i; urtwn_efuse_switch_power(sc); @@ -1228,15 +1221,18 @@ urtwn_efuse_read(struct urtwn_softc *sc) printf("\n"); } #endif - urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF); -} + /* Disable LDO 2.5V. */ + vol = urtwn_read_1(sc, R92C_EFUSE_TEST + 3); + urtwn_write_1(sc, R92C_EFUSE_TEST + 3, vol & ~(0x80)); +} static void urtwn_efuse_switch_power(struct urtwn_softc *sc) { uint32_t reg; - urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON); + if (sc->chip & URTWN_CHIP_88E) + urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON); reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL); if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { @@ -1254,6 +1250,16 @@ urtwn_efuse_switch_power(struct urtwn_softc *sc) urtwn_write_2(sc, R92C_SYS_CLKR, reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); } + + if (!(sc->chip & URTWN_CHIP_88E)) { + uint8_t vol; + + /* Enable LDO 2.5V. */ + vol = urtwn_read_1(sc, R92C_EFUSE_TEST + 3); + vol &= 0x0f; + vol |= 0x30; + urtwn_write_1(sc, R92C_EFUSE_TEST + 3, (vol | 0x80)); + } } static int @@ -1483,7 +1489,7 @@ static void urtwn_set_led(struct urtwn_softc *sc, int led, int on) { uint8_t reg; - + if (led == URTWN_LED_LINK) { if (sc->chip & URTWN_CHIP_88E) { reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; @@ -1644,7 +1650,7 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (sc->chip & URTWN_CHIP_88E) ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1]; - else + else urtwn_ra_init(sc); /* Turn link LED on. */ urtwn_set_led(sc, URTWN_LED_LINK, 1); @@ -1672,7 +1678,7 @@ urtwn_watchdog(void *arg) if (sc->sc_txtimer > 0) { if (--sc->sc_txtimer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc); @@ -1755,7 +1761,7 @@ urtwn_r88e_get_rssi(struct urtwn_softc *sc, int rate, void *physt) cck = (struct r88e_rx_cck *)physt; cck_agc_rpt = cck->agc_rpt; lna_idx = (cck_agc_rpt & 0xe0) >> 5; - vga_idx = cck_agc_rpt & 0x1f; + vga_idx = cck_agc_rpt & 0x1f; switch (lna_idx) { case 7: if (vga_idx <= 27) @@ -1795,7 +1801,7 @@ urtwn_r88e_get_rssi(struct urtwn_softc *sc, int rate, void *physt) static int -urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, +urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, struct urtwn_data *data) { struct ifnet *ifp = sc->sc_ifp; @@ -1836,7 +1842,7 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, /* in case packet header moved, reset pointer */ wh = mtod(m0, struct ieee80211_frame *); } - + switch (type) { case IEEE80211_FC0_TYPE_CTL: case IEEE80211_FC0_TYPE_MGT: @@ -1848,7 +1854,7 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, xfer = urtwn_pipes[M_WME_GETAC(m0)]; break; } - + hasqos = 0; /* Fill Tx descriptor. */ @@ -1892,7 +1898,10 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, 8)); txd->txdw5 |= htole32(0x0001ff00); /* Send data at OFDM54. */ - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11)); + if (sc->chip & URTWN_CHIP_88E) + txd->txdw5 |= htole32(0x13 & 0x3f); + else + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11)); } else { txd->txdw1 |= htole32( SM(R92C_TXDW1_MACID, 0) | @@ -1973,7 +1982,7 @@ urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc) m->m_pkthdr.rcvif = NULL; if (urtwn_tx_start(sc, ni, m, bf) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); ieee80211_free_node(ni); break; @@ -2323,7 +2332,7 @@ urtwn_fw_loadpage(struct urtwn_softc *sc, int page, const uint8_t *buf, int len) else mlen = 1; /* XXX fix this deconst */ - error = urtwn_write_region_1(sc, off, + error = urtwn_write_region_1(sc, off, __DECONST(uint8_t *, buf), mlen); if (error != 0) break; @@ -2458,7 +2467,7 @@ fail: static __inline int urtwn_dma_init(struct urtwn_softc *sc) { - + return sc->sc_dma_init(sc); } @@ -3226,10 +3235,10 @@ urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | R92C_FPGA0_ANAPARAM2_CBW20); } - + /* Select 20MHz bandwidth. */ urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | chan | + (sc->rf_chnlbw[0] & ~0xfff) | chan | ((sc->chip & URTWN_CHIP_88E) ? R88E_RF_CHNLBW_BW20 : R92C_RF_CHNLBW_BW20)); } @@ -3304,7 +3313,7 @@ urtwn_init_locked(void *arg) error = urtwn_alloc_rx_list(sc); if (error != 0) goto fail; - + error = urtwn_alloc_tx_list(sc); if (error != 0) goto fail; @@ -3348,7 +3357,6 @@ urtwn_init_locked(void *arg) urtwn_rxfilter_init(sc); - /* Set response rate. */ reg = urtwn_read_4(sc, R92C_RRSR); reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_CCK_ONLY_1M); urtwn_write_4(sc, R92C_RRSR, reg); @@ -3540,10 +3548,10 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return (ENOBUFS); } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if (urtwn_tx_start(sc, ni, m, bf) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); URTWN_UNLOCK(sc); return (EIO); diff --git a/sys/dev/usb/wlan/if_urtwnreg.h b/sys/dev/usb/wlan/if_urtwnreg.h index 2bbec7a..4eef029 100644 --- a/sys/dev/usb/wlan/if_urtwnreg.h +++ b/sys/dev/usb/wlan/if_urtwnreg.h @@ -177,13 +177,13 @@ #define R92C_RD_NAV_NXT 0x544 #define R92C_NAV_PROT_LEN 0x546 #define R92C_BCN_CTRL 0x550 +#define R92C_USTIME_TSF 0x551 #define R92C_MBID_NUM 0x552 #define R92C_DUAL_TSF_RST 0x553 #define R92C_BCN_INTERVAL 0x554 #define R92C_DRVERLYINT 0x558 #define R92C_BCNDMATIM 0x559 #define R92C_ATIMWND 0x55a -#define R92C_USTIME_TSF 0x55c #define R92C_BCN_MAX_ERR 0x55d #define R92C_RXTSF_OFFSET_CCK 0x55e #define R92C_RXTSF_OFFSET_OFDM 0x55f diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index ca1fb06..35a064b 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -80,7 +79,7 @@ __FBSDID("$FreeBSD$"); static int zyd_debug = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, zyd, CTLFLAG_RW, 0, "USB zyd"); -SYSCTL_INT(_hw_usb_zyd, OID_AUTO, debug, CTLFLAG_RWTUN, &zyd_debug, 0, +SYSCTL_INT(_hw_usb_zyd, OID_AUTO, debug, CTLFLAG_RW, &zyd_debug, 0, "zyd debug level"); enum { @@ -679,7 +678,7 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) ieee80211_free_node(ni); } if (le16toh(retry->count) & 0x100) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */ + ifp->if_oerrors++; /* too many retries */ break; } case ZYD_NOTIF_IORD: @@ -2188,7 +2187,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) if (len < ZYD_MIN_FRAGSZ) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } pc = usbd_xfer_get_frame(xfer, 0); @@ -2199,7 +2198,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) DPRINTF(sc, ZYD_DEBUG_RECV, "%s: RX status indicated error (%x)\n", device_get_nameunit(sc->sc_dev), stat.flags); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } @@ -2211,7 +2210,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) if (rlen > (int)MCLBYTES) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n", device_get_nameunit(sc->sc_dev), rlen); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } else if (rlen > (int)MHLEN) m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); @@ -2220,7 +2219,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) if (m == NULL) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", device_get_nameunit(sc->sc_dev)); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; return; } m->m_pkthdr.rcvif = ifp; @@ -2403,7 +2402,7 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) zyd_tx_free(data, 0); usbd_xfer_set_priv(xfer, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* FALLTHROUGH */ @@ -2447,7 +2446,7 @@ tr_setup: DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", usbd_errstr(error)); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; data = usbd_xfer_get_priv(xfer); usbd_xfer_set_priv(xfer, NULL); if (data != NULL) @@ -2608,7 +2607,7 @@ zyd_start(struct ifnet *ifp) ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (zyd_tx_start(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; break; } } @@ -2646,7 +2645,7 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, */ if (zyd_tx_start(sc, m, ni) != 0) { ZYD_UNLOCK(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_free_node(ni); return (EIO); } diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 6d58c5c..5442d3d 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -87,7 +87,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -132,7 +131,6 @@ static int wi_reset(struct wi_softc *); static void wi_watchdog(void *); static int wi_ioctl(struct ifnet *, u_long, caddr_t); static void wi_media_status(struct ifnet *, struct ifmediareq *); -static uint64_t wi_get_counter(struct ifnet *, ift_counter); static void wi_rx_intr(struct wi_softc *); static void wi_tx_intr(struct wi_softc *); @@ -338,7 +336,6 @@ wi_attach(device_t dev) ifp->if_ioctl = wi_ioctl; ifp->if_start = wi_start; ifp->if_init = wi_init; - //ifp->if_get_counter = wi_get_counter; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); @@ -1030,7 +1027,7 @@ wi_start_locked(struct ifnet *ifp) continue; sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } } @@ -1057,7 +1054,7 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0) || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0; m_freem(m0); if (error) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return -1; } sc->sc_txd[cur].d_len = off; @@ -1184,7 +1181,7 @@ wi_watchdog(void *arg) if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) { if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; wi_init_locked(ifp->if_softc); return; } @@ -1329,7 +1326,7 @@ wi_rx_intr(struct wi_softc *sc) /* First read in the frame header */ if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF(("wi_rx_intr: read fid %x failed\n", fid)); return; } @@ -1340,7 +1337,7 @@ wi_rx_intr(struct wi_softc *sc) status = le16toh(frmhdr.wi_status); if (status & WI_STAT_ERRSTAT) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status)); return; } @@ -1355,7 +1352,7 @@ wi_rx_intr(struct wi_softc *sc) if (off + len > MCLBYTES) { if (ic->ic_opmode != IEEE80211_M_MONITOR) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF(("wi_rx_intr: oversized packet\n")); return; } else @@ -1368,7 +1365,7 @@ wi_rx_intr(struct wi_softc *sc) m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; DPRINTF(("wi_rx_intr: MGET failed\n")); return; } @@ -1452,13 +1449,13 @@ wi_tx_ex_intr(struct wi_softc *sc) printf(", status=0x%x", status); printf("\n"); } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } else + ifp->if_oerrors++; + } else { DPRINTF(("port disconnected\n")); - } else { + ifp->if_collisions++; /* XXX */ + } + } else DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid)); - ifp->if_collisions++; /* XXX */ - } CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); } @@ -1499,7 +1496,8 @@ wi_tx_intr(struct wi_softc *sc) static __noinline void wi_info_intr(struct wi_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); int i, fid, len, off; u_int16_t ltbuf[2]; @@ -1563,9 +1561,9 @@ wi_info_intr(struct wi_softc *sc) #endif *ptr += stat; } - sc->sc_ifp->if_collisions = sc->sc_stats.wi_tx_single_retries + - sc->sc_stats.wi_tx_multi_retries + - sc->sc_stats.wi_tx_retry_limit; + ifp->if_collisions = sc->sc_stats.wi_tx_single_retries + + sc->sc_stats.wi_tx_multi_retries + + sc->sc_stats.wi_tx_retry_limit; break; default: DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid, @@ -1576,27 +1574,6 @@ finish: CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); } -static uint64_t -wi_get_counter(struct ifnet *ifp, ift_counter cnt) -{ -#if 0 - struct wi_softc *sc; - - sc = if_getsoftc(ifp); - - switch (cnt) { - case IFCOUNTER_COLLISIONS: - return (sc->sc_stats.wi_tx_single_retries + - sc->sc_stats.wi_tx_multi_retries + - sc->sc_stats.wi_tx_retry_limit); - default: - return (if_get_counter_default(ifp, cnt)); - } -#else - return 0; -#endif -} - static int wi_write_multi(struct wi_softc *sc) { diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c index fd70e77..382a3a3 100644 --- a/sys/dev/wi/if_wi_pccard.c +++ b/sys/dev/wi/if_wi_pccard.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -63,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include #include +#define PCCARD_API_LEVEL 6 #include #include diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c index 198c599..30cdbc4 100644 --- a/sys/dev/wi/if_wi_pci.c +++ b/sys/dev/wi/if_wi_pci.c @@ -55,7 +55,6 @@ #include #include -#include #include #include #include diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index 7b438c7..6b3929e 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define VERSION "20071127" + #include __FBSDID("$FreeBSD$"); @@ -42,7 +44,7 @@ __FBSDID("$FreeBSD$"); * * A similar thing happens with the tx rings. The difference is the firmware * stop processing buffers once the queue is full and until confirmation - * of a successful transmition (tx_done) has occurred. + * of a successful transmition (tx_intr) has occurred. * * The command ring operates in the same manner as the tx queues. * @@ -58,7 +60,6 @@ __FBSDID("$FreeBSD$"); */ #include "opt_wlan.h" -#include "opt_wpi.h" #include #include @@ -85,27 +86,58 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include #include #include -#include -#include -#include -#include -#include - #include #include #include #include +#include +#include +#include +#include +#include + #include #include -#include + +#define WPI_DEBUG + +#ifdef WPI_DEBUG +#define DPRINTF(x) do { if (wpi_debug != 0) printf x; } while (0) +#define DPRINTFN(n, x) do { if (wpi_debug & n) printf x; } while (0) +#define WPI_DEBUG_SET (wpi_debug != 0) + +enum { + WPI_DEBUG_UNUSED = 0x00000001, /* Unused */ + WPI_DEBUG_HW = 0x00000002, /* Stage 1 (eeprom) debugging */ + WPI_DEBUG_TX = 0x00000004, /* Stage 2 TX intrp debugging*/ + WPI_DEBUG_RX = 0x00000008, /* Stage 2 RX intrp debugging */ + WPI_DEBUG_CMD = 0x00000010, /* Stage 2 CMD intrp debugging*/ + WPI_DEBUG_FIRMWARE = 0x00000020, /* firmware(9) loading debug */ + WPI_DEBUG_DMA = 0x00000040, /* DMA (de)allocations/syncs */ + WPI_DEBUG_SCANNING = 0x00000080, /* Stage 2 Scanning debugging */ + WPI_DEBUG_NOTIFY = 0x00000100, /* State 2 Noftif intr debug */ + WPI_DEBUG_TEMP = 0x00000200, /* TXPower/Temp Calibration */ + WPI_DEBUG_OPS = 0x00000400, /* wpi_ops taskq debug */ + WPI_DEBUG_WATCHDOG = 0x00000800, /* Watch dog debug */ + WPI_DEBUG_ANY = 0xffffffff +}; + +static int wpi_debug = 0; +SYSCTL_INT(_debug, OID_AUTO, wpi, CTLFLAG_RW, &wpi_debug, 0, "wpi debug level"); +TUNABLE_INT("debug.wpi", &wpi_debug); + +#else +#define DPRINTF(x) +#define DPRINTFN(n, x) +#define WPI_DEBUG_SET 0 +#endif struct wpi_ident { uint16_t vendor; @@ -126,160 +158,99 @@ static const struct wpi_ident wpi_ident_table[] = { { 0, 0, 0, NULL } }; -static int wpi_probe(device_t); -static int wpi_attach(device_t); -static void wpi_radiotap_attach(struct wpi_softc *); -static void wpi_sysctlattach(struct wpi_softc *); -static void wpi_init_beacon(struct wpi_vap *); static struct ieee80211vap *wpi_vap_create(struct ieee80211com *, const char [IFNAMSIZ], int, enum ieee80211_opmode, int, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void wpi_vap_delete(struct ieee80211vap *); -static int wpi_detach(device_t); -static int wpi_shutdown(device_t); -static int wpi_suspend(device_t); -static int wpi_resume(device_t); -static int wpi_nic_lock(struct wpi_softc *); -static int wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int); -static void wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int); static int wpi_dma_contig_alloc(struct wpi_softc *, struct wpi_dma_info *, - void **, bus_size_t, bus_size_t); + void **, bus_size_t, bus_size_t, int); static void wpi_dma_contig_free(struct wpi_dma_info *); +static void wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int); static int wpi_alloc_shared(struct wpi_softc *); static void wpi_free_shared(struct wpi_softc *); -static int wpi_alloc_fwmem(struct wpi_softc *); -static void wpi_free_fwmem(struct wpi_softc *); -static int wpi_alloc_rx_ring(struct wpi_softc *); -static void wpi_update_rx_ring(struct wpi_softc *); -static void wpi_update_rx_ring_ps(struct wpi_softc *); -static void wpi_reset_rx_ring(struct wpi_softc *); -static void wpi_free_rx_ring(struct wpi_softc *); +static int wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *); +static void wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *); +static void wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *); static int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *, - int); -static void wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); -static void wpi_update_tx_ring_ps(struct wpi_softc *, - struct wpi_tx_ring *); + int, int); static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); -static int wpi_read_eeprom(struct wpi_softc *, - uint8_t macaddr[IEEE80211_ADDR_LEN]); -static uint32_t wpi_eeprom_channel_flags(struct wpi_eeprom_chan *); -static void wpi_read_eeprom_band(struct wpi_softc *, int); -static int wpi_read_eeprom_channels(struct wpi_softc *, int); -static struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *, - struct ieee80211_channel *); -static int wpi_setregdomain(struct ieee80211com *, - struct ieee80211_regdomain *, int, - struct ieee80211_channel[]); -static int wpi_read_eeprom_group(struct wpi_softc *, int); -static int wpi_add_node_entry_adhoc(struct wpi_softc *); -static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void wpi_node_free(struct ieee80211_node *); -static void wpi_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, int, - int); -static void wpi_restore_node(void *, struct ieee80211_node *); -static void wpi_restore_node_table(struct wpi_softc *, struct wpi_vap *); static int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static void wpi_calib_timeout(void *); -static void wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *, - struct wpi_rx_data *); -static void wpi_rx_statistics(struct wpi_softc *, struct wpi_rx_desc *, +static void wpi_mem_lock(struct wpi_softc *); +static void wpi_mem_unlock(struct wpi_softc *); +static uint32_t wpi_mem_read(struct wpi_softc *, uint16_t); +static void wpi_mem_write(struct wpi_softc *, uint16_t, uint32_t); +static void wpi_mem_write_region_4(struct wpi_softc *, uint16_t, + const uint32_t *, int); +static uint16_t wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int); +static int wpi_alloc_fwmem(struct wpi_softc *); +static void wpi_free_fwmem(struct wpi_softc *); +static int wpi_load_firmware(struct wpi_softc *); +static void wpi_unload_firmware(struct wpi_softc *); +static int wpi_load_microcode(struct wpi_softc *, const uint8_t *, int); +static void wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *, struct wpi_rx_data *); -static void wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *); -static void wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *); +static void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *); +static void wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *); static void wpi_notif_intr(struct wpi_softc *); -static void wpi_wakeup_intr(struct wpi_softc *); -#ifdef WPI_DEBUG -static void wpi_debug_registers(struct wpi_softc *); -#endif -static void wpi_fatal_intr(struct wpi_softc *); static void wpi_intr(void *); -static int wpi_cmd2(struct wpi_softc *, struct wpi_buf *); +static uint8_t wpi_plcp_signal(int); +static void wpi_watchdog(void *); static int wpi_tx_data(struct wpi_softc *, struct mbuf *, - struct ieee80211_node *); -static int wpi_tx_data_raw(struct wpi_softc *, struct mbuf *, - struct ieee80211_node *, - const struct ieee80211_bpf_params *); + struct ieee80211_node *, int); +static void wpi_start(struct ifnet *); +static void wpi_start_locked(struct ifnet *); static int wpi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void wpi_start(struct ifnet *); -static void wpi_start_task(void *, int); -static void wpi_watchdog_rfkill(void *); -static void wpi_scan_timeout(void *); -static void wpi_tx_timeout(void *); +static void wpi_scan_start(struct ieee80211com *); +static void wpi_scan_end(struct ieee80211com *); +static void wpi_set_channel(struct ieee80211com *); +static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long); +static void wpi_scan_mindwell(struct ieee80211_scan_state *); static int wpi_ioctl(struct ifnet *, u_long, caddr_t); -static int wpi_cmd(struct wpi_softc *, int, const void *, size_t, int); +static void wpi_read_eeprom(struct wpi_softc *, + uint8_t macaddr[IEEE80211_ADDR_LEN]); +static void wpi_read_eeprom_channels(struct wpi_softc *, int); +static void wpi_read_eeprom_group(struct wpi_softc *, int); +static int wpi_cmd(struct wpi_softc *, int, const void *, int, int); +static int wpi_wme_update(struct ieee80211com *); static int wpi_mrr_setup(struct wpi_softc *); -static int wpi_add_node(struct wpi_softc *, struct ieee80211_node *); -static int wpi_add_broadcast_node(struct wpi_softc *, int); -static int wpi_add_ibss_node(struct wpi_softc *, struct ieee80211_node *); -static void wpi_del_node(struct wpi_softc *, struct ieee80211_node *); -static int wpi_updateedca(struct ieee80211com *); -static void wpi_set_promisc(struct wpi_softc *); -static void wpi_update_promisc(struct ifnet *); -static void wpi_update_mcast(struct ifnet *); static void wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t); -static int wpi_set_timing(struct wpi_softc *, struct ieee80211_node *); -static void wpi_power_calibration(struct wpi_softc *); -static int wpi_set_txpower(struct wpi_softc *, int); -static int wpi_get_power_index(struct wpi_softc *, - struct wpi_power_group *, uint8_t, int, int); -static int wpi_set_pslevel(struct wpi_softc *, uint8_t, int, int); -static int wpi_send_btcoex(struct wpi_softc *); -static int wpi_send_rxon(struct wpi_softc *, int, int); -static int wpi_config(struct wpi_softc *); -static uint16_t wpi_get_active_dwell_time(struct wpi_softc *, - struct ieee80211_channel *, uint8_t); -static uint16_t wpi_limit_dwell(struct wpi_softc *, uint16_t); -static uint16_t wpi_get_passive_dwell_time(struct wpi_softc *, - struct ieee80211_channel *); -static uint32_t wpi_get_scan_pause_time(uint32_t, uint16_t); -static int wpi_scan(struct wpi_softc *, struct ieee80211_channel *); -static int wpi_auth(struct wpi_softc *, struct ieee80211vap *); -static int wpi_config_beacon(struct wpi_vap *); +static void wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *); +#if 0 static int wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *); -static void wpi_update_beacon(struct ieee80211vap *, int); -static void wpi_newassoc(struct ieee80211_node *, int); +#endif +static int wpi_auth(struct wpi_softc *, struct ieee80211vap *); static int wpi_run(struct wpi_softc *, struct ieee80211vap *); -static int wpi_load_key(struct ieee80211_node *, - const struct ieee80211_key *); -static void wpi_load_key_cb(void *, struct ieee80211_node *); -static int wpi_set_global_keys(struct ieee80211_node *); -static int wpi_del_key(struct ieee80211_node *, - const struct ieee80211_key *); -static void wpi_del_key_cb(void *, struct ieee80211_node *); -static int wpi_process_key(struct ieee80211vap *, - const struct ieee80211_key *, int); -static int wpi_key_set(struct ieee80211vap *, - const struct ieee80211_key *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static int wpi_key_delete(struct ieee80211vap *, - const struct ieee80211_key *); -static int wpi_post_alive(struct wpi_softc *); -static int wpi_load_bootcode(struct wpi_softc *, const uint8_t *, int); -static int wpi_load_firmware(struct wpi_softc *); -static int wpi_read_firmware(struct wpi_softc *); -static void wpi_unload_firmware(struct wpi_softc *); -static int wpi_clock_wait(struct wpi_softc *); -static int wpi_apm_init(struct wpi_softc *); -static void wpi_apm_stop_master(struct wpi_softc *); -static void wpi_apm_stop(struct wpi_softc *); -static void wpi_nic_config(struct wpi_softc *); -static int wpi_hw_init(struct wpi_softc *); -static void wpi_hw_stop(struct wpi_softc *); -static void wpi_radio_on(void *, int); -static void wpi_radio_off(void *, int); +static int wpi_scan(struct wpi_softc *); +static int wpi_config(struct wpi_softc *); +static void wpi_stop_master(struct wpi_softc *); +static int wpi_power_up(struct wpi_softc *); +static int wpi_reset(struct wpi_softc *); +static void wpi_hwreset(void *, int); +static void wpi_rfreset(void *, int); +static void wpi_hw_config(struct wpi_softc *); static void wpi_init(void *); -static void wpi_stop_locked(struct wpi_softc *); +static void wpi_init_locked(struct wpi_softc *, int); static void wpi_stop(struct wpi_softc *); -static void wpi_scan_start(struct ieee80211com *); -static void wpi_scan_end(struct ieee80211com *); -static void wpi_set_channel(struct ieee80211com *); -static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long); -static void wpi_scan_mindwell(struct ieee80211_scan_state *); -static void wpi_hw_reset(void *, int); +static void wpi_stop_locked(struct wpi_softc *); + +static int wpi_set_txpower(struct wpi_softc *, struct ieee80211_channel *, + int); +static void wpi_calib_timeout(void *); +static void wpi_power_calibration(struct wpi_softc *, int); +static int wpi_get_power_index(struct wpi_softc *, + struct wpi_power_group *, struct ieee80211_channel *, int); +#ifdef WPI_DEBUG +static const char *wpi_cmd_str(int); +#endif +static int wpi_probe(device_t); +static int wpi_attach(device_t); +static int wpi_detach(device_t); +static int wpi_shutdown(device_t); +static int wpi_suspend(device_t); +static int wpi_resume(device_t); static device_method_t wpi_methods[] = { /* Device interface */ @@ -298,15 +269,25 @@ static driver_t wpi_driver = { wpi_methods, sizeof (struct wpi_softc) }; + static devclass_t wpi_devclass; DRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, NULL, NULL); MODULE_VERSION(wpi, 1); -MODULE_DEPEND(wpi, pci, 1, 1, 1); -MODULE_DEPEND(wpi, wlan, 1, 1, 1); -MODULE_DEPEND(wpi, firmware, 1, 1, 1); +static const uint8_t wpi_ridx_to_plcp[] = { + /* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */ + /* R1-R4 (ral/ural is R4-R1) */ + 0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, + /* CCK: device-dependent */ + 10, 20, 55, 110 +}; + +static const uint8_t wpi_ridx_to_rate[] = { + 12, 18, 24, 36, 48, 72, 96, 108, /* OFDM */ + 2, 4, 11, 22 /*CCK */ +}; static int wpi_probe(device_t dev) @@ -323,48 +304,208 @@ wpi_probe(device_t dev) return ENXIO; } +/** + * Load the firmare image from disk to the allocated dma buffer. + * we also maintain the reference to the firmware pointer as there + * is times where we may need to reload the firmware but we are not + * in a context that can access the filesystem (ie taskq cause by restart) + * + * @return 0 on success, an errno on failure + */ +static int +wpi_load_firmware(struct wpi_softc *sc) +{ + const struct firmware *fp; + struct wpi_dma_info *dma = &sc->fw_dma; + const struct wpi_firmware_hdr *hdr; + const uint8_t *itext, *idata, *rtext, *rdata, *btext; + uint32_t itextsz, idatasz, rtextsz, rdatasz, btextsz; + int error; + + DPRINTFN(WPI_DEBUG_FIRMWARE, + ("Attempting Loading Firmware from wpi_fw module\n")); + + WPI_UNLOCK(sc); + + if (sc->fw_fp == NULL && (sc->fw_fp = firmware_get("wpifw")) == NULL) { + device_printf(sc->sc_dev, + "could not load firmware image 'wpifw'\n"); + error = ENOENT; + WPI_LOCK(sc); + goto fail; + } + + fp = sc->fw_fp; + + WPI_LOCK(sc); + + /* Validate the firmware is minimum a particular version */ + if (fp->version < WPI_FW_MINVERSION) { + device_printf(sc->sc_dev, + "firmware version is too old. Need %d, got %d\n", + WPI_FW_MINVERSION, + fp->version); + error = ENXIO; + goto fail; + } + + if (fp->datasize < sizeof (struct wpi_firmware_hdr)) { + device_printf(sc->sc_dev, + "firmware file too short: %zu bytes\n", fp->datasize); + error = ENXIO; + goto fail; + } + + hdr = (const struct wpi_firmware_hdr *)fp->data; + + /* | RUNTIME FIRMWARE | INIT FIRMWARE | BOOT FW | + |HDR|<--TEXT-->|<--DATA-->|<--TEXT-->|<--DATA-->|<--TEXT-->| */ + + rtextsz = le32toh(hdr->rtextsz); + rdatasz = le32toh(hdr->rdatasz); + itextsz = le32toh(hdr->itextsz); + idatasz = le32toh(hdr->idatasz); + btextsz = le32toh(hdr->btextsz); + + /* check that all firmware segments are present */ + if (fp->datasize < sizeof (struct wpi_firmware_hdr) + + rtextsz + rdatasz + itextsz + idatasz + btextsz) { + device_printf(sc->sc_dev, + "firmware file too short: %zu bytes\n", fp->datasize); + error = ENXIO; /* XXX appropriate error code? */ + goto fail; + } + + /* get pointers to firmware segments */ + rtext = (const uint8_t *)(hdr + 1); + rdata = rtext + rtextsz; + itext = rdata + rdatasz; + idata = itext + itextsz; + btext = idata + idatasz; + + DPRINTFN(WPI_DEBUG_FIRMWARE, + ("Firmware Version: Major %d, Minor %d, Driver %d, \n" + "runtime (text: %u, data: %u) init (text: %u, data %u) boot (text %u)\n", + (le32toh(hdr->version) & 0xff000000) >> 24, + (le32toh(hdr->version) & 0x00ff0000) >> 16, + (le32toh(hdr->version) & 0x0000ffff), + rtextsz, rdatasz, + itextsz, idatasz, btextsz)); + + DPRINTFN(WPI_DEBUG_FIRMWARE,("rtext 0x%x\n", *(const uint32_t *)rtext)); + DPRINTFN(WPI_DEBUG_FIRMWARE,("rdata 0x%x\n", *(const uint32_t *)rdata)); + DPRINTFN(WPI_DEBUG_FIRMWARE,("itext 0x%x\n", *(const uint32_t *)itext)); + DPRINTFN(WPI_DEBUG_FIRMWARE,("idata 0x%x\n", *(const uint32_t *)idata)); + DPRINTFN(WPI_DEBUG_FIRMWARE,("btext 0x%x\n", *(const uint32_t *)btext)); + + /* sanity checks */ + if (rtextsz > WPI_FW_MAIN_TEXT_MAXSZ || + rdatasz > WPI_FW_MAIN_DATA_MAXSZ || + itextsz > WPI_FW_INIT_TEXT_MAXSZ || + idatasz > WPI_FW_INIT_DATA_MAXSZ || + btextsz > WPI_FW_BOOT_TEXT_MAXSZ || + (btextsz & 3) != 0) { + device_printf(sc->sc_dev, "firmware invalid\n"); + error = EINVAL; + goto fail; + } + + /* copy initialization images into pre-allocated DMA-safe memory */ + memcpy(dma->vaddr, idata, idatasz); + memcpy(dma->vaddr + WPI_FW_INIT_DATA_MAXSZ, itext, itextsz); + + bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); + + /* tell adapter where to find initialization images */ + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr); + wpi_mem_write(sc, WPI_MEM_DATA_SIZE, idatasz); + wpi_mem_write(sc, WPI_MEM_TEXT_BASE, + dma->paddr + WPI_FW_INIT_DATA_MAXSZ); + wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, itextsz); + wpi_mem_unlock(sc); + + /* load firmware boot code */ + if ((error = wpi_load_microcode(sc, btext, btextsz)) != 0) { + device_printf(sc->sc_dev, "Failed to load microcode\n"); + goto fail; + } + + /* now press "execute" */ + WPI_WRITE(sc, WPI_RESET, 0); + + /* wait at most one second for the first alive notification */ + if ((error = msleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) { + device_printf(sc->sc_dev, + "timeout waiting for adapter to initialize\n"); + goto fail; + } + + /* copy runtime images into pre-allocated DMA-sage memory */ + memcpy(dma->vaddr, rdata, rdatasz); + memcpy(dma->vaddr + WPI_FW_MAIN_DATA_MAXSZ, rtext, rtextsz); + bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); + + /* tell adapter where to find runtime images */ + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr); + wpi_mem_write(sc, WPI_MEM_DATA_SIZE, rdatasz); + wpi_mem_write(sc, WPI_MEM_TEXT_BASE, + dma->paddr + WPI_FW_MAIN_DATA_MAXSZ); + wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, WPI_FW_UPDATED | rtextsz); + wpi_mem_unlock(sc); + + /* wait at most one second for the first alive notification */ + if ((error = msleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) { + device_printf(sc->sc_dev, + "timeout waiting for adapter to initialize2\n"); + goto fail; + } + + DPRINTFN(WPI_DEBUG_FIRMWARE, + ("Firmware loaded to driver successfully\n")); + return error; +fail: + wpi_unload_firmware(sc); + return error; +} + +/** + * Free the referenced firmware image + */ +static void +wpi_unload_firmware(struct wpi_softc *sc) +{ + + if (sc->fw_fp) { + WPI_UNLOCK(sc); + firmware_put(sc->fw_fp, FIRMWARE_UNLOAD); + WPI_LOCK(sc); + sc->fw_fp = NULL; + } +} + static int wpi_attach(device_t dev) { - struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev); - struct ieee80211com *ic; + struct wpi_softc *sc = device_get_softc(dev); struct ifnet *ifp; - int i, error, rid; -#ifdef WPI_DEBUG - int supportsa = 1; + struct ieee80211com *ic; + int ac, error, rid, supportsa = 1; + uint32_t tmp; const struct wpi_ident *ident; -#endif uint8_t macaddr[IEEE80211_ADDR_LEN]; sc->sc_dev = dev; -#ifdef WPI_DEBUG - error = resource_int_value(device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug)); - if (error != 0) - sc->sc_debug = 0; -#else - sc->sc_debug = 0; -#endif - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - /* - * Get the offset of the PCI Express Capability Structure in PCI - * Configuration Space. - */ - error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off); - if (error != 0) { - device_printf(dev, "PCIe capability structure not found!\n"); - return error; - } + if (bootverbose || WPI_DEBUG_SET) + device_printf(sc->sc_dev,"Driver Revision %s\n", VERSION); /* * Some card's only support 802.11b/g not a, check to see if * this is one such card. A 0x0 in the subdevice table indicates * the entire subdevice range is to be ignored. */ -#ifdef WPI_DEBUG for (ident = wpi_ident_table; ident->name != NULL; ident++) { if (ident->subdevice && pci_get_subdevice(dev) == ident->subdevice) { @@ -372,133 +513,143 @@ wpi_attach(device_t dev) break; } } -#endif - /* Clear device-specific "PCI retry timeout" register (41h). */ + /* Create the tasks that can be queued */ + TASK_INIT(&sc->sc_restarttask, 0, wpi_hwreset, sc); + TASK_INIT(&sc->sc_radiotask, 0, wpi_rfreset, sc); + + WPI_LOCK_INIT(sc); + + callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); + callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); + + /* disable the retry timeout register */ pci_write_config(dev, 0x41, 0, 1); - /* Enable bus-mastering. */ + /* enable bus-mastering */ pci_enable_busmaster(dev); rid = PCIR_BAR(0); sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem == NULL) { - device_printf(dev, "can't map mem space\n"); - return ENOMEM; + device_printf(dev, "could not allocate memory resource\n"); + error = ENOMEM; + goto fail; } + sc->sc_st = rman_get_bustag(sc->mem); sc->sc_sh = rman_get_bushandle(sc->mem); - i = 1; rid = 0; - if (pci_alloc_msi(dev, &i) == 0) - rid = 1; - /* Install interrupt handler. */ - sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | - (rid != 0 ? 0 : RF_SHAREABLE)); + sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE | RF_SHAREABLE); if (sc->irq == NULL) { - device_printf(dev, "can't map interrupt\n"); + device_printf(dev, "could not allocate interrupt resource\n"); error = ENOMEM; goto fail; } - WPI_LOCK_INIT(sc); - WPI_TX_LOCK_INIT(sc); - WPI_RXON_LOCK_INIT(sc); - WPI_NT_LOCK_INIT(sc); - WPI_TXQ_LOCK_INIT(sc); - WPI_TXQ_STATE_LOCK_INIT(sc); - - /* Allocate DMA memory for firmware transfers. */ + /* + * Allocate DMA memory for firmware transfers. + */ if ((error = wpi_alloc_fwmem(sc)) != 0) { - device_printf(dev, - "could not allocate memory for firmware, error %d\n", - error); + printf(": could not allocate firmware memory\n"); + error = ENOMEM; + goto fail; + } + + /* + * Put adapter into a known state. + */ + if ((error = wpi_reset(sc)) != 0) { + device_printf(dev, "could not reset adapter\n"); goto fail; } - /* Allocate shared page. */ + wpi_mem_lock(sc); + tmp = wpi_mem_read(sc, WPI_MEM_PCIDEV); + if (bootverbose || WPI_DEBUG_SET) + device_printf(sc->sc_dev, "Hardware Revision (0x%X)\n", tmp); + + wpi_mem_unlock(sc); + + /* Allocate shared page */ if ((error = wpi_alloc_shared(sc)) != 0) { device_printf(dev, "could not allocate shared page\n"); goto fail; } - /* Allocate TX rings - 4 for QoS purposes, 1 for commands. */ - for (i = 0; i < WPI_NTXQUEUES; i++) { - if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) { - device_printf(dev, - "could not allocate TX ring %d, error %d\n", i, - error); - goto fail; + /* tx data queues - 4 for QoS purposes */ + for (ac = 0; ac < WME_NUM_AC; ac++) { + error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT, ac); + if (error != 0) { + device_printf(dev, "could not allocate Tx ring %d\n",ac); + goto fail; } } - /* Allocate RX ring. */ - if ((error = wpi_alloc_rx_ring(sc)) != 0) { - device_printf(dev, "could not allocate RX ring, error %d\n", - error); + /* command queue to talk to the card's firmware */ + error = wpi_alloc_tx_ring(sc, &sc->cmdq, WPI_CMD_RING_COUNT, 4); + if (error != 0) { + device_printf(dev, "could not allocate command ring\n"); goto fail; } - /* Clear pending interrupts. */ - WPI_WRITE(sc, WPI_INT, 0xffffffff); + /* receive data queue */ + error = wpi_alloc_rx_ring(sc, &sc->rxq); + if (error != 0) { + device_printf(dev, "could not allocate Rx ring\n"); + goto fail; + } ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { - device_printf(dev, "can not allocate ifnet structure\n"); + device_printf(dev, "can not if_alloc()\n"); + error = ENOMEM; goto fail; } - ic = ifp->if_l2com; + ic->ic_ifp = ifp; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - /* Set device capabilities. */ + /* set device capabilities */ ic->ic_caps = IEEE80211_C_STA /* station mode supported */ - | IEEE80211_C_IBSS /* IBSS mode supported */ - | IEEE80211_C_HOSTAP /* Host access point mode */ | IEEE80211_C_MONITOR /* monitor mode supported */ - | IEEE80211_C_AHDEMO /* adhoc demo mode */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ | IEEE80211_C_TXPMGT /* tx power management */ | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_WPA /* 802.11i */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ + | IEEE80211_C_WPA /* 802.11i */ +/* XXX looks like WME is partly supported? */ +#if 0 + | IEEE80211_C_IBSS /* IBSS mode support */ + | IEEE80211_C_BGSCAN /* capable of bg scanning */ | IEEE80211_C_WME /* 802.11e */ - | IEEE80211_C_PMGT /* Station-side power mgmt */ + | IEEE80211_C_HOSTAP /* Host access point mode */ +#endif ; - ic->ic_cryptocaps = - IEEE80211_CRYPTO_AES_CCM; - /* * Read in the eeprom and also setup the channels for * net80211. We don't set the rates as net80211 does this for us */ - if ((error = wpi_read_eeprom(sc, macaddr)) != 0) { - device_printf(dev, "could not read EEPROM, error %d\n", - error); - goto fail; - } + wpi_read_eeprom(sc, macaddr); -#ifdef WPI_DEBUG - if (bootverbose) { - device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n", - sc->domain); - device_printf(sc->sc_dev, "Hardware Type: %c\n", - sc->type > 1 ? 'B': '?'); - device_printf(sc->sc_dev, "Hardware Revision: %c\n", - ((sc->rev & 0xf0) == 0xd0) ? 'D': '?'); - device_printf(sc->sc_dev, "SKU %s support 802.11a\n", - supportsa ? "does" : "does not"); - - /* XXX hw_config uses the PCIDEV for the Hardware rev. Must - check what sc->rev really represents - benjsc 20070615 */ + if (bootverbose || WPI_DEBUG_SET) { + device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n", sc->domain); + device_printf(sc->sc_dev, "Hardware Type: %c\n", + sc->type > 1 ? 'B': '?'); + device_printf(sc->sc_dev, "Hardware Revision: %c\n", + ((le16toh(sc->rev) & 0xf0) == 0xd0) ? 'D': '?'); + device_printf(sc->sc_dev, "SKU %s support 802.11a\n", + supportsa ? "does" : "does not"); + + /* XXX hw_config uses the PCIDEV for the Hardware rev. Must check + what sc->rev really represents - benjsc 20070615 */ } -#endif if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_softc = sc; @@ -511,124 +662,98 @@ wpi_attach(device_t dev) IFQ_SET_READY(&ifp->if_snd); ieee80211_ifattach(ic, macaddr); - ic->ic_vap_create = wpi_vap_create; - ic->ic_vap_delete = wpi_vap_delete; + /* override default methods */ ic->ic_raw_xmit = wpi_raw_xmit; - ic->ic_node_alloc = wpi_node_alloc; - sc->sc_node_free = ic->ic_node_free; - ic->ic_node_free = wpi_node_free; - ic->ic_wme.wme_update = wpi_updateedca; - ic->ic_update_promisc = wpi_update_promisc; - ic->ic_update_mcast = wpi_update_mcast; - ic->ic_newassoc = wpi_newassoc; + ic->ic_wme.wme_update = wpi_wme_update; ic->ic_scan_start = wpi_scan_start; ic->ic_scan_end = wpi_scan_end; ic->ic_set_channel = wpi_set_channel; ic->ic_scan_curchan = wpi_scan_curchan; ic->ic_scan_mindwell = wpi_scan_mindwell; - ic->ic_setregdomain = wpi_setregdomain; - - sc->sc_update_rx_ring = wpi_update_rx_ring; - sc->sc_update_tx_ring = wpi_update_tx_ring; - wpi_radiotap_attach(sc); - - callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); - callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0); - callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0); - callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0); - TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc); - TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc); - TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc); - TASK_INIT(&sc->sc_start_task, 0, wpi_start_task, sc); - - sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK, - taskqueue_thread_enqueue, &sc->sc_tq); - error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "wpi_taskq"); - if (error != 0) { - device_printf(dev, "can't start threads, error %d\n", error); - goto fail; - } + ic->ic_vap_create = wpi_vap_create; + ic->ic_vap_delete = wpi_vap_delete; - wpi_sysctlattach(sc); + ieee80211_radiotap_attach(ic, + &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), + WPI_TX_RADIOTAP_PRESENT, + &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), + WPI_RX_RADIOTAP_PRESENT); /* * Hook our interrupt after all initialization is complete. */ - error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, + error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE, NULL, wpi_intr, sc, &sc->sc_ih); if (error != 0) { - device_printf(dev, "can't establish interrupt, error %d\n", - error); + device_printf(dev, "could not set up interrupt\n"); goto fail; } if (bootverbose) ieee80211_announce(ic); - -#ifdef WPI_DEBUG - if (sc->sc_debug & WPI_DEBUG_HW) - ieee80211_announce_channels(ic); +#ifdef XXX_DEBUG + ieee80211_announce_channels(ic); #endif - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); return 0; fail: wpi_detach(dev); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - return error; + return ENXIO; } -/* - * Attach the interface to 802.11 radiotap. - */ -static void -wpi_radiotap_attach(struct wpi_softc *sc) +static int +wpi_detach(device_t dev) { + struct wpi_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - WPI_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - WPI_RX_RADIOTAP_PRESENT); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); -} + struct ieee80211com *ic; + int ac; -static void -wpi_sysctlattach(struct wpi_softc *sc) -{ -#ifdef WPI_DEBUG - struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); - struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + if (sc->irq != NULL) + bus_teardown_intr(dev, sc->irq, sc->sc_ih); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "debug", CTLFLAG_RW, &sc->sc_debug, sc->sc_debug, - "control debugging printfs"); -#endif -} + if (ifp != NULL) { + ic = ifp->if_l2com; -static void -wpi_init_beacon(struct wpi_vap *wvp) -{ - struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data; + ieee80211_draintask(ic, &sc->sc_restarttask); + ieee80211_draintask(ic, &sc->sc_radiotask); + wpi_stop(sc); + callout_drain(&sc->watchdog_to); + callout_drain(&sc->calib_to); + ieee80211_ifdetach(ic); + } - cmd->id = WPI_ID_BROADCAST; - cmd->ofdm_mask = 0xff; - cmd->cck_mask = 0x0f; - cmd->lifetime = htole32(WPI_LIFETIME_INFINITE); + WPI_LOCK(sc); + if (sc->txq[0].data_dmat) { + for (ac = 0; ac < WME_NUM_AC; ac++) + wpi_free_tx_ring(sc, &sc->txq[ac]); - /* - * XXX WPI_TX_AUTO_SEQ seems to be ignored - workaround this issue - * XXX by using WPI_TX_NEED_ACK instead (with some side effects). - */ - cmd->flags = htole32(WPI_TX_NEED_ACK | WPI_TX_INSERT_TSTAMP); + wpi_free_tx_ring(sc, &sc->cmdq); + wpi_free_rx_ring(sc, &sc->rxq); + wpi_free_shared(sc); + } + + if (sc->fw_fp != NULL) { + wpi_unload_firmware(sc); + } + + if (sc->fw_dma.tag) + wpi_free_fwmem(sc); + WPI_UNLOCK(sc); + + if (sc->irq != NULL) + bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq), + sc->irq); + if (sc->mem != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(sc->mem), sc->mem); + + if (ifp != NULL) + if_free(ifp); - bcn->code = WPI_CMD_SET_BEACON; - bcn->ac = WPI_CMD_QUEUE_NUM; - bcn->size = sizeof(struct wpi_cmd_beacon); + WPI_LOCK_DESTROY(sc); + + return 0; } static struct ieee80211vap * @@ -642,33 +767,19 @@ wpi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - wvp = (struct wpi_vap *) malloc(sizeof(struct wpi_vap), M_80211_VAP, M_NOWAIT | M_ZERO); if (wvp == NULL) return NULL; - vap = &wvp->wv_vap; + vap = &wvp->vap; ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); - - if (opmode == IEEE80211_M_IBSS || opmode == IEEE80211_M_HOSTAP) { - WPI_VAP_LOCK_INIT(wvp); - wpi_init_beacon(wvp); - } - - /* Override with driver methods. */ - vap->iv_key_set = wpi_key_set; - vap->iv_key_delete = wpi_key_delete; - wvp->wv_recv_mgmt = vap->iv_recv_mgmt; - vap->iv_recv_mgmt = wpi_recv_mgmt; - wvp->wv_newstate = vap->iv_newstate; + /* override with driver methods */ + wvp->newstate = vap->iv_newstate; vap->iv_newstate = wpi_newstate; - vap->iv_update_beacon = wpi_update_beacon; - vap->iv_max_aid = WPI_ID_IBSS_MAX - WPI_ID_IBSS_MIN + 1; ieee80211_ratectl_init(vap); - /* Complete setup. */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + /* complete setup */ + ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); ic->ic_opmode = opmode; return vap; } @@ -677,304 +788,127 @@ static void wpi_vap_delete(struct ieee80211vap *vap) { struct wpi_vap *wvp = WPI_VAP(vap); - struct wpi_buf *bcn = &wvp->wv_bcbuf; - enum ieee80211_opmode opmode = vap->iv_opmode; ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); - - if (opmode == IEEE80211_M_IBSS || opmode == IEEE80211_M_HOSTAP) { - if (bcn->m != NULL) - m_freem(bcn->m); - - WPI_VAP_LOCK_DESTROY(wvp); - } - free(wvp, M_80211_VAP); } -static int -wpi_detach(device_t dev) -{ - struct wpi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; - int qid; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - if (ifp != NULL) { - ic = ifp->if_l2com; - - ieee80211_draintask(ic, &sc->sc_radioon_task); - ieee80211_draintask(ic, &sc->sc_start_task); - - wpi_stop(sc); - - taskqueue_drain_all(sc->sc_tq); - taskqueue_free(sc->sc_tq); - - callout_drain(&sc->watchdog_rfkill); - callout_drain(&sc->tx_timeout); - callout_drain(&sc->scan_timeout); - callout_drain(&sc->calib_to); - ieee80211_ifdetach(ic); - } - - /* Uninstall interrupt handler. */ - if (sc->irq != NULL) { - bus_teardown_intr(dev, sc->irq, sc->sc_ih); - bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq), - sc->irq); - pci_release_msi(dev); - } - - if (sc->txq[0].data_dmat) { - /* Free DMA resources. */ - for (qid = 0; qid < WPI_NTXQUEUES; qid++) - wpi_free_tx_ring(sc, &sc->txq[qid]); - - wpi_free_rx_ring(sc); - wpi_free_shared(sc); - } - - if (sc->fw_dma.tag) - wpi_free_fwmem(sc); - - if (sc->mem != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(sc->mem), sc->mem); - - if (ifp != NULL) - if_free(ifp); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - WPI_TXQ_STATE_LOCK_DESTROY(sc); - WPI_TXQ_LOCK_DESTROY(sc); - WPI_NT_LOCK_DESTROY(sc); - WPI_RXON_LOCK_DESTROY(sc); - WPI_TX_LOCK_DESTROY(sc); - WPI_LOCK_DESTROY(sc); - return 0; -} - -static int -wpi_shutdown(device_t dev) -{ - struct wpi_softc *sc = device_get_softc(dev); - - wpi_stop(sc); - return 0; -} - -static int -wpi_suspend(device_t dev) -{ - struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - - ieee80211_suspend_all(ic); - return 0; -} - -static int -wpi_resume(device_t dev) -{ - struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - - /* Clear device-specific "PCI retry timeout" register (41h). */ - pci_write_config(dev, 0x41, 0, 1); - - ieee80211_resume_all(ic); - return 0; -} - -/* - * Grab exclusive access to NIC memory. - */ -static int -wpi_nic_lock(struct wpi_softc *sc) -{ - int ntries; - - /* Request exclusive access to NIC. */ - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); - - /* Spin until we actually get the lock. */ - for (ntries = 0; ntries < 1000; ntries++) { - if ((WPI_READ(sc, WPI_GP_CNTRL) & - (WPI_GP_CNTRL_MAC_ACCESS_ENA | WPI_GP_CNTRL_SLEEP)) == - WPI_GP_CNTRL_MAC_ACCESS_ENA) - return 0; - DELAY(10); - } - - device_printf(sc->sc_dev, "could not lock memory\n"); - - return ETIMEDOUT; -} - -/* - * Release lock on NIC memory. - */ -static __inline void -wpi_nic_unlock(struct wpi_softc *sc) -{ - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); -} - -static __inline uint32_t -wpi_prph_read(struct wpi_softc *sc, uint32_t addr) -{ - WPI_WRITE(sc, WPI_PRPH_RADDR, WPI_PRPH_DWORD | addr); - WPI_BARRIER_READ_WRITE(sc); - return WPI_READ(sc, WPI_PRPH_RDATA); -} - -static __inline void -wpi_prph_write(struct wpi_softc *sc, uint32_t addr, uint32_t data) -{ - WPI_WRITE(sc, WPI_PRPH_WADDR, WPI_PRPH_DWORD | addr); - WPI_BARRIER_WRITE(sc); - WPI_WRITE(sc, WPI_PRPH_WDATA, data); -} - -static __inline void -wpi_prph_setbits(struct wpi_softc *sc, uint32_t addr, uint32_t mask) -{ - wpi_prph_write(sc, addr, wpi_prph_read(sc, addr) | mask); -} - -static __inline void -wpi_prph_clrbits(struct wpi_softc *sc, uint32_t addr, uint32_t mask) -{ - wpi_prph_write(sc, addr, wpi_prph_read(sc, addr) & ~mask); -} - -static __inline void -wpi_prph_write_region_4(struct wpi_softc *sc, uint32_t addr, - const uint32_t *data, int count) -{ - for (; count > 0; count--, data++, addr += 4) - wpi_prph_write(sc, addr, *data); -} - -static __inline uint32_t -wpi_mem_read(struct wpi_softc *sc, uint32_t addr) -{ - WPI_WRITE(sc, WPI_MEM_RADDR, addr); - WPI_BARRIER_READ_WRITE(sc); - return WPI_READ(sc, WPI_MEM_RDATA); -} - -static __inline void -wpi_mem_read_region_4(struct wpi_softc *sc, uint32_t addr, uint32_t *data, - int count) -{ - for (; count > 0; count--, addr += 4) - *data++ = wpi_mem_read(sc, addr); -} - -static int -wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int count) -{ - uint8_t *out = data; - uint32_t val; - int error, ntries; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - if ((error = wpi_nic_lock(sc)) != 0) - return error; - - for (; count > 0; count -= 2, addr++) { - WPI_WRITE(sc, WPI_EEPROM, addr << 2); - for (ntries = 0; ntries < 10; ntries++) { - val = WPI_READ(sc, WPI_EEPROM); - if (val & WPI_EEPROM_READ_VALID) - break; - DELAY(5); - } - if (ntries == 10) { - device_printf(sc->sc_dev, - "timeout reading ROM at 0x%x\n", addr); - return ETIMEDOUT; - } - *out++= val >> 16; - if (count > 1) - *out ++= val >> 24; - } - - wpi_nic_unlock(sc); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - return 0; -} - static void wpi_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { if (error != 0) return; + KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs)); + *(bus_addr_t *)arg = segs[0].ds_addr; } /* * Allocates a contiguous block of dma memory of the requested size and - * alignment. + * alignment. Due to limitations of the FreeBSD dma subsystem as of 20071217, + * allocations greater than 4096 may fail. Hence if the requested alignment is + * greater we allocate 'alignment' size extra memory and shift the vaddr and + * paddr after the dma load. This bypasses the problem at the cost of a little + * more memory. */ static int wpi_dma_contig_alloc(struct wpi_softc *sc, struct wpi_dma_info *dma, - void **kvap, bus_size_t size, bus_size_t alignment) + void **kvap, bus_size_t size, bus_size_t alignment, int flags) { int error; + bus_size_t align; + bus_size_t reqsize; + + DPRINTFN(WPI_DEBUG_DMA, + ("Size: %zd - alignment %zd\n", size, alignment)); - dma->tag = NULL; dma->size = size; + dma->tag = NULL; - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment, - 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, - 1, size, BUS_DMA_NOWAIT, NULL, NULL, &dma->tag); - if (error != 0) + if (alignment > 4096) { + align = PAGE_SIZE; + reqsize = size + alignment; + } else { + align = alignment; + reqsize = size; + } + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), align, + 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, + NULL, NULL, reqsize, + 1, reqsize, flags, + NULL, NULL, &dma->tag); + if (error != 0) { + device_printf(sc->sc_dev, + "could not create shared page DMA tag\n"); goto fail; - - error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr, - BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map); - if (error != 0) + } + error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr_start, + flags | BUS_DMA_ZERO, &dma->map); + if (error != 0) { + device_printf(sc->sc_dev, + "could not allocate shared page DMA memory\n"); goto fail; + } - error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, size, - wpi_dma_map_addr, &dma->paddr, BUS_DMA_NOWAIT); - if (error != 0) - goto fail; + error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr_start, + reqsize, wpi_dma_map_addr, &dma->paddr_start, flags); - bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); + /* Save the original pointers so we can free all the memory */ + dma->paddr = dma->paddr_start; + dma->vaddr = dma->vaddr_start; + + /* + * Check the alignment and increment by 4096 until we get the + * requested alignment. Fail if can't obtain the alignment + * we requested. + */ + if ((dma->paddr & (alignment -1 )) != 0) { + int i; + + for (i = 0; i < alignment / 4096; i++) { + if ((dma->paddr & (alignment - 1 )) == 0) + break; + dma->paddr += 4096; + dma->vaddr += 4096; + } + if (i == alignment / 4096) { + device_printf(sc->sc_dev, + "alignment requirement was not satisfied\n"); + goto fail; + } + } + + if (error != 0) { + device_printf(sc->sc_dev, + "could not load shared page DMA map\n"); + goto fail; + } if (kvap != NULL) *kvap = dma->vaddr; return 0; -fail: wpi_dma_contig_free(dma); +fail: + wpi_dma_contig_free(dma); return error; } static void wpi_dma_contig_free(struct wpi_dma_info *dma) { - if (dma->vaddr != NULL) { - bus_dmamap_sync(dma->tag, dma->map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(dma->tag, dma->map); - bus_dmamem_free(dma->tag, dma->vaddr, dma->map); - dma->vaddr = NULL; - } - if (dma->tag != NULL) { + if (dma->tag) { + if (dma->map != NULL) { + if (dma->paddr_start != 0) { + bus_dmamap_sync(dma->tag, dma->map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(dma->tag, dma->map); + } + bus_dmamem_free(dma->tag, &dma->vaddr_start, dma->map); + } bus_dma_tag_destroy(dma->tag); - dma->tag = NULL; } } @@ -984,9 +918,19 @@ wpi_dma_contig_free(struct wpi_dma_info *dma) static int wpi_alloc_shared(struct wpi_softc *sc) { - /* Shared buffer must be aligned on a 4KB boundary. */ - return wpi_dma_contig_alloc(sc, &sc->shared_dma, - (void **)&sc->shared, sizeof (struct wpi_shared), 4096); + int error; + + error = wpi_dma_contig_alloc(sc, &sc->shared_dma, + (void **)&sc->shared, sizeof (struct wpi_shared), + PAGE_SIZE, + BUS_DMA_NOWAIT); + + if (error != 0) { + device_printf(sc->sc_dev, + "could not allocate shared area DMA memory\n"); + } + + return error; } static void @@ -995,167 +939,114 @@ wpi_free_shared(struct wpi_softc *sc) wpi_dma_contig_free(&sc->shared_dma); } -/* - * Allocate DMA-safe memory for firmware transfer. - */ static int -wpi_alloc_fwmem(struct wpi_softc *sc) -{ - /* Must be aligned on a 16-byte boundary. */ - return wpi_dma_contig_alloc(sc, &sc->fw_dma, NULL, - WPI_FW_TEXT_MAXSZ + WPI_FW_DATA_MAXSZ, 16); -} - -static void -wpi_free_fwmem(struct wpi_softc *sc) +wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring) { - wpi_dma_contig_free(&sc->fw_dma); -} -static int -wpi_alloc_rx_ring(struct wpi_softc *sc) -{ - struct wpi_rx_ring *ring = &sc->rxq; - bus_size_t size; int i, error; ring->cur = 0; - ring->update = 0; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - /* Allocate RX descriptors (16KB aligned.) */ - size = WPI_RX_RING_COUNT * sizeof (uint32_t); error = wpi_dma_contig_alloc(sc, &ring->desc_dma, - (void **)&ring->desc, size, WPI_RING_DMA_ALIGN); + (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t), + WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT); + if (error != 0) { device_printf(sc->sc_dev, - "%s: could not allocate RX ring DMA memory, error %d\n", + "%s: could not allocate rx ring DMA memory, error %d\n", __func__, error); goto fail; } - /* Create RX buffer DMA tag. */ - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - MJUMPAGESIZE, 1, MJUMPAGESIZE, BUS_DMA_NOWAIT, NULL, NULL, - &ring->data_dmat); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not create RX buf DMA tag, error %d\n", + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, + BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, MJUMPAGESIZE, 1, + MJUMPAGESIZE, BUS_DMA_NOWAIT, NULL, NULL, &ring->data_dmat); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: bus_dma_tag_create_failed, error %d\n", __func__, error); - goto fail; - } + goto fail; + } /* - * Allocate and map RX buffers. + * Setup Rx buffers. */ for (i = 0; i < WPI_RX_RING_COUNT; i++) { struct wpi_rx_data *data = &ring->data[i]; + struct mbuf *m; bus_addr_t paddr; error = bus_dmamap_create(ring->data_dmat, 0, &data->map); if (error != 0) { device_printf(sc->sc_dev, - "%s: could not create RX buf DMA map, error %d\n", + "%s: bus_dmamap_create failed, error %d\n", __func__, error); goto fail; } - - data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); - if (data->m == NULL) { + m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); + if (m == NULL) { device_printf(sc->sc_dev, - "%s: could not allocate RX mbuf\n", __func__); - error = ENOBUFS; + "%s: could not allocate rx mbuf\n", __func__); + error = ENOMEM; goto fail; } - + /* map page */ error = bus_dmamap_load(ring->data_dmat, data->map, - mtod(data->m, void *), MJUMPAGESIZE, wpi_dma_map_addr, - &paddr, BUS_DMA_NOWAIT); + mtod(m, caddr_t), MJUMPAGESIZE, + wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); if (error != 0 && error != EFBIG) { device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, - error); + "%s: bus_dmamap_load failed, error %d\n", + __func__, error); + m_freem(m); + error = ENOMEM; /* XXX unique code */ goto fail; } + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_PREWRITE); - /* Set physical address of RX buffer. */ + data->m = m; ring->desc[i] = htole32(paddr); } - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - return 0; - -fail: wpi_free_rx_ring(sc); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - +fail: + wpi_free_rx_ring(sc, ring); return error; } static void -wpi_update_rx_ring(struct wpi_softc *sc) +wpi_reset_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring) { - WPI_WRITE(sc, WPI_FH_RX_WPTR, sc->rxq.cur & ~7); -} + int ntries; -static void -wpi_update_rx_ring_ps(struct wpi_softc *sc) -{ - struct wpi_rx_ring *ring = &sc->rxq; + wpi_mem_lock(sc); - if (ring->update != 0) { - /* Wait for INT_WAKEUP event. */ - return; - } + WPI_WRITE(sc, WPI_RX_CONFIG, 0); - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { - DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s: wakeup request\n", - __func__); - ring->update = 1; - } else { - wpi_update_rx_ring(sc); - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + for (ntries = 0; ntries < 100; ntries++) { + if (WPI_READ(sc, WPI_RX_STATUS) & WPI_RX_IDLE) + break; + DELAY(10); } -} - -static void -wpi_reset_rx_ring(struct wpi_softc *sc) -{ - struct wpi_rx_ring *ring = &sc->rxq; - int ntries; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + wpi_mem_unlock(sc); - if (wpi_nic_lock(sc) == 0) { - WPI_WRITE(sc, WPI_FH_RX_CONFIG, 0); - for (ntries = 0; ntries < 1000; ntries++) { - if (WPI_READ(sc, WPI_FH_RX_STATUS) & - WPI_FH_RX_STATUS_IDLE) - break; - DELAY(10); - } - wpi_nic_unlock(sc); - } +#ifdef WPI_DEBUG + if (ntries == 100 && wpi_debug > 0) + device_printf(sc->sc_dev, "timeout resetting Rx ring\n"); +#endif ring->cur = 0; - ring->update = 0; } static void -wpi_free_rx_ring(struct wpi_softc *sc) +wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring) { - struct wpi_rx_ring *ring = &sc->rxq; int i; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - wpi_dma_contig_free(&ring->desc_dma); for (i = 0; i < WPI_RX_RING_COUNT; i++) { @@ -1166,64 +1057,52 @@ wpi_free_rx_ring(struct wpi_softc *sc) BUS_DMASYNC_POSTREAD); bus_dmamap_unload(ring->data_dmat, data->map); m_freem(data->m); - data->m = NULL; } if (data->map != NULL) bus_dmamap_destroy(ring->data_dmat, data->map); } - if (ring->data_dmat != NULL) { - bus_dma_tag_destroy(ring->data_dmat); - ring->data_dmat = NULL; - } } static int -wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int qid) +wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int count, + int qid) { - bus_addr_t paddr; - bus_size_t size; + struct wpi_tx_data *data; int i, error; ring->qid = qid; + ring->count = count; ring->queued = 0; ring->cur = 0; - ring->update = 0; + ring->data = NULL; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + error = wpi_dma_contig_alloc(sc, &ring->desc_dma, + (void **)&ring->desc, count * sizeof (struct wpi_tx_desc), + WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT); - /* Allocate TX descriptors (16KB aligned.) */ - size = WPI_TX_RING_COUNT * sizeof (struct wpi_tx_desc); - error = wpi_dma_contig_alloc(sc, &ring->desc_dma, (void **)&ring->desc, - size, WPI_RING_DMA_ALIGN); if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not allocate TX ring DMA memory, error %d\n", - __func__, error); - goto fail; + device_printf(sc->sc_dev, "could not allocate tx dma memory\n"); + goto fail; } - /* Update shared area with ring physical address. */ + /* update shared page with ring's base address */ sc->shared->txbase[qid] = htole32(ring->desc_dma.paddr); - bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map, - BUS_DMASYNC_PREWRITE); - - /* - * We only use rings 0 through 4 (4 EDCA + cmd) so there is no need - * to allocate commands space for other rings. - * XXX Do we really need to allocate descriptors for other rings? - */ - if (qid > WPI_CMD_QUEUE_NUM) { - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - return 0; - } - size = WPI_TX_RING_COUNT * sizeof (struct wpi_tx_cmd); error = wpi_dma_contig_alloc(sc, &ring->cmd_dma, (void **)&ring->cmd, - size, 4); + count * sizeof (struct wpi_tx_cmd), WPI_RING_DMA_ALIGN, + BUS_DMA_NOWAIT); + if (error != 0) { device_printf(sc->sc_dev, - "%s: could not allocate TX cmd DMA memory, error %d\n", - __func__, error); + "could not allocate tx command DMA memory\n"); + goto fail; + } + + ring->data = malloc(count * sizeof (struct wpi_tx_data), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (ring->data == NULL) { + device_printf(sc->sc_dev, + "could not allocate tx data slots\n"); goto fail; } @@ -1232,664 +1111,726 @@ wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int qid) WPI_MAX_SCATTER - 1, MCLBYTES, BUS_DMA_NOWAIT, NULL, NULL, &ring->data_dmat); if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not create TX buf DMA tag, error %d\n", - __func__, error); + device_printf(sc->sc_dev, "could not create data DMA tag\n"); goto fail; } - paddr = ring->cmd_dma.paddr; - for (i = 0; i < WPI_TX_RING_COUNT; i++) { - struct wpi_tx_data *data = &ring->data[i]; - - data->cmd_paddr = paddr; - paddr += sizeof (struct wpi_tx_cmd); + for (i = 0; i < count; i++) { + data = &ring->data[i]; error = bus_dmamap_create(ring->data_dmat, 0, &data->map); if (error != 0) { device_printf(sc->sc_dev, - "%s: could not create TX buf DMA map, error %d\n", - __func__, error); + "could not create tx buf DMA map\n"); goto fail; } + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_PREWRITE); } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - return 0; -fail: wpi_free_tx_ring(sc, ring); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); +fail: + wpi_free_tx_ring(sc, ring); return error; } static void -wpi_update_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) -{ - WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); -} - -static void -wpi_update_tx_ring_ps(struct wpi_softc *sc, struct wpi_tx_ring *ring) +wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) { + struct wpi_tx_data *data; + int i, ntries; - if (ring->update != 0) { - /* Wait for INT_WAKEUP event. */ - return; - } + wpi_mem_lock(sc); - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_SLEEP) { - DPRINTF(sc, WPI_DEBUG_PWRSAVE, "%s (%d): requesting wakeup\n", - __func__, ring->qid); - ring->update = 1; - } else { - wpi_update_tx_ring(sc, ring); - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); + WPI_WRITE(sc, WPI_TX_CONFIG(ring->qid), 0); + for (ntries = 0; ntries < 100; ntries++) { + if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(ring->qid)) + break; + DELAY(10); } -} - -static void -wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) -{ - int i; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); +#ifdef WPI_DEBUG + if (ntries == 100 && wpi_debug > 0) + device_printf(sc->sc_dev, "timeout resetting Tx ring %d\n", + ring->qid); +#endif + wpi_mem_unlock(sc); - for (i = 0; i < WPI_TX_RING_COUNT; i++) { - struct wpi_tx_data *data = &ring->data[i]; + for (i = 0; i < ring->count; i++) { + data = &ring->data[i]; if (data->m != NULL) { - bus_dmamap_sync(ring->data_dmat, data->map, - BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->data_dmat, data->map); m_freem(data->m); data->m = NULL; } - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } } - /* Clear TX descriptors. */ - memset(ring->desc, 0, ring->desc_dma.size); - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - sc->qfullmsk &= ~(1 << ring->qid); + ring->queued = 0; ring->cur = 0; - ring->update = 0; } static void wpi_free_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) { + struct wpi_tx_data *data; int i; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - wpi_dma_contig_free(&ring->desc_dma); wpi_dma_contig_free(&ring->cmd_dma); - for (i = 0; i < WPI_TX_RING_COUNT; i++) { - struct wpi_tx_data *data = &ring->data[i]; + if (ring->data != NULL) { + for (i = 0; i < ring->count; i++) { + data = &ring->data[i]; - if (data->m != NULL) { - bus_dmamap_sync(ring->data_dmat, data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(ring->data_dmat, data->map); - m_freem(data->m); + if (data->m != NULL) { + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + data->m = NULL; + } } - if (data->map != NULL) - bus_dmamap_destroy(ring->data_dmat, data->map); + free(ring->data, M_DEVBUF); } - if (ring->data_dmat != NULL) { + + if (ring->data_dmat != NULL) bus_dma_tag_destroy(ring->data_dmat); - ring->data_dmat = NULL; - } } -/* - * Extract various information from EEPROM. - */ static int -wpi_read_eeprom(struct wpi_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) +wpi_shutdown(device_t dev) { -#define WPI_CHK(res) do { \ - if ((error = res) != 0) \ - goto fail; \ -} while (0) - int error, i; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - /* Adapter has to be powered on for EEPROM access to work. */ - if ((error = wpi_apm_init(sc)) != 0) { - device_printf(sc->sc_dev, - "%s: could not power ON adapter, error %d\n", __func__, - error); - return error; - } + struct wpi_softc *sc = device_get_softc(dev); - if ((WPI_READ(sc, WPI_EEPROM_GP) & 0x6) == 0) { - device_printf(sc->sc_dev, "bad EEPROM signature\n"); - error = EIO; - goto fail; - } - /* Clear HW ownership of EEPROM. */ - WPI_CLRBITS(sc, WPI_EEPROM_GP, WPI_EEPROM_GP_IF_OWNER); + WPI_LOCK(sc); + wpi_stop_locked(sc); + wpi_unload_firmware(sc); + WPI_UNLOCK(sc); - /* Read the hardware capabilities, revision and SKU type. */ - WPI_CHK(wpi_read_prom_data(sc, WPI_EEPROM_SKU_CAP, &sc->cap, - sizeof(sc->cap))); - WPI_CHK(wpi_read_prom_data(sc, WPI_EEPROM_REVISION, &sc->rev, - sizeof(sc->rev))); - WPI_CHK(wpi_read_prom_data(sc, WPI_EEPROM_TYPE, &sc->type, - sizeof(sc->type))); + return 0; +} - sc->rev = le16toh(sc->rev); - DPRINTF(sc, WPI_DEBUG_EEPROM, "cap=%x rev=%x type=%x\n", sc->cap, - sc->rev, sc->type); +static int +wpi_suspend(device_t dev) +{ + struct wpi_softc *sc = device_get_softc(dev); + struct ieee80211com *ic = sc->sc_ifp->if_l2com; - /* Read the regulatory domain (4 ASCII characters.) */ - WPI_CHK(wpi_read_prom_data(sc, WPI_EEPROM_DOMAIN, sc->domain, - sizeof(sc->domain))); + ieee80211_suspend_all(ic); + return 0; +} - /* Read MAC address. */ - WPI_CHK(wpi_read_prom_data(sc, WPI_EEPROM_MAC, macaddr, - IEEE80211_ADDR_LEN)); +static int +wpi_resume(device_t dev) +{ + struct wpi_softc *sc = device_get_softc(dev); + struct ieee80211com *ic = sc->sc_ifp->if_l2com; - /* Read the list of authorized channels. */ - for (i = 0; i < WPI_CHAN_BANDS_COUNT; i++) - WPI_CHK(wpi_read_eeprom_channels(sc, i)); + pci_write_config(dev, 0x41, 0, 1); - /* Read the list of TX power groups. */ - for (i = 0; i < WPI_POWER_GROUPS_COUNT; i++) - WPI_CHK(wpi_read_eeprom_group(sc, i)); + ieee80211_resume_all(ic); + return 0; +} -fail: wpi_apm_stop(sc); /* Power OFF adapter. */ +/** + * Called by net80211 when ever there is a change to 80211 state machine + */ +static int +wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) +{ + struct wpi_vap *wvp = WPI_VAP(vap); + struct ieee80211com *ic = vap->iv_ic; + struct ifnet *ifp = ic->ic_ifp; + struct wpi_softc *sc = ifp->if_softc; + int error; - DPRINTF(sc, WPI_DEBUG_TRACE, error ? TRACE_STR_END_ERR : TRACE_STR_END, - __func__); + DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__, + ieee80211_state_name[vap->iv_state], + ieee80211_state_name[nstate], sc->flags)); - return error; -#undef WPI_CHK + IEEE80211_UNLOCK(ic); + WPI_LOCK(sc); + if (nstate == IEEE80211_S_SCAN && vap->iv_state != IEEE80211_S_INIT) { + /* + * On !INIT -> SCAN transitions, we need to clear any possible + * knowledge about associations. + */ + error = wpi_config(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: device config failed, error %d\n", + __func__, error); + } + } + if (nstate == IEEE80211_S_AUTH || + (nstate == IEEE80211_S_ASSOC && vap->iv_state == IEEE80211_S_RUN)) { + /* + * The node must be registered in the firmware before auth. + * Also the associd must be cleared on RUN -> ASSOC + * transitions. + */ + error = wpi_auth(sc, vap); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not move to auth state, error %d\n", + __func__, error); + } + } + if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) { + error = wpi_run(sc, vap); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not move to run state, error %d\n", + __func__, error); + } + } + if (nstate == IEEE80211_S_RUN) { + /* RUN -> RUN transition; just restart the timers */ + wpi_calib_timeout(sc); + /* XXX split out rate control timer */ + } + WPI_UNLOCK(sc); + IEEE80211_LOCK(ic); + return wvp->newstate(vap, nstate, arg); } /* - * Translate EEPROM flags to net80211. + * Grab exclusive access to NIC memory. */ -static uint32_t -wpi_eeprom_channel_flags(struct wpi_eeprom_chan *channel) +static void +wpi_mem_lock(struct wpi_softc *sc) { - uint32_t nflags; + int ntries; + uint32_t tmp; - nflags = 0; - if ((channel->flags & WPI_EEPROM_CHAN_ACTIVE) == 0) - nflags |= IEEE80211_CHAN_PASSIVE; - if ((channel->flags & WPI_EEPROM_CHAN_IBSS) == 0) - nflags |= IEEE80211_CHAN_NOADHOC; - if (channel->flags & WPI_EEPROM_CHAN_RADAR) { - nflags |= IEEE80211_CHAN_DFS; - /* XXX apparently IBSS may still be marked */ - nflags |= IEEE80211_CHAN_NOADHOC; + tmp = WPI_READ(sc, WPI_GPIO_CTL); + WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_MAC); + + /* spin until we actually get the lock */ + for (ntries = 0; ntries < 100; ntries++) { + if ((WPI_READ(sc, WPI_GPIO_CTL) & + (WPI_GPIO_CLOCK | WPI_GPIO_SLEEP)) == WPI_GPIO_CLOCK) + break; + DELAY(10); } + if (ntries == 100) + device_printf(sc->sc_dev, "could not lock memory\n"); +} - /* XXX HOSTAP uses WPI_MODE_IBSS */ - if (nflags & IEEE80211_CHAN_NOADHOC) - nflags |= IEEE80211_CHAN_NOHOSTAP; +/* + * Release lock on NIC memory. + */ +static void +wpi_mem_unlock(struct wpi_softc *sc) +{ + uint32_t tmp = WPI_READ(sc, WPI_GPIO_CTL); + WPI_WRITE(sc, WPI_GPIO_CTL, tmp & ~WPI_GPIO_MAC); +} - return nflags; +static uint32_t +wpi_mem_read(struct wpi_softc *sc, uint16_t addr) +{ + WPI_WRITE(sc, WPI_READ_MEM_ADDR, WPI_MEM_4 | addr); + return WPI_READ(sc, WPI_READ_MEM_DATA); } static void -wpi_read_eeprom_band(struct wpi_softc *sc, int n) +wpi_mem_write(struct wpi_softc *sc, uint16_t addr, uint32_t data) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct wpi_eeprom_chan *channels = sc->eeprom_channels[n]; - const struct wpi_chan_band *band = &wpi_bands[n]; - struct ieee80211_channel *c; - uint8_t chan; - int i, nflags; - - for (i = 0; i < band->nchan; i++) { - if (!(channels[i].flags & WPI_EEPROM_CHAN_VALID)) { - DPRINTF(sc, WPI_DEBUG_EEPROM, - "Channel Not Valid: %d, band %d\n", - band->chan[i],n); - continue; - } + WPI_WRITE(sc, WPI_WRITE_MEM_ADDR, WPI_MEM_4 | addr); + WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data); +} - chan = band->chan[i]; - nflags = wpi_eeprom_channel_flags(&channels[i]); +static void +wpi_mem_write_region_4(struct wpi_softc *sc, uint16_t addr, + const uint32_t *data, int wlen) +{ + for (; wlen > 0; wlen--, data++, addr+=4) + wpi_mem_write(sc, addr, *data); +} - c = &ic->ic_channels[ic->ic_nchans++]; - c->ic_ieee = chan; - c->ic_maxregpower = channels[i].maxpwr; - c->ic_maxpower = 2*c->ic_maxregpower; +/* + * Read data from the EEPROM. We access EEPROM through the MAC instead of + * using the traditional bit-bang method. Data is read up until len bytes have + * been obtained. + */ +static uint16_t +wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int len) +{ + int ntries; + uint32_t val; + uint8_t *out = data; - if (n == 0) { /* 2GHz band */ - c->ic_freq = ieee80211_ieee2mhz(chan, - IEEE80211_CHAN_G); + wpi_mem_lock(sc); - /* G =>'s B is supported */ - c->ic_flags = IEEE80211_CHAN_B | nflags; - c = &ic->ic_channels[ic->ic_nchans++]; - c[0] = c[-1]; - c->ic_flags = IEEE80211_CHAN_G | nflags; - } else { /* 5GHz band */ - c->ic_freq = ieee80211_ieee2mhz(chan, - IEEE80211_CHAN_A); + for (; len > 0; len -= 2, addr++) { + WPI_WRITE(sc, WPI_EEPROM_CTL, addr << 2); - c->ic_flags = IEEE80211_CHAN_A | nflags; + for (ntries = 0; ntries < 10; ntries++) { + if ((val = WPI_READ(sc, WPI_EEPROM_CTL)) & WPI_EEPROM_READY) + break; + DELAY(5); } - /* Save maximum allowed TX power for this channel. */ - sc->maxpwr[chan] = channels[i].maxpwr; + if (ntries == 10) { + device_printf(sc->sc_dev, "could not read EEPROM\n"); + return ETIMEDOUT; + } - DPRINTF(sc, WPI_DEBUG_EEPROM, - "adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d," - " offset %d\n", chan, c->ic_freq, - channels[i].flags, sc->maxpwr[chan], - IEEE80211_IS_CHAN_PASSIVE(c), ic->ic_nchans); + *out++= val >> 16; + if (len > 1) + *out ++= val >> 24; } + + wpi_mem_unlock(sc); + + return 0; } -/** - * Read the eeprom to find out what channels are valid for the given - * band and update net80211 with what we find. +/* + * The firmware text and data segments are transferred to the NIC using DMA. + * The driver just copies the firmware into DMA-safe memory and tells the NIC + * where to find it. Once the NIC has copied the firmware into its internal + * memory, we can free our local copy in the driver. */ static int -wpi_read_eeprom_channels(struct wpi_softc *sc, int n) +wpi_load_microcode(struct wpi_softc *sc, const uint8_t *fw, int size) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - const struct wpi_chan_band *band = &wpi_bands[n]; - int error; + int error, ntries; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + DPRINTFN(WPI_DEBUG_HW,("Loading microcode size 0x%x\n", size)); - error = wpi_read_prom_data(sc, band->addr, &sc->eeprom_channels[n], - band->nchan * sizeof (struct wpi_eeprom_chan)); - if (error != 0) { - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - return error; - } + size /= sizeof(uint32_t); - wpi_read_eeprom_band(sc, n); + wpi_mem_lock(sc); - ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans); + wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE, + (const uint32_t *)fw, size); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + wpi_mem_write(sc, WPI_MEM_UCODE_SRC, 0); + wpi_mem_write(sc, WPI_MEM_UCODE_DST, WPI_FW_TEXT); + wpi_mem_write(sc, WPI_MEM_UCODE_SIZE, size); - return 0; -} + /* run microcode */ + wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN); -static struct wpi_eeprom_chan * -wpi_find_eeprom_channel(struct wpi_softc *sc, struct ieee80211_channel *c) -{ - int i, j; + /* wait while the adapter is busy copying the firmware */ + for (error = 0, ntries = 0; ntries < 1000; ntries++) { + uint32_t status = WPI_READ(sc, WPI_TX_STATUS); + DPRINTFN(WPI_DEBUG_HW, + ("firmware status=0x%x, val=0x%x, result=0x%x\n", status, + WPI_TX_IDLE(6), status & WPI_TX_IDLE(6))); + if (status & WPI_TX_IDLE(6)) { + DPRINTFN(WPI_DEBUG_HW, + ("Status Match! - ntries = %d\n", ntries)); + break; + } + DELAY(10); + } + if (ntries == 1000) { + device_printf(sc->sc_dev, "timeout transferring firmware\n"); + error = ETIMEDOUT; + } - for (j = 0; j < WPI_CHAN_BANDS_COUNT; j++) - for (i = 0; i < wpi_bands[j].nchan; i++) - if (wpi_bands[j].chan[i] == c->ic_ieee) - return &sc->eeprom_channels[j][i]; + /* start the microcode executing */ + wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_ENABLE); - return NULL; -} - -/* - * Enforce flags read from EEPROM. - */ -static int -wpi_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd, - int nchan, struct ieee80211_channel chans[]) -{ - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; - int i; - - for (i = 0; i < nchan; i++) { - struct ieee80211_channel *c = &chans[i]; - struct wpi_eeprom_chan *channel; - - channel = wpi_find_eeprom_channel(sc, c); - if (channel == NULL) { - if_printf(ic->ic_ifp, - "%s: invalid channel %u freq %u/0x%x\n", - __func__, c->ic_ieee, c->ic_freq, c->ic_flags); - return EINVAL; - } - c->ic_flags |= wpi_eeprom_channel_flags(channel); - } + wpi_mem_unlock(sc); - return 0; + return (error); } -static int -wpi_read_eeprom_group(struct wpi_softc *sc, int n) +static void +wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc, + struct wpi_rx_data *data) { - struct wpi_power_group *group = &sc->groups[n]; - struct wpi_eeprom_group rgroup; - int i, error; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_rx_ring *ring = &sc->rxq; + struct wpi_rx_stat *stat; + struct wpi_rx_head *head; + struct wpi_rx_tail *tail; + struct ieee80211_node *ni; + struct mbuf *m, *mnew; + bus_addr_t paddr; + int error; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + stat = (struct wpi_rx_stat *)(desc + 1); - if ((error = wpi_read_prom_data(sc, WPI_EEPROM_POWER_GRP + n * 32, - &rgroup, sizeof rgroup)) != 0) { - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - return error; + if (stat->len > WPI_STAT_MAXLEN) { + device_printf(sc->sc_dev, "invalid rx statistic header\n"); + ifp->if_ierrors++; + return; } - /* Save TX power group information. */ - group->chan = rgroup.chan; - group->maxpwr = rgroup.maxpwr; - /* Retrieve temperature at which the samples were taken. */ - group->temp = (int16_t)le16toh(rgroup.temp); - - DPRINTF(sc, WPI_DEBUG_EEPROM, - "power group %d: chan=%d maxpwr=%d temp=%d\n", n, group->chan, - group->maxpwr, group->temp); + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); + head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len); + tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + le16toh(head->len)); + + DPRINTFN(WPI_DEBUG_RX, ("rx intr: idx=%d len=%d stat len=%d rssi=%d " + "rate=%x chan=%d tstamp=%ju\n", ring->cur, le32toh(desc->len), + le16toh(head->len), (int8_t)stat->rssi, head->rate, head->chan, + (uintmax_t)le64toh(tail->tstamp))); + + /* discard Rx frames with bad CRC early */ + if ((le32toh(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) { + DPRINTFN(WPI_DEBUG_RX, ("%s: rx flags error %x\n", __func__, + le32toh(tail->flags))); + ifp->if_ierrors++; + return; + } + if (le16toh(head->len) < sizeof (struct ieee80211_frame)) { + DPRINTFN(WPI_DEBUG_RX, ("%s: frame too short: %d\n", __func__, + le16toh(head->len))); + ifp->if_ierrors++; + return; + } - for (i = 0; i < WPI_SAMPLES_COUNT; i++) { - group->samples[i].index = rgroup.samples[i].index; - group->samples[i].power = rgroup.samples[i].power; + /* XXX don't need mbuf, just dma buffer */ + mnew = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); + if (mnew == NULL) { + DPRINTFN(WPI_DEBUG_RX, ("%s: no mbuf to restock ring\n", + __func__)); + ifp->if_ierrors++; + return; + } + bus_dmamap_unload(ring->data_dmat, data->map); - DPRINTF(sc, WPI_DEBUG_EEPROM, - "\tsample %d: index=%d power=%d\n", i, - group->samples[i].index, group->samples[i].power); + error = bus_dmamap_load(ring->data_dmat, data->map, + mtod(mnew, caddr_t), MJUMPAGESIZE, + wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); + if (error != 0 && error != EFBIG) { + device_printf(sc->sc_dev, + "%s: bus_dmamap_load failed, error %d\n", __func__, error); + m_freem(mnew); + ifp->if_ierrors++; + return; } + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + /* finalize mbuf and swap in new one */ + m = data->m; + m->m_pkthdr.rcvif = ifp; + m->m_data = (caddr_t)(head + 1); + m->m_pkthdr.len = m->m_len = le16toh(head->len); - return 0; -} + data->m = mnew; + /* update Rx descriptor */ + ring->desc[ring->cur] = htole32(paddr); -static int -wpi_add_node_entry_adhoc(struct wpi_softc *sc) -{ - int newid = WPI_ID_IBSS_MIN; + if (ieee80211_radiotap_active(ic)) { + struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap; - for (; newid <= WPI_ID_IBSS_MAX; newid++) { - if ((sc->nodesmsk & (1 << newid)) == 0) { - sc->nodesmsk |= 1 << newid; - return newid; - } + tap->wr_flags = 0; + tap->wr_chan_freq = + htole16(ic->ic_channels[head->chan].ic_freq); + tap->wr_chan_flags = + htole16(ic->ic_channels[head->chan].ic_flags); + tap->wr_dbm_antsignal = (int8_t)(stat->rssi - WPI_RSSI_OFFSET); + tap->wr_dbm_antnoise = (int8_t)le16toh(stat->noise); + tap->wr_tsft = tail->tstamp; + tap->wr_antenna = (le16toh(head->flags) >> 4) & 0xf; + switch (head->rate) { + /* CCK rates */ + case 10: tap->wr_rate = 2; break; + case 20: tap->wr_rate = 4; break; + case 55: tap->wr_rate = 11; break; + case 110: tap->wr_rate = 22; break; + /* OFDM rates */ + case 0xd: tap->wr_rate = 12; break; + case 0xf: tap->wr_rate = 18; break; + case 0x5: tap->wr_rate = 24; break; + case 0x7: tap->wr_rate = 36; break; + case 0x9: tap->wr_rate = 48; break; + case 0xb: tap->wr_rate = 72; break; + case 0x1: tap->wr_rate = 96; break; + case 0x3: tap->wr_rate = 108; break; + /* unknown rate: should not happen */ + default: tap->wr_rate = 0; + } + if (le16toh(head->flags) & 0x4) + tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; } - return WPI_ID_UNDEFINED; -} - -static __inline int -wpi_add_node_entry_sta(struct wpi_softc *sc) -{ - sc->nodesmsk |= 1 << WPI_ID_BSS; - - return WPI_ID_BSS; -} + WPI_UNLOCK(sc); -static __inline int -wpi_check_node_entry(struct wpi_softc *sc, uint8_t id) -{ - if (id == WPI_ID_UNDEFINED) - return 0; + ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); + if (ni != NULL) { + (void) ieee80211_input(ni, m, stat->rssi, 0); + ieee80211_free_node(ni); + } else + (void) ieee80211_input_all(ic, m, stat->rssi, 0); - return (sc->nodesmsk >> id) & 1; + WPI_LOCK(sc); } -static __inline void -wpi_clear_node_table(struct wpi_softc *sc) +static void +wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) { - sc->nodesmsk = 0; -} + struct ifnet *ifp = sc->sc_ifp; + struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; + struct wpi_tx_data *txdata = &ring->data[desc->idx]; + struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); + struct ieee80211_node *ni = txdata->ni; + struct ieee80211vap *vap = ni->ni_vap; + int retrycnt = 0; -static __inline void -wpi_del_node_entry(struct wpi_softc *sc, uint8_t id) -{ - sc->nodesmsk &= ~(1 << id); -} + DPRINTFN(WPI_DEBUG_TX, ("tx done: qid=%d idx=%d retries=%d nkill=%d " + "rate=%x duration=%d status=%x\n", desc->qid, desc->idx, + stat->ntries, stat->nkill, stat->rate, le32toh(stat->duration), + le32toh(stat->status))); -static struct ieee80211_node * -wpi_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct wpi_node *wn; + /* + * Update rate control statistics for the node. + * XXX we should not count mgmt frames since they're always sent at + * the lowest available bit-rate. + * XXX frames w/o ACK shouldn't be used either + */ + if (stat->ntries > 0) { + DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries)); + retrycnt = 1; + } + ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); - wn = malloc(sizeof (struct wpi_node), M_80211_NODE, - M_NOWAIT | M_ZERO); + /* XXX oerrors should only count errors !maxtries */ + if ((le32toh(stat->status) & 0xff) != 1) + ifp->if_oerrors++; + else + ifp->if_opackets++; - if (wn == NULL) - return NULL; + bus_dmamap_sync(ring->data_dmat, txdata->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, txdata->map); + /* XXX handle M_TXCB? */ + m_freem(txdata->m); + txdata->m = NULL; + ieee80211_free_node(txdata->ni); + txdata->ni = NULL; - wn->id = WPI_ID_UNDEFINED; + ring->queued--; - return &wn->ni; + sc->sc_tx_timer = 0; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + wpi_start_locked(ifp); } static void -wpi_node_free(struct ieee80211_node *ni) +wpi_cmd_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) { - struct ieee80211com *ic = ni->ni_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); + struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_data *data; - if (wn->id != WPI_ID_UNDEFINED) { - WPI_NT_LOCK(sc); - if (wpi_check_node_entry(sc, wn->id)) { - wpi_del_node_entry(sc, wn->id); - wpi_del_node(sc, ni); - } - WPI_NT_UNLOCK(sc); - } + DPRINTFN(WPI_DEBUG_CMD, ("cmd notification qid=%x idx=%d flags=%x " + "type=%s len=%d\n", desc->qid, desc->idx, + desc->flags, wpi_cmd_str(desc->type), + le32toh(desc->len))); - sc->sc_node_free(ni); -} + if ((desc->qid & 7) != 4) + return; /* not a command ack */ -static __inline int -wpi_check_bss_filter(struct wpi_softc *sc) -{ - return (sc->rxon.filter & htole32(WPI_FILTER_BSS)) != 0; -} + data = &ring->data[desc->idx]; -static void -wpi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, int rssi, - int nf) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; - struct wpi_vap *wvp = WPI_VAP(vap); - uint64_t ni_tstamp, rx_tstamp; - - wvp->wv_recv_mgmt(ni, m, subtype, rssi, nf); - - if (vap->iv_opmode == IEEE80211_M_IBSS && - vap->iv_state == IEEE80211_S_RUN && - (subtype == IEEE80211_FC0_SUBTYPE_BEACON || - subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { - ni_tstamp = le64toh(ni->ni_tstamp.tsf); - rx_tstamp = le64toh(sc->rx_tstamp); - - if (ni_tstamp >= rx_tstamp) { - DPRINTF(sc, WPI_DEBUG_STATE, - "ibss merge, tsf %ju tstamp %ju\n", - (uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp); - (void) ieee80211_ibss_merge(ni); - } + /* if the command was mapped in a mbuf, free it */ + if (data->m != NULL) { + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + data->m = NULL; } + + sc->flags &= ~WPI_FLAG_BUSY; + wakeup(&ring->cmd[desc->idx]); } static void -wpi_restore_node(void *arg, struct ieee80211_node *ni) +wpi_notif_intr(struct wpi_softc *sc) { - struct wpi_softc *sc = arg; - struct wpi_node *wn = WPI_NODE(ni); - int error; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_rx_desc *desc; + struct wpi_rx_data *data; + uint32_t hw; - WPI_NT_LOCK(sc); - if (wn->id != WPI_ID_UNDEFINED) { - wn->id = WPI_ID_UNDEFINED; - if ((error = wpi_add_ibss_node(sc, ni)) != 0) { - device_printf(sc->sc_dev, - "%s: could not add IBSS node, error %d\n", - __func__, error); - } - } - WPI_NT_UNLOCK(sc); -} + bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map, + BUS_DMASYNC_POSTREAD); -static void -wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + hw = le32toh(sc->shared->next); + while (sc->rxq.cur != hw) { + data = &sc->rxq.data[sc->rxq.cur]; - /* Set group keys once. */ - WPI_NT_LOCK(sc); - wvp->wv_gtk = 0; - WPI_NT_UNLOCK(sc); + bus_dmamap_sync(sc->rxq.data_dmat, data->map, + BUS_DMASYNC_POSTREAD); + desc = (void *)data->m->m_ext.ext_buf; - ieee80211_iterate_nodes(&ic->ic_sta, wpi_restore_node, sc); - ieee80211_crypto_reload_keys(ic); -} + DPRINTFN(WPI_DEBUG_NOTIFY, + ("notify qid=%x idx=%d flags=%x type=%d len=%d\n", + desc->qid, + desc->idx, + desc->flags, + desc->type, + le32toh(desc->len))); -/** - * Called by net80211 when ever there is a change to 80211 state machine - */ -static int -wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct wpi_vap *wvp = WPI_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; - int error = 0; + if (!(desc->qid & 0x80)) /* reply to a command */ + wpi_cmd_intr(sc, desc); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + switch (desc->type) { + case WPI_RX_DONE: + /* a 802.11 frame was received */ + wpi_rx_intr(sc, desc, data); + break; - DPRINTF(sc, WPI_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); + case WPI_TX_DONE: + /* a 802.11 frame has been transmitted */ + wpi_tx_intr(sc, desc); + break; - if (vap->iv_state == IEEE80211_S_RUN && nstate < IEEE80211_S_RUN) { - if ((error = wpi_set_pslevel(sc, 0, 0, 1)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set power saving level\n", - __func__); - return error; - } + case WPI_UC_READY: + { + struct wpi_ucode_info *uc = + (struct wpi_ucode_info *)(desc + 1); - wpi_set_led(sc, WPI_LED_LINK, 1, 0); - } + /* the microcontroller is ready */ + DPRINTF(("microcode alive notification version %x " + "alive %x\n", le32toh(uc->version), + le32toh(uc->valid))); - switch (nstate) { - case IEEE80211_S_SCAN: - WPI_RXON_LOCK(sc); - if (wpi_check_bss_filter(sc) != 0) { - sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); - if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { + if (le32toh(uc->valid) != 1) { device_printf(sc->sc_dev, - "%s: could not send RXON\n", __func__); + "microcontroller initialization failed\n"); + wpi_stop_locked(sc); } + break; } - WPI_RXON_UNLOCK(sc); - break; + case WPI_STATE_CHANGED: + { + uint32_t *status = (uint32_t *)(desc + 1); + + /* enabled/disabled notification */ + DPRINTF(("state changed to %x\n", le32toh(*status))); - case IEEE80211_S_ASSOC: - if (vap->iv_state != IEEE80211_S_RUN) + if (le32toh(*status) & 1) { + device_printf(sc->sc_dev, + "Radio transmitter is switched off\n"); + sc->flags |= WPI_FLAG_HW_RADIO_OFF; + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + /* Disable firmware commands */ + WPI_WRITE(sc, WPI_UCODE_SET, WPI_DISABLE_CMD); + } break; - /* FALLTHROUGH */ - case IEEE80211_S_AUTH: - /* - * NB: do not optimize AUTH -> AUTH state transmission - - * this will break powersave with non-QoS AP! - */ + } + case WPI_START_SCAN: + { +#ifdef WPI_DEBUG + struct wpi_start_scan *scan = + (struct wpi_start_scan *)(desc + 1); +#endif - /* - * The node must be registered in the firmware before auth. - * Also the associd must be cleared on RUN -> ASSOC - * transitions. - */ - if ((error = wpi_auth(sc, vap)) != 0) { - device_printf(sc->sc_dev, - "%s: could not move to AUTH state, error %d\n", - __func__, error); + DPRINTFN(WPI_DEBUG_SCANNING, + ("scanning channel %d status %x\n", + scan->chan, le32toh(scan->status))); + break; } - break; + case WPI_STOP_SCAN: + { +#ifdef WPI_DEBUG + struct wpi_stop_scan *scan = + (struct wpi_stop_scan *)(desc + 1); +#endif + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - case IEEE80211_S_RUN: - /* - * RUN -> RUN transition: - * STA mode: Just restart the timers. - * IBSS mode: Process IBSS merge. - */ - if (vap->iv_state == IEEE80211_S_RUN) { - if (vap->iv_opmode != IEEE80211_M_IBSS) { - WPI_RXON_LOCK(sc); - wpi_calib_timeout(sc); - WPI_RXON_UNLOCK(sc); - break; - } else { - /* - * Drop the BSS_FILTER bit - * (there is no another way to change bssid). - */ - WPI_RXON_LOCK(sc); - sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); - if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { - device_printf(sc->sc_dev, - "%s: could not send RXON\n", - __func__); - } - WPI_RXON_UNLOCK(sc); - - /* Restore all what was lost. */ - wpi_restore_node_table(sc, wvp); - - /* XXX set conditionally? */ - wpi_updateedca(ic); + DPRINTFN(WPI_DEBUG_SCANNING, + ("scan finished nchan=%d status=%d chan=%d\n", + scan->nchan, scan->status, scan->chan)); + + sc->sc_scan_timer = 0; + ieee80211_scan_next(vap); + break; + } + case WPI_MISSED_BEACON: + { + struct wpi_missed_beacon *beacon = + (struct wpi_missed_beacon *)(desc + 1); + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + + if (le32toh(beacon->consecutive) >= + vap->iv_bmissthreshold) { + DPRINTF(("Beacon miss: %u >= %u\n", + le32toh(beacon->consecutive), + vap->iv_bmissthreshold)); + ieee80211_beacon_miss(ic); } + break; } - - /* - * !RUN -> RUN requires setting the association id - * which is done with a firmware cmd. We also defer - * starting the timers until that work is done. - */ - if ((error = wpi_run(sc, vap)) != 0) { - device_printf(sc->sc_dev, - "%s: could not move to RUN state\n", __func__); } - break; - default: - break; - } - if (error != 0) { - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - return error; + sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT; } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - return wvp->wv_newstate(vap, nstate, arg); + /* tell the firmware what we have processed */ + hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1; + WPI_WRITE(sc, WPI_RX_WIDX, hw & ~7); } static void -wpi_calib_timeout(void *arg) +wpi_intr(void *arg) { struct wpi_softc *sc = arg; + uint32_t r; + + WPI_LOCK(sc); - if (wpi_check_bss_filter(sc) == 0) + r = WPI_READ(sc, WPI_INTR); + if (r == 0 || r == 0xffffffff) { + WPI_UNLOCK(sc); return; + } - wpi_power_calibration(sc); + /* disable interrupts */ + WPI_WRITE(sc, WPI_MASK, 0); + /* ack interrupts */ + WPI_WRITE(sc, WPI_INTR, r); - callout_reset(&sc->calib_to, 60*hz, wpi_calib_timeout, sc); + if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) { + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + + device_printf(sc->sc_dev, "fatal firmware error\n"); + DPRINTFN(6,("(%s)\n", (r & WPI_SW_ERROR) ? "(Software Error)" : + "(Hardware Error)")); + if (vap != NULL) + ieee80211_cancel_scan(vap); + ieee80211_runtask(ic, &sc->sc_restarttask); + sc->flags &= ~WPI_FLAG_BUSY; + WPI_UNLOCK(sc); + return; + } + + if (r & WPI_RX_INTR) + wpi_notif_intr(sc); + + if (r & WPI_ALIVE_INTR) /* firmware initialized */ + wakeup(sc); + + /* re-enable interrupts */ + if (sc->sc_ifp->if_flags & IFF_UP) + WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK); + + WPI_UNLOCK(sc); } -static __inline uint8_t -rate2plcp(const uint8_t rate) +static uint8_t +wpi_plcp_signal(int rate) { switch (rate) { + /* CCK rates (returned values are device-dependent) */ + case 2: return 10; + case 4: return 20; + case 11: return 55; + case 22: return 110; + + /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ + /* R1-R4 (ral/ural is R4-R1) */ case 12: return 0xd; case 18: return 0xf; case 24: return 0x5; @@ -1898,2568 +1839,652 @@ rate2plcp(const uint8_t rate) case 72: return 0xb; case 96: return 0x1; case 108: return 0x3; - case 2: return 10; - case 4: return 20; - case 11: return 55; - case 22: return 110; - default: return 0; - } -} -static __inline uint8_t -plcp2rate(const uint8_t plcp) -{ - switch (plcp) { - case 0xd: return 12; - case 0xf: return 18; - case 0x5: return 24; - case 0x7: return 36; - case 0x9: return 48; - case 0xb: return 72; - case 0x1: return 96; - case 0x3: return 108; - case 10: return 2; - case 20: return 4; - case 55: return 11; - case 110: return 22; + /* unsupported rates (should not get there) */ default: return 0; } } -/* Quickly determine if a given rate is CCK or OFDM. */ -#define WPI_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) +/* quickly determine if a given rate is CCK or OFDM */ +#define WPI_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) -static void -wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc, - struct wpi_rx_data *data) +/* + * Construct the data packet for a transmit buffer and acutally put + * the buffer onto the transmit ring, kicking the card to process the + * the buffer. + */ +static int +wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, + int ac) { + struct ieee80211vap *vap = ni->ni_vap; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - struct wpi_rx_ring *ring = &sc->rxq; - struct wpi_rx_stat *stat; - struct wpi_rx_head *head; - struct wpi_rx_tail *tail; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m, *m1; - bus_addr_t paddr; - uint32_t flags; - uint16_t len; - int error; - - stat = (struct wpi_rx_stat *)(desc + 1); - - if (stat->len > WPI_STAT_MAXLEN) { - device_printf(sc->sc_dev, "invalid RX statistic header\n"); - goto fail1; - } - - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); - head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len); - len = le16toh(head->len); - tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + len); - flags = le32toh(tail->flags); - - DPRINTF(sc, WPI_DEBUG_RECV, "%s: idx %d len %d stat len %u rssi %d" - " rate %x chan %d tstamp %ju\n", __func__, ring->cur, - le32toh(desc->len), len, (int8_t)stat->rssi, - head->plcp, head->chan, (uintmax_t)le64toh(tail->tstamp)); - - /* Discard frames with a bad FCS early. */ - if ((flags & WPI_RX_NOERROR) != WPI_RX_NOERROR) { - DPRINTF(sc, WPI_DEBUG_RECV, "%s: RX flags error %x\n", - __func__, flags); - goto fail1; - } - /* Discard frames that are too short. */ - if (len < sizeof (struct ieee80211_frame_ack)) { - DPRINTF(sc, WPI_DEBUG_RECV, "%s: frame too short: %d\n", - __func__, len); - goto fail1; - } - - m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); - if (m1 == NULL) { - DPRINTF(sc, WPI_DEBUG_ANY, "%s: no mbuf to restock ring\n", - __func__); - goto fail1; - } - bus_dmamap_unload(ring->data_dmat, data->map); - - error = bus_dmamap_load(ring->data_dmat, data->map, mtod(m1, void *), - MJUMPAGESIZE, wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); - if (error != 0 && error != EFBIG) { - device_printf(sc->sc_dev, - "%s: bus_dmamap_load failed, error %d\n", __func__, error); - m_freem(m1); - - /* Try to reload the old mbuf. */ - error = bus_dmamap_load(ring->data_dmat, data->map, - mtod(data->m, void *), MJUMPAGESIZE, wpi_dma_map_addr, - &paddr, BUS_DMA_NOWAIT); - if (error != 0 && error != EFBIG) { - panic("%s: could not load old RX mbuf", __func__); - } - /* Physical address may have changed. */ - ring->desc[ring->cur] = htole32(paddr); - bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - goto fail1; - } - - m = data->m; - data->m = m1; - /* Update RX descriptor. */ - ring->desc[ring->cur] = htole32(paddr); - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - - /* Finalize mbuf. */ - m->m_pkthdr.rcvif = ifp; - m->m_data = (caddr_t)(head + 1); - m->m_pkthdr.len = m->m_len = len; - - /* Grab a reference to the source node. */ - wh = mtod(m, struct ieee80211_frame *); - - if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && - (flags & WPI_RX_CIPHER_MASK) == WPI_RX_CIPHER_CCMP) { - /* Check whether decryption was successful or not. */ - if ((flags & WPI_RX_DECRYPT_MASK) != WPI_RX_DECRYPT_OK) { - DPRINTF(sc, WPI_DEBUG_RECV, - "CCMP decryption failed 0x%x\n", flags); - goto fail2; - } - m->m_flags |= M_WEP; - } - - if (len >= sizeof(struct ieee80211_frame_min)) - ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); - else - ni = NULL; - - sc->rx_tstamp = tail->tstamp; - - if (ieee80211_radiotap_active(ic)) { - struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - if (head->flags & htole16(WPI_STAT_FLAG_SHPREAMBLE)) - tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - tap->wr_dbm_antsignal = (int8_t)(stat->rssi + WPI_RSSI_OFFSET); - tap->wr_dbm_antnoise = WPI_RSSI_OFFSET; - tap->wr_tsft = tail->tstamp; - tap->wr_antenna = (le16toh(head->flags) >> 4) & 0xf; - tap->wr_rate = plcp2rate(head->plcp); - } - - WPI_UNLOCK(sc); - - /* Send the frame to the 802.11 layer. */ - if (ni != NULL) { - (void)ieee80211_input(ni, m, stat->rssi, WPI_RSSI_OFFSET); - /* Node is no longer needed. */ - ieee80211_free_node(ni); - } else - (void)ieee80211_input_all(ic, m, stat->rssi, WPI_RSSI_OFFSET); - - WPI_LOCK(sc); - - return; - -fail2: m_freem(m); - -fail1: if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); -} - -static void -wpi_rx_statistics(struct wpi_softc *sc, struct wpi_rx_desc *desc, - struct wpi_rx_data *data) -{ - /* Ignore */ -} - -static void -wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; - struct wpi_tx_data *data = &ring->data[desc->idx]; - struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); - struct mbuf *m; - struct ieee80211_node *ni; - struct ieee80211vap *vap; - struct ieee80211com *ic; - uint32_t status = le32toh(stat->status); - int ackfailcnt = stat->ackfailcnt / WPI_NTRIES_DEFAULT; - - KASSERT(data->ni != NULL, ("no node")); - KASSERT(data->m != NULL, ("no mbuf")); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - DPRINTF(sc, WPI_DEBUG_XMIT, "%s: " - "qid %d idx %d retries %d btkillcnt %d rate %x duration %d " - "status %x\n", __func__, desc->qid, desc->idx, stat->ackfailcnt, - stat->btkillcnt, stat->rate, le32toh(stat->duration), status); - - /* Unmap and free mbuf. */ - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(ring->data_dmat, data->map); - m = data->m, data->m = NULL; - ni = data->ni, data->ni = NULL; - vap = ni->ni_vap; - ic = vap->iv_ic; - - /* - * Update rate control statistics for the node. - */ - if (status & WPI_TX_STATUS_FAIL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); - } - - ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0); - - WPI_TXQ_STATE_LOCK(sc); - ring->queued -= 1; - if (ring->queued > 0) { - callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); - - if (sc->qfullmsk != 0 && - ring->queued < WPI_TX_RING_LOMARK) { - sc->qfullmsk &= ~(1 << ring->qid); - IF_LOCK(&ifp->if_snd); - if (sc->qfullmsk == 0 && - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - ieee80211_runtask(ic, &sc->sc_start_task); - } else - IF_UNLOCK(&ifp->if_snd); - } - } else - callout_stop(&sc->tx_timeout); - WPI_TXQ_STATE_UNLOCK(sc); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); -} - -/* - * Process a "command done" firmware notification. This is where we wakeup - * processes waiting for a synchronous command completion. - */ -static void -wpi_cmd_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) -{ - struct wpi_tx_ring *ring = &sc->txq[WPI_CMD_QUEUE_NUM]; + const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; + struct wpi_tx_ring *ring = &sc->txq[ac]; + struct wpi_tx_desc *desc; struct wpi_tx_data *data; + struct wpi_tx_cmd *cmd; + struct wpi_cmd_data *tx; + struct ieee80211_frame *wh; + const struct ieee80211_txparam *tp; + struct ieee80211_key *k; + struct mbuf *mnew; + int i, error, nsegs, rate, hdrlen, ismcast; + bus_dma_segment_t segs[WPI_MAX_SCATTER]; - DPRINTF(sc, WPI_DEBUG_CMD, "cmd notification qid %x idx %d flags %x " - "type %s len %d\n", desc->qid, desc->idx, - desc->flags, wpi_cmd_str(desc->type), - le32toh(desc->len)); - - if ((desc->qid & WPI_RX_DESC_QID_MSK) != WPI_CMD_QUEUE_NUM) - return; /* Not a command ack. */ - - KASSERT(ring->queued == 0, ("ring->queued must be 0")); - - data = &ring->data[desc->idx]; - - /* If the command was mapped in an mbuf, free it. */ - if (data->m != NULL) { - bus_dmamap_sync(ring->data_dmat, data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(ring->data_dmat, data->map); - m_freem(data->m); - data->m = NULL; - } - - wakeup(&ring->cmd[desc->idx]); - - if (desc->type == WPI_CMD_SET_POWER_MODE) { - WPI_TXQ_LOCK(sc); - if (sc->sc_flags & WPI_PS_PATH) { - sc->sc_update_rx_ring = wpi_update_rx_ring_ps; - sc->sc_update_tx_ring = wpi_update_tx_ring_ps; - } else { - sc->sc_update_rx_ring = wpi_update_rx_ring; - sc->sc_update_tx_ring = wpi_update_tx_ring; - } - WPI_TXQ_UNLOCK(sc); - } -} - -static void -wpi_notif_intr(struct wpi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t hw; - - bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map, - BUS_DMASYNC_POSTREAD); - - hw = le32toh(sc->shared->next) & 0xfff; - hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1; - - while (sc->rxq.cur != hw) { - sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT; - - struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur]; - struct wpi_rx_desc *desc; - - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - desc = mtod(data->m, struct wpi_rx_desc *); - - DPRINTF(sc, WPI_DEBUG_NOTIFY, - "%s: cur=%d; qid %x idx %d flags %x type %d(%s) len %d\n", - __func__, sc->rxq.cur, desc->qid, desc->idx, desc->flags, - desc->type, wpi_cmd_str(desc->type), le32toh(desc->len)); - - if (!(desc->qid & WPI_UNSOLICITED_RX_NOTIF)) { - /* Reply to a command. */ - wpi_cmd_done(sc, desc); - } - - switch (desc->type) { - case WPI_RX_DONE: - /* An 802.11 frame has been received. */ - wpi_rx_done(sc, desc, data); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - /* wpi_stop() was called. */ - return; - } - - break; - - case WPI_TX_DONE: - /* An 802.11 frame has been transmitted. */ - wpi_tx_done(sc, desc); - break; - - case WPI_RX_STATISTICS: - case WPI_BEACON_STATISTICS: - wpi_rx_statistics(sc, desc, data); - break; - - case WPI_BEACON_MISSED: - { - struct wpi_beacon_missed *miss = - (struct wpi_beacon_missed *)(desc + 1); - uint32_t expected, misses, received, threshold; - - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - - misses = le32toh(miss->consecutive); - expected = le32toh(miss->expected); - received = le32toh(miss->received); - threshold = MAX(2, vap->iv_bmissthreshold); - - DPRINTF(sc, WPI_DEBUG_BMISS, - "%s: beacons missed %u(%u) (received %u/%u)\n", - __func__, misses, le32toh(miss->total), received, - expected); - - if (misses >= threshold || - (received == 0 && expected >= threshold)) { - WPI_RXON_LOCK(sc); - if (callout_pending(&sc->scan_timeout)) { - wpi_cmd(sc, WPI_CMD_SCAN_ABORT, NULL, - 0, 1); - } - WPI_RXON_UNLOCK(sc); - if (vap->iv_state == IEEE80211_S_RUN && - (ic->ic_flags & IEEE80211_F_SCAN) == 0) - ieee80211_beacon_miss(ic); - } - - break; - } -#ifdef WPI_DEBUG - case WPI_BEACON_SENT: - { - struct wpi_tx_stat *stat = - (struct wpi_tx_stat *)(desc + 1); - uint64_t *tsf = (uint64_t *)(stat + 1); - uint32_t *mode = (uint32_t *)(tsf + 1); - - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - - DPRINTF(sc, WPI_DEBUG_BEACON, - "beacon sent: rts %u, ack %u, btkill %u, rate %u, " - "duration %u, status %x, tsf %ju, mode %x\n", - stat->rtsfailcnt, stat->ackfailcnt, - stat->btkillcnt, stat->rate, le32toh(stat->duration), - le32toh(stat->status), *tsf, *mode); - - break; - } -#endif - case WPI_UC_READY: - { - struct wpi_ucode_info *uc = - (struct wpi_ucode_info *)(desc + 1); - - /* The microcontroller is ready. */ - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - DPRINTF(sc, WPI_DEBUG_RESET, - "microcode alive notification version=%d.%d " - "subtype=%x alive=%x\n", uc->major, uc->minor, - uc->subtype, le32toh(uc->valid)); - - if (le32toh(uc->valid) != 1) { - device_printf(sc->sc_dev, - "microcontroller initialization failed\n"); - wpi_stop_locked(sc); - } - /* Save the address of the error log in SRAM. */ - sc->errptr = le32toh(uc->errptr); - break; - } - case WPI_STATE_CHANGED: - { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - - uint32_t *status = (uint32_t *)(desc + 1); - - DPRINTF(sc, WPI_DEBUG_STATE, "state changed to %x\n", - le32toh(*status)); - - if (le32toh(*status) & 1) { - WPI_NT_LOCK(sc); - wpi_clear_node_table(sc); - WPI_NT_UNLOCK(sc); - taskqueue_enqueue(sc->sc_tq, - &sc->sc_radiooff_task); - return; - } - break; - } -#ifdef WPI_DEBUG - case WPI_START_SCAN: - { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); - - struct wpi_start_scan *scan = - (struct wpi_start_scan *)(desc + 1); - DPRINTF(sc, WPI_DEBUG_SCAN, - "%s: scanning channel %d status %x\n", - __func__, scan->chan, le32toh(scan->status)); + desc = &ring->desc[ring->cur]; + data = &ring->data[ring->cur]; - break; - } -#endif - case WPI_STOP_SCAN: - { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); + wh = mtod(m0, struct ieee80211_frame *); - struct wpi_stop_scan *scan = - (struct wpi_stop_scan *)(desc + 1); - - DPRINTF(sc, WPI_DEBUG_SCAN, - "scan finished nchan=%d status=%d chan=%d\n", - scan->nchan, scan->status, scan->chan); - - WPI_RXON_LOCK(sc); - callout_stop(&sc->scan_timeout); - WPI_RXON_UNLOCK(sc); - if (scan->status == WPI_SCAN_ABORTED) - ieee80211_cancel_scan(vap); - else - ieee80211_scan_next(vap); - break; - } - } + hdrlen = ieee80211_hdrsize(wh); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - if (sc->rxq.cur % 8 == 0) { - /* Tell the firmware what we have processed. */ - sc->sc_update_rx_ring(sc); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + k = ieee80211_crypto_encap(ni, m0); + if (k == NULL) { + m_freem(m0); + return ENOBUFS; } + /* packet header may have moved, reset our local pointer */ + wh = mtod(m0, struct ieee80211_frame *); } -} - -/* - * Process an INT_WAKEUP interrupt raised when the microcontroller wakes up - * from power-down sleep mode. - */ -static void -wpi_wakeup_intr(struct wpi_softc *sc) -{ - int qid; - DPRINTF(sc, WPI_DEBUG_PWRSAVE, - "%s: ucode wakeup from power-down sleep\n", __func__); + cmd = &ring->cmd[ring->cur]; + cmd->code = WPI_CMD_TX_DATA; + cmd->flags = 0; + cmd->qid = ring->qid; + cmd->idx = ring->cur; - /* Wakeup RX and TX rings. */ - if (sc->rxq.update) { - sc->rxq.update = 0; - wpi_update_rx_ring(sc); - } - WPI_TXQ_LOCK(sc); - for (qid = 0; qid < WPI_DRV_NTXQUEUES; qid++) { - struct wpi_tx_ring *ring = &sc->txq[qid]; + tx = (struct wpi_cmd_data *)cmd->data; + tx->flags = htole32(WPI_TX_AUTO_SEQ); + tx->timeout = htole16(0); + tx->ofdm_mask = 0xff; + tx->cck_mask = 0x0f; + tx->lifetime = htole32(WPI_LIFETIME_INFINITE); + tx->id = ismcast ? WPI_ID_BROADCAST : WPI_ID_BSS; + tx->len = htole16(m0->m_pkthdr.len); - if (ring->update) { - ring->update = 0; - wpi_update_tx_ring(sc, ring); + if (!ismcast) { + if ((ni->ni_flags & IEEE80211_NODE_QOS) == 0 || + !cap->cap_wmeParams[ac].wmep_noackPolicy) + tx->flags |= htole32(WPI_TX_NEED_ACK); + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) { + tx->flags |= htole32(WPI_TX_NEED_RTS|WPI_TX_FULL_TXOP); + tx->rts_ntries = 7; } } - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ); - WPI_TXQ_UNLOCK(sc); -} - -/* - * This function prints firmware registers - */ -#ifdef WPI_DEBUG -static void -wpi_debug_registers(struct wpi_softc *sc) -{ - size_t i; - static const uint32_t csr_tbl[] = { - WPI_HW_IF_CONFIG, - WPI_INT, - WPI_INT_MASK, - WPI_FH_INT, - WPI_GPIO_IN, - WPI_RESET, - WPI_GP_CNTRL, - WPI_EEPROM, - WPI_EEPROM_GP, - WPI_GIO, - WPI_UCODE_GP1, - WPI_UCODE_GP2, - WPI_GIO_CHICKEN, - WPI_ANA_PLL, - WPI_DBG_HPET_MEM, - }; - static const uint32_t prph_tbl[] = { - WPI_APMG_CLK_CTRL, - WPI_APMG_PS, - WPI_APMG_PCI_STT, - WPI_APMG_RFKILL, - }; - - DPRINTF(sc, WPI_DEBUG_REGISTER,"%s","\n"); - - for (i = 0; i < nitems(csr_tbl); i++) { - DPRINTF(sc, WPI_DEBUG_REGISTER, " %-18s: 0x%08x ", - wpi_get_csr_string(csr_tbl[i]), WPI_READ(sc, csr_tbl[i])); - - if ((i + 1) % 2 == 0) - DPRINTF(sc, WPI_DEBUG_REGISTER, "\n"); - } - DPRINTF(sc, WPI_DEBUG_REGISTER, "\n\n"); - - if (wpi_nic_lock(sc) == 0) { - for (i = 0; i < nitems(prph_tbl); i++) { - DPRINTF(sc, WPI_DEBUG_REGISTER, " %-18s: 0x%08x ", - wpi_get_prph_string(prph_tbl[i]), - wpi_prph_read(sc, prph_tbl[i])); - - if ((i + 1) % 2 == 0) - DPRINTF(sc, WPI_DEBUG_REGISTER, "\n"); - } - DPRINTF(sc, WPI_DEBUG_REGISTER, "\n"); - wpi_nic_unlock(sc); + /* pick a rate */ + tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; + if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) { + uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + /* tell h/w to set timestamp in probe responses */ + if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) + tx->flags |= htole32(WPI_TX_INSERT_TSTAMP); + if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ || + subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) + tx->timeout = htole16(3); + else + tx->timeout = htole16(2); + rate = tp->mgmtrate; + } else if (ismcast) { + rate = tp->mcastrate; + } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { + rate = tp->ucastrate; } else { - DPRINTF(sc, WPI_DEBUG_REGISTER, - "Cannot access internal registers.\n"); - } -} -#endif - -/* - * Dump the error log of the firmware when a firmware panic occurs. Although - * we can't debug the firmware because it is neither open source nor free, it - * can help us to identify certain classes of problems. - */ -static void -wpi_fatal_intr(struct wpi_softc *sc) -{ - struct wpi_fw_dump dump; - uint32_t i, offset, count; - - /* Check that the error log address is valid. */ - if (sc->errptr < WPI_FW_DATA_BASE || - sc->errptr + sizeof (dump) > - WPI_FW_DATA_BASE + WPI_FW_DATA_MAXSZ) { - printf("%s: bad firmware error log address 0x%08x\n", __func__, - sc->errptr); - return; - } - if (wpi_nic_lock(sc) != 0) { - printf("%s: could not read firmware error log\n", __func__); - return; - } - /* Read number of entries in the log. */ - count = wpi_mem_read(sc, sc->errptr); - if (count == 0 || count * sizeof (dump) > WPI_FW_DATA_MAXSZ) { - printf("%s: invalid count field (count = %u)\n", __func__, - count); - wpi_nic_unlock(sc); - return; - } - /* Skip "count" field. */ - offset = sc->errptr + sizeof (uint32_t); - printf("firmware error log (count = %u):\n", count); - for (i = 0; i < count; i++) { - wpi_mem_read_region_4(sc, offset, (uint32_t *)&dump, - sizeof (dump) / sizeof (uint32_t)); - - printf(" error type = \"%s\" (0x%08X)\n", - (dump.desc < nitems(wpi_fw_errmsg)) ? - wpi_fw_errmsg[dump.desc] : "UNKNOWN", - dump.desc); - printf(" error data = 0x%08X\n", - dump.data); - printf(" branch link = 0x%08X%08X\n", - dump.blink[0], dump.blink[1]); - printf(" interrupt link = 0x%08X%08X\n", - dump.ilink[0], dump.ilink[1]); - printf(" time = %u\n", dump.time); - - offset += sizeof (dump); - } - wpi_nic_unlock(sc); - /* Dump driver status (TX and RX rings) while we're here. */ - printf("driver status:\n"); - WPI_TXQ_LOCK(sc); - for (i = 0; i < WPI_DRV_NTXQUEUES; i++) { - struct wpi_tx_ring *ring = &sc->txq[i]; - printf(" tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n", - i, ring->qid, ring->cur, ring->queued); - } - WPI_TXQ_UNLOCK(sc); - printf(" rx ring: cur=%d\n", sc->rxq.cur); -} - -static void -wpi_intr(void *arg) -{ - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - uint32_t r1, r2; - - WPI_LOCK(sc); - - /* Disable interrupts. */ - WPI_WRITE(sc, WPI_INT_MASK, 0); - - r1 = WPI_READ(sc, WPI_INT); - - if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) - goto end; /* Hardware gone! */ - - r2 = WPI_READ(sc, WPI_FH_INT); - - DPRINTF(sc, WPI_DEBUG_INTR, "%s: reg1=0x%08x reg2=0x%08x\n", __func__, - r1, r2); - - if (r1 == 0 && r2 == 0) - goto done; /* Interrupt not for us. */ - - /* Acknowledge interrupts. */ - WPI_WRITE(sc, WPI_INT, r1); - WPI_WRITE(sc, WPI_FH_INT, r2); - - if (r1 & (WPI_INT_SW_ERR | WPI_INT_HW_ERR)) { - device_printf(sc->sc_dev, "fatal firmware error\n"); -#ifdef WPI_DEBUG - wpi_debug_registers(sc); -#endif - wpi_fatal_intr(sc); - DPRINTF(sc, WPI_DEBUG_HW, - "(%s)\n", (r1 & WPI_INT_SW_ERR) ? "(Software Error)" : - "(Hardware Error)"); - taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); - goto end; - } - - if ((r1 & (WPI_INT_FH_RX | WPI_INT_SW_RX)) || - (r2 & WPI_FH_INT_RX)) - wpi_notif_intr(sc); - - if (r1 & WPI_INT_ALIVE) - wakeup(sc); /* Firmware is alive. */ - - if (r1 & WPI_INT_WAKEUP) - wpi_wakeup_intr(sc); - -done: - /* Re-enable interrupts. */ - if (ifp->if_flags & IFF_UP) - WPI_WRITE(sc, WPI_INT_MASK, WPI_INT_MASK_DEF); - -end: WPI_UNLOCK(sc); -} - -static int -wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211_frame *wh; - struct wpi_tx_cmd *cmd; - struct wpi_tx_data *data; - struct wpi_tx_desc *desc; - struct wpi_tx_ring *ring; - struct mbuf *m1; - bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER]; - int error, i, hdrlen, nsegs, totlen, pad; - - WPI_TXQ_LOCK(sc); - - KASSERT(buf->size <= sizeof(buf->data), ("buffer overflow")); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - if (sc->txq_active == 0) { - /* wpi_stop() was called */ - error = ENETDOWN; - goto fail; - } - - wh = mtod(buf->m, struct ieee80211_frame *); - hdrlen = ieee80211_anyhdrsize(wh); - totlen = buf->m->m_pkthdr.len; - - if (hdrlen & 3) { - /* First segment length must be a multiple of 4. */ - pad = 4 - (hdrlen & 3); - } else - pad = 0; - - ring = &sc->txq[buf->ac]; - desc = &ring->desc[ring->cur]; - data = &ring->data[ring->cur]; - - /* Prepare TX firmware command. */ - cmd = &ring->cmd[ring->cur]; - cmd->code = buf->code; - cmd->flags = 0; - cmd->qid = ring->qid; - cmd->idx = ring->cur; - - memcpy(cmd->data, buf->data, buf->size); - - /* Save and trim IEEE802.11 header. */ - memcpy((uint8_t *)(cmd->data + buf->size), wh, hdrlen); - m_adj(buf->m, hdrlen); - - error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, buf->m, - segs, &nsegs, BUS_DMA_NOWAIT); - if (error != 0 && error != EFBIG) { - device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, error); - goto fail; - } - if (error != 0) { - /* Too many DMA segments, linearize mbuf. */ - m1 = m_collapse(buf->m, M_NOWAIT, WPI_MAX_SCATTER - 1); - if (m1 == NULL) { - device_printf(sc->sc_dev, - "%s: could not defrag mbuf\n", __func__); - error = ENOBUFS; - goto fail; - } - buf->m = m1; - - error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, - buf->m, segs, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, - error); - goto fail; - } - } - - KASSERT(nsegs < WPI_MAX_SCATTER, - ("too many DMA segments, nsegs (%d) should be less than %d", - nsegs, WPI_MAX_SCATTER)); - - data->m = buf->m; - data->ni = buf->ni; - - DPRINTF(sc, WPI_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n", - __func__, ring->qid, ring->cur, totlen, nsegs); - - /* Fill TX descriptor. */ - desc->nsegs = WPI_PAD32(totlen + pad) << 4 | (1 + nsegs); - /* First DMA segment is used by the TX command. */ - desc->segs[0].addr = htole32(data->cmd_paddr); - desc->segs[0].len = htole32(4 + buf->size + hdrlen + pad); - /* Other DMA segments are for data payload. */ - seg = &segs[0]; - for (i = 1; i <= nsegs; i++) { - desc->segs[i].addr = htole32(seg->ds_addr); - desc->segs[i].len = htole32(seg->ds_len); - seg++; - } - - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(ring->data_dmat, ring->cmd_dma.map, - BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - - /* Kick TX ring. */ - ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - sc->sc_update_tx_ring(sc, ring); - - if (ring->qid < WPI_CMD_QUEUE_NUM) { - /* Mark TX ring as full if we reach a certain threshold. */ - WPI_TXQ_STATE_LOCK(sc); - if (++ring->queued > WPI_TX_RING_HIMARK) { - sc->qfullmsk |= 1 << ring->qid; - - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - } - - callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); - WPI_TXQ_STATE_UNLOCK(sc); - } - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - WPI_TXQ_UNLOCK(sc); - - return 0; - -fail: m_freem(buf->m); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - - WPI_TXQ_UNLOCK(sc); - - return error; -} - -/* - * Construct the data packet for a transmit buffer. - */ -static int -wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) -{ - const struct ieee80211_txparam *tp; - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct wpi_node *wn = WPI_NODE(ni); - struct ieee80211_channel *chan; - struct ieee80211_frame *wh; - struct ieee80211_key *k = NULL; - struct wpi_buf tx_data; - struct wpi_cmd_data *tx = (struct wpi_cmd_data *)&tx_data.data; - uint32_t flags; - uint16_t qos; - uint8_t tid, type; - int ac, error, swcrypt, rate, ismcast, totlen; - - wh = mtod(m, struct ieee80211_frame *); - type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - - /* Select EDCA Access Category and TX ring for this frame. */ - if (IEEE80211_QOS_HAS_SEQ(wh)) { - qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; - tid = qos & IEEE80211_QOS_TID; - } else { - qos = 0; - tid = 0; - } - ac = M_WME_GETAC(m); - - chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? - ni->ni_chan : ic->ic_curchan; - tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; - - /* Choose a TX rate index. */ - if (type == IEEE80211_FC0_TYPE_MGT) - rate = tp->mgmtrate; - else if (ismcast) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else if (m->m_flags & M_EAPOL) - rate = tp->mgmtrate; - else { - /* XXX pass pktlen */ (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } + tx->rate = wpi_plcp_signal(rate); - /* Encrypt the frame if need be. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - /* Retrieve key for TX. */ - k = ieee80211_crypto_encap(ni, m); - if (k == NULL) { - error = ENOBUFS; - goto fail; - } - swcrypt = k->wk_flags & IEEE80211_KEY_SWCRYPT; - - /* 802.11 header may have moved. */ - wh = mtod(m, struct ieee80211_frame *); - } - totlen = m->m_pkthdr.len; - - if (ieee80211_radiotap_active_vap(vap)) { - struct wpi_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - if (k != NULL) - tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; - - ieee80211_radiotap_tx(vap, m); - } - - flags = 0; - if (!ismcast) { - /* Unicast frame, check if an ACK is expected. */ - if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != - IEEE80211_QOS_ACKPOLICY_NOACK) - flags |= WPI_TX_NEED_ACK; - } - - if (!IEEE80211_QOS_HAS_SEQ(wh)) - flags |= WPI_TX_AUTO_SEQ; - if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) - flags |= WPI_TX_MORE_FRAG; /* Cannot happen yet. */ - - /* Check if frame must be protected using RTS/CTS or CTS-to-self. */ - if (!ismcast) { - /* NB: Group frames are sent using CCK in 802.11b/g. */ - if (totlen + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) { - flags |= WPI_TX_NEED_RTS; - } else if ((ic->ic_flags & IEEE80211_F_USEPROT) && - WPI_RATE_IS_OFDM(rate)) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) - flags |= WPI_TX_NEED_CTS; - else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) - flags |= WPI_TX_NEED_RTS; - } - - if (flags & (WPI_TX_NEED_RTS | WPI_TX_NEED_CTS)) - flags |= WPI_TX_FULL_TXOP; - } - - memset(tx, 0, sizeof (struct wpi_cmd_data)); - if (type == IEEE80211_FC0_TYPE_MGT) { - uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - - /* Tell HW to set timestamp in probe responses. */ - if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) - flags |= WPI_TX_INSERT_TSTAMP; - if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ || - subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) - tx->timeout = htole16(3); - else - tx->timeout = htole16(2); - } - - if (ismcast || type != IEEE80211_FC0_TYPE_DATA) - tx->id = WPI_ID_BROADCAST; - else { - if (wn->id == WPI_ID_UNDEFINED) { - device_printf(sc->sc_dev, - "%s: undefined node id\n", __func__); - error = EINVAL; - goto fail; - } - - tx->id = wn->id; - } - - if (k != NULL && !swcrypt) { - switch (k->wk_cipher->ic_cipher) { - case IEEE80211_CIPHER_AES_CCM: - tx->security = WPI_CIPHER_CCMP; - break; - - default: - break; - } - - memcpy(tx->key, k->wk_key, k->wk_keylen); - } - - tx->len = htole16(totlen); - tx->flags = htole32(flags); - tx->plcp = rate2plcp(rate); - tx->tid = tid; - tx->lifetime = htole32(WPI_LIFETIME_INFINITE); - tx->ofdm_mask = 0xff; - tx->cck_mask = 0x0f; - tx->rts_ntries = 7; - tx->data_ntries = tp->maxretry; - - tx_data.ni = ni; - tx_data.m = m; - tx_data.size = sizeof(struct wpi_cmd_data); - tx_data.code = WPI_CMD_TX_DATA; - tx_data.ac = ac; - - return wpi_cmd2(sc, &tx_data); - -fail: m_freem(m); - return error; -} - -static int -wpi_tx_data_raw(struct wpi_softc *sc, struct mbuf *m, - struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_key *k = NULL; - struct ieee80211_frame *wh; - struct wpi_buf tx_data; - struct wpi_cmd_data *tx = (struct wpi_cmd_data *)&tx_data.data; - uint32_t flags; - uint8_t type; - int ac, rate, swcrypt, totlen; - - wh = mtod(m, struct ieee80211_frame *); - type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - - ac = params->ibp_pri & 3; - - /* Choose a TX rate index. */ - rate = params->ibp_rate0; - - flags = 0; - if (!IEEE80211_QOS_HAS_SEQ(wh)) - flags |= WPI_TX_AUTO_SEQ; - if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) - flags |= WPI_TX_NEED_ACK; - if (params->ibp_flags & IEEE80211_BPF_RTS) - flags |= WPI_TX_NEED_RTS; - if (params->ibp_flags & IEEE80211_BPF_CTS) - flags |= WPI_TX_NEED_CTS; - if (flags & (WPI_TX_NEED_RTS | WPI_TX_NEED_CTS)) - flags |= WPI_TX_FULL_TXOP; - - /* Encrypt the frame if need be. */ - if (params->ibp_flags & IEEE80211_BPF_CRYPTO) { - /* Retrieve key for TX. */ - k = ieee80211_crypto_encap(ni, m); - if (k == NULL) { - m_freem(m); - return ENOBUFS; - } - swcrypt = k->wk_flags & IEEE80211_KEY_SWCRYPT; - - /* 802.11 header may have moved. */ - wh = mtod(m, struct ieee80211_frame *); - } - totlen = m->m_pkthdr.len; - - if (ieee80211_radiotap_active_vap(vap)) { - struct wpi_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - if (params->ibp_flags & IEEE80211_BPF_CRYPTO) - tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; - - ieee80211_radiotap_tx(vap, m); - } - - memset(tx, 0, sizeof (struct wpi_cmd_data)); - if (type == IEEE80211_FC0_TYPE_MGT) { - uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - - /* Tell HW to set timestamp in probe responses. */ - if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) - flags |= WPI_TX_INSERT_TSTAMP; - if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ || - subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) - tx->timeout = htole16(3); - else - tx->timeout = htole16(2); - } - - if (k != NULL && !swcrypt) { - switch (k->wk_cipher->ic_cipher) { - case IEEE80211_CIPHER_AES_CCM: - tx->security = WPI_CIPHER_CCMP; - break; - - default: - break; - } - - memcpy(tx->key, k->wk_key, k->wk_keylen); - } - - tx->len = htole16(totlen); - tx->flags = htole32(flags); - tx->plcp = rate2plcp(rate); - tx->id = WPI_ID_BROADCAST; - tx->lifetime = htole32(WPI_LIFETIME_INFINITE); - tx->rts_ntries = params->ibp_try1; - tx->data_ntries = params->ibp_try0; - - tx_data.ni = ni; - tx_data.m = m; - tx_data.size = sizeof(struct wpi_cmd_data); - tx_data.code = WPI_CMD_TX_DATA; - tx_data.ac = ac; - - return wpi_cmd2(sc, &tx_data); -} - -static int -wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; - int error = 0; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ieee80211_free_node(ni); - m_freem(m); - return ENETDOWN; - } - - WPI_TX_LOCK(sc); - if (params == NULL) { - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - */ - error = wpi_tx_data(sc, m, ni); - } else { - /* - * Caller supplied explicit parameters to use in - * sending the frame. - */ - error = wpi_tx_data_raw(sc, m, ni, params); - } - WPI_TX_UNLOCK(sc); - - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - - return error; - } - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - return 0; -} - -/** - * Process data waiting to be sent on the IFNET output queue - */ -static void -wpi_start(struct ifnet *ifp) -{ - struct wpi_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - WPI_TX_LOCK(sc); - DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); - - for (;;) { - IF_LOCK(&ifp->if_snd); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - IF_UNLOCK(&ifp->if_snd); - break; - } - IF_UNLOCK(&ifp->if_snd); - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (wpi_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } - } - - DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); - WPI_TX_UNLOCK(sc); -} - -static void -wpi_start_task(void *arg0, int pending) -{ - struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - - wpi_start(ifp); -} - -static void -wpi_watchdog_rfkill(void *arg) -{ - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - DPRINTF(sc, WPI_DEBUG_WATCHDOG, "RFkill Watchdog: tick\n"); - - /* No need to lock firmware memory. */ - if ((wpi_prph_read(sc, WPI_APMG_RFKILL) & 0x1) == 0) { - /* Radio kill switch is still off. */ - callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill, - sc); - } else - ieee80211_runtask(ic, &sc->sc_radioon_task); -} - -static void -wpi_scan_timeout(void *arg) -{ - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if_printf(ifp, "scan timeout\n"); - taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); -} - -static void -wpi_tx_timeout(void *arg) -{ - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); -} - -static int -wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct wpi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (cmd) { - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - wpi_init(sc); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 && - vap != NULL) - ieee80211_stop(vap); - } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - wpi_stop(sc); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Send a command to the firmware. - */ -static int -wpi_cmd(struct wpi_softc *sc, int code, const void *buf, size_t size, - int async) -{ - struct wpi_tx_ring *ring = &sc->txq[WPI_CMD_QUEUE_NUM]; - struct wpi_tx_desc *desc; - struct wpi_tx_data *data; - struct wpi_tx_cmd *cmd; - struct mbuf *m; - bus_addr_t paddr; - int totlen, error; - - WPI_TXQ_LOCK(sc); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - if (sc->txq_active == 0) { - /* wpi_stop() was called */ - error = 0; - goto fail; - } - - if (async == 0) - WPI_LOCK_ASSERT(sc); - - DPRINTF(sc, WPI_DEBUG_CMD, "%s: cmd %s size %zu async %d\n", - __func__, wpi_cmd_str(code), size, async); - - desc = &ring->desc[ring->cur]; - data = &ring->data[ring->cur]; - totlen = 4 + size; - - if (size > sizeof cmd->data) { - /* Command is too large to fit in a descriptor. */ - if (totlen > MCLBYTES) { - error = EINVAL; - goto fail; - } - m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); - if (m == NULL) { - error = ENOMEM; - goto fail; - } - cmd = mtod(m, struct wpi_tx_cmd *); - error = bus_dmamap_load(ring->data_dmat, data->map, cmd, - totlen, wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); - if (error != 0) { - m_freem(m); - goto fail; - } - data->m = m; - } else { - cmd = &ring->cmd[ring->cur]; - paddr = data->cmd_paddr; - } - - cmd->code = code; - cmd->flags = 0; - cmd->qid = ring->qid; - cmd->idx = ring->cur; - memcpy(cmd->data, buf, size); - - desc->nsegs = 1 + (WPI_PAD32(size) << 4); - desc->segs[0].addr = htole32(paddr); - desc->segs[0].len = htole32(totlen); - - if (size > sizeof cmd->data) { - bus_dmamap_sync(ring->data_dmat, data->map, - BUS_DMASYNC_PREWRITE); - } else { - bus_dmamap_sync(ring->data_dmat, ring->cmd_dma.map, - BUS_DMASYNC_PREWRITE); - } - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - - /* Kick command ring. */ - ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - sc->sc_update_tx_ring(sc, ring); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - WPI_TXQ_UNLOCK(sc); - - if (async) - return 0; - - return mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); - -fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - - WPI_TXQ_UNLOCK(sc); - - return error; -} - -/* - * Configure HW multi-rate retries. - */ -static int -wpi_mrr_setup(struct wpi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct wpi_mrr_setup mrr; - int i, error; - - /* CCK rates (not used with 802.11a). */ - for (i = WPI_RIDX_CCK1; i <= WPI_RIDX_CCK11; i++) { - mrr.rates[i].flags = 0; - mrr.rates[i].plcp = wpi_ridx_to_plcp[i]; - /* Fallback to the immediate lower CCK rate (if any.) */ - mrr.rates[i].next = - (i == WPI_RIDX_CCK1) ? WPI_RIDX_CCK1 : i - 1; - /* Try twice at this rate before falling back to "next". */ - mrr.rates[i].ntries = WPI_NTRIES_DEFAULT; - } - /* OFDM rates (not used with 802.11b). */ - for (i = WPI_RIDX_OFDM6; i <= WPI_RIDX_OFDM54; i++) { - mrr.rates[i].flags = 0; - mrr.rates[i].plcp = wpi_ridx_to_plcp[i]; - /* Fallback to the immediate lower rate (if any.) */ - /* We allow fallback from OFDM/6 to CCK/2 in 11b/g mode. */ - mrr.rates[i].next = (i == WPI_RIDX_OFDM6) ? - ((ic->ic_curmode == IEEE80211_MODE_11A) ? - WPI_RIDX_OFDM6 : WPI_RIDX_CCK2) : - i - 1; - /* Try twice at this rate before falling back to "next". */ - mrr.rates[i].ntries = WPI_NTRIES_DEFAULT; - } - /* Setup MRR for control frames. */ - mrr.which = htole32(WPI_MRR_CTL); - error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not setup MRR for control frames\n"); - return error; - } - /* Setup MRR for data frames. */ - mrr.which = htole32(WPI_MRR_DATA); - error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not setup MRR for data frames\n"); - return error; - } - return 0; -} - -static int -wpi_add_node(struct wpi_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = ni->ni_ic; - struct wpi_vap *wvp = WPI_VAP(ni->ni_vap); - struct wpi_node *wn = WPI_NODE(ni); - struct wpi_node_info node; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - if (wn->id == WPI_ID_UNDEFINED) - return EINVAL; - - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr); - node.id = wn->id; - node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ? - wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1]; - node.action = htole32(WPI_ACTION_SET_RATE); - node.antenna = WPI_ANTENNA_BOTH; - - DPRINTF(sc, WPI_DEBUG_NODE, "%s: adding node %d (%s)\n", __func__, - wn->id, ether_sprintf(ni->ni_macaddr)); - - error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: wpi_cmd() call failed with error code %d\n", __func__, - error); - return error; - } - - if (wvp->wv_gtk != 0) { - error = wpi_set_global_keys(ni); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: error while setting global keys\n", __func__); - return ENXIO; - } - } - - return 0; -} - -/* - * Broadcast node is used to send group-addressed and management frames. - */ -static int -wpi_add_broadcast_node(struct wpi_softc *sc, int async) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct wpi_node_info node; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr); - node.id = WPI_ID_BROADCAST; - node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ? - wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1]; - node.action = htole32(WPI_ACTION_SET_RATE); - node.antenna = WPI_ANTENNA_BOTH; - - DPRINTF(sc, WPI_DEBUG_NODE, "%s: adding broadcast node\n", __func__); - - return wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, async); -} - -static int -wpi_add_sta_node(struct wpi_softc *sc, struct ieee80211_node *ni) -{ - struct wpi_node *wn = WPI_NODE(ni); - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - wn->id = wpi_add_node_entry_sta(sc); - - if ((error = wpi_add_node(sc, ni)) != 0) { - wpi_del_node_entry(sc, wn->id); - wn->id = WPI_ID_UNDEFINED; - return error; - } - - return 0; -} - -static int -wpi_add_ibss_node(struct wpi_softc *sc, struct ieee80211_node *ni) -{ - struct wpi_node *wn = WPI_NODE(ni); - int error; - - KASSERT(wn->id == WPI_ID_UNDEFINED, - ("the node %d was added before", wn->id)); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - if ((wn->id = wpi_add_node_entry_adhoc(sc)) == WPI_ID_UNDEFINED) { - device_printf(sc->sc_dev, "%s: h/w table is full\n", __func__); - return ENOMEM; - } - - if ((error = wpi_add_node(sc, ni)) != 0) { - wpi_del_node_entry(sc, wn->id); - wn->id = WPI_ID_UNDEFINED; - return error; - } - - return 0; -} - -static void -wpi_del_node(struct wpi_softc *sc, struct ieee80211_node *ni) -{ - struct wpi_node *wn = WPI_NODE(ni); - struct wpi_cmd_del_node node; - int error; - - KASSERT(wn->id != WPI_ID_UNDEFINED, ("undefined node id passed")); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr); - node.count = 1; - - DPRINTF(sc, WPI_DEBUG_NODE, "%s: deleting node %d (%s)\n", __func__, - wn->id, ether_sprintf(ni->ni_macaddr)); - - error = wpi_cmd(sc, WPI_CMD_DEL_NODE, &node, sizeof node, 1); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not delete node %u, error %d\n", __func__, - wn->id, error); - } -} - -static int -wpi_updateedca(struct ieee80211com *ic) -{ -#define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ - struct wpi_softc *sc = ic->ic_ifp->if_softc; - struct wpi_edca_params cmd; - int aci, error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - memset(&cmd, 0, sizeof cmd); - cmd.flags = htole32(WPI_EDCA_UPDATE); - for (aci = 0; aci < WME_NUM_AC; aci++) { - const struct wmeParams *ac = - &ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; - cmd.ac[aci].aifsn = ac->wmep_aifsn; - cmd.ac[aci].cwmin = htole16(WPI_EXP2(ac->wmep_logcwmin)); - cmd.ac[aci].cwmax = htole16(WPI_EXP2(ac->wmep_logcwmax)); - cmd.ac[aci].txoplimit = - htole16(IEEE80211_TXOP_TO_US(ac->wmep_txopLimit)); - - DPRINTF(sc, WPI_DEBUG_EDCA, - "setting WME for queue %d aifsn=%d cwmin=%d cwmax=%d " - "txoplimit=%d\n", aci, cmd.ac[aci].aifsn, - cmd.ac[aci].cwmin, cmd.ac[aci].cwmax, - cmd.ac[aci].txoplimit); - } - error = wpi_cmd(sc, WPI_CMD_EDCA_PARAMS, &cmd, sizeof cmd, 1); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - return error; -#undef WPI_EXP2 -} - -static void -wpi_set_promisc(struct wpi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t promisc_filter; - - promisc_filter = WPI_FILTER_CTL; - if (vap != NULL && vap->iv_opmode != IEEE80211_M_HOSTAP) - promisc_filter |= WPI_FILTER_PROMISC; - - if (ifp->if_flags & IFF_PROMISC) - sc->rxon.filter |= htole32(promisc_filter); - else - sc->rxon.filter &= ~htole32(promisc_filter); -} - -static void -wpi_update_promisc(struct ifnet *ifp) -{ - struct wpi_softc *sc = ifp->if_softc; - - WPI_RXON_LOCK(sc); - wpi_set_promisc(sc); - - if (wpi_send_rxon(sc, 1, 1) != 0) { - device_printf(sc->sc_dev, "%s: could not send RXON\n", - __func__); - } - WPI_RXON_UNLOCK(sc); -} - -static void -wpi_update_mcast(struct ifnet *ifp) -{ - /* Ignore */ -} - -static void -wpi_set_led(struct wpi_softc *sc, uint8_t which, uint8_t off, uint8_t on) -{ - struct wpi_cmd_led led; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - led.which = which; - led.unit = htole32(100000); /* on/off in unit of 100ms */ - led.off = off; - led.on = on; - (void)wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof led, 1); -} - -static int -wpi_set_timing(struct wpi_softc *sc, struct ieee80211_node *ni) -{ - struct wpi_cmd_timing cmd; - uint64_t val, mod; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - memset(&cmd, 0, sizeof cmd); - memcpy(&cmd.tstamp, ni->ni_tstamp.data, sizeof (uint64_t)); - cmd.bintval = htole16(ni->ni_intval); - cmd.lintval = htole16(10); - - /* Compute remaining time until next beacon. */ - val = (uint64_t)ni->ni_intval * IEEE80211_DUR_TU; - mod = le64toh(cmd.tstamp) % val; - cmd.binitval = htole32((uint32_t)(val - mod)); - - DPRINTF(sc, WPI_DEBUG_RESET, "timing bintval=%u tstamp=%ju, init=%u\n", - ni->ni_intval, le64toh(cmd.tstamp), (uint32_t)(val - mod)); - - return wpi_cmd(sc, WPI_CMD_TIMING, &cmd, sizeof cmd, 1); -} - -/* - * This function is called periodically (every 60 seconds) to adjust output - * power to temperature changes. - */ -static void -wpi_power_calibration(struct wpi_softc *sc) -{ - int temp; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - /* Update sensor data. */ - temp = (int)WPI_READ(sc, WPI_UCODE_GP2); - DPRINTF(sc, WPI_DEBUG_TEMP, "Temp in calibration is: %d\n", temp); - - /* Sanity-check read value. */ - if (temp < -260 || temp > 25) { - /* This can't be correct, ignore. */ - DPRINTF(sc, WPI_DEBUG_TEMP, - "out-of-range temperature reported: %d\n", temp); - return; - } - - DPRINTF(sc, WPI_DEBUG_TEMP, "temperature %d->%d\n", sc->temp, temp); - - /* Adjust Tx power if need be. */ - if (abs(temp - sc->temp) <= 6) - return; - - sc->temp = temp; - - if (wpi_set_txpower(sc, 1) != 0) { - /* just warn, too bad for the automatic calibration... */ - device_printf(sc->sc_dev,"could not adjust Tx power\n"); - } -} - -/* - * Set TX power for current channel. - */ -static int -wpi_set_txpower(struct wpi_softc *sc, int async) -{ - struct wpi_power_group *group; - struct wpi_cmd_txpower cmd; - uint8_t chan; - int idx, is_chan_5ghz, i; - - /* Retrieve current channel from last RXON. */ - chan = sc->rxon.chan; - is_chan_5ghz = (sc->rxon.flags & htole32(WPI_RXON_24GHZ)) == 0; - - /* Find the TX power group to which this channel belongs. */ - if (is_chan_5ghz) { - for (group = &sc->groups[1]; group < &sc->groups[4]; group++) - if (chan <= group->chan) - break; - } else - group = &sc->groups[0]; - - memset(&cmd, 0, sizeof cmd); - cmd.band = is_chan_5ghz ? WPI_BAND_5GHZ : WPI_BAND_2GHZ; - cmd.chan = htole16(chan); - - /* Set TX power for all OFDM and CCK rates. */ - for (i = 0; i <= WPI_RIDX_MAX ; i++) { - /* Retrieve TX power for this channel/rate. */ - idx = wpi_get_power_index(sc, group, chan, is_chan_5ghz, i); - - cmd.rates[i].plcp = wpi_ridx_to_plcp[i]; - - if (is_chan_5ghz) { - cmd.rates[i].rf_gain = wpi_rf_gain_5ghz[idx]; - cmd.rates[i].dsp_gain = wpi_dsp_gain_5ghz[idx]; - } else { - cmd.rates[i].rf_gain = wpi_rf_gain_2ghz[idx]; - cmd.rates[i].dsp_gain = wpi_dsp_gain_2ghz[idx]; - } - DPRINTF(sc, WPI_DEBUG_TEMP, - "chan %d/ridx %d: power index %d\n", chan, i, idx); - } - - return wpi_cmd(sc, WPI_CMD_TXPOWER, &cmd, sizeof cmd, async); -} - -/* - * Determine Tx power index for a given channel/rate combination. - * This takes into account the regulatory information from EEPROM and the - * current temperature. - */ -static int -wpi_get_power_index(struct wpi_softc *sc, struct wpi_power_group *group, - uint8_t chan, int is_chan_5ghz, int ridx) -{ -/* Fixed-point arithmetic division using a n-bit fractional part. */ -#define fdivround(a, b, n) \ - ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n)) - -/* Linear interpolation. */ -#define interpolate(x, x1, y1, x2, y2, n) \ - ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n)) - - struct wpi_power_sample *sample; - int pwr, idx; - - /* Default TX power is group maximum TX power minus 3dB. */ - pwr = group->maxpwr / 2; - - /* Decrease TX power for highest OFDM rates to reduce distortion. */ - switch (ridx) { - case WPI_RIDX_OFDM36: - pwr -= is_chan_5ghz ? 5 : 0; - break; - case WPI_RIDX_OFDM48: - pwr -= is_chan_5ghz ? 10 : 7; - break; - case WPI_RIDX_OFDM54: - pwr -= is_chan_5ghz ? 12 : 9; - break; - } - - /* Never exceed the channel maximum allowed TX power. */ - pwr = min(pwr, sc->maxpwr[chan]); - - /* Retrieve TX power index into gain tables from samples. */ - for (sample = group->samples; sample < &group->samples[3]; sample++) - if (pwr > sample[1].power) - break; - /* Fixed-point linear interpolation using a 19-bit fractional part. */ - idx = interpolate(pwr, sample[0].power, sample[0].index, - sample[1].power, sample[1].index, 19); - - /*- - * Adjust power index based on current temperature: - * - if cooler than factory-calibrated: decrease output power - * - if warmer than factory-calibrated: increase output power - */ - idx -= (sc->temp - group->temp) * 11 / 100; - - /* Decrease TX power for CCK rates (-5dB). */ - if (ridx >= WPI_RIDX_CCK1) - idx += 10; - - /* Make sure idx stays in a valid range. */ - if (idx < 0) - return 0; - if (idx > WPI_MAX_PWR_INDEX) - return WPI_MAX_PWR_INDEX; - return idx; - -#undef interpolate -#undef fdivround -} - -/* - * Set STA mode power saving level (between 0 and 5). - * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving. - */ -static int -wpi_set_pslevel(struct wpi_softc *sc, uint8_t dtim, int level, int async) -{ - struct wpi_pmgt_cmd cmd; - const struct wpi_pmgt *pmgt; - uint32_t max, skip_dtim; - uint32_t reg; - int i; - - DPRINTF(sc, WPI_DEBUG_PWRSAVE, - "%s: dtim=%d, level=%d, async=%d\n", - __func__, dtim, level, async); - - /* Select which PS parameters to use. */ - if (dtim <= 10) - pmgt = &wpi_pmgt[0][level]; - else - pmgt = &wpi_pmgt[1][level]; - - memset(&cmd, 0, sizeof cmd); - WPI_TXQ_LOCK(sc); - if (level != 0) { /* not CAM */ - cmd.flags |= htole16(WPI_PS_ALLOW_SLEEP); - sc->sc_flags |= WPI_PS_PATH; - } else - sc->sc_flags &= ~WPI_PS_PATH; - WPI_TXQ_UNLOCK(sc); - /* Retrieve PCIe Active State Power Management (ASPM). */ - reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1); - if (!(reg & 0x1)) /* L0s Entry disabled. */ - cmd.flags |= htole16(WPI_PS_PCI_PMGT); - - cmd.rxtimeout = htole32(pmgt->rxtimeout * IEEE80211_DUR_TU); - cmd.txtimeout = htole32(pmgt->txtimeout * IEEE80211_DUR_TU); - - if (dtim == 0) { - dtim = 1; - skip_dtim = 0; - } else - skip_dtim = pmgt->skip_dtim; - - if (skip_dtim != 0) { - cmd.flags |= htole16(WPI_PS_SLEEP_OVER_DTIM); - max = pmgt->intval[4]; - if (max == (uint32_t)-1) - max = dtim * (skip_dtim + 1); - else if (max > dtim) - max = (max / dtim) * dtim; - } else - max = dtim; - - for (i = 0; i < 5; i++) - cmd.intval[i] = htole32(MIN(max, pmgt->intval[i])); - - return wpi_cmd(sc, WPI_CMD_SET_POWER_MODE, &cmd, sizeof cmd, async); -} - -static int -wpi_send_btcoex(struct wpi_softc *sc) -{ - struct wpi_bluetooth cmd; - - memset(&cmd, 0, sizeof cmd); - cmd.flags = WPI_BT_COEX_MODE_4WIRE; - cmd.lead_time = WPI_BT_LEAD_TIME_DEF; - cmd.max_kill = WPI_BT_MAX_KILL_DEF; - DPRINTF(sc, WPI_DEBUG_RESET, "%s: configuring bluetooth coexistence\n", - __func__); - return wpi_cmd(sc, WPI_CMD_BT_COEX, &cmd, sizeof(cmd), 0); -} - -static int -wpi_send_rxon(struct wpi_softc *sc, int assoc, int async) -{ - int error; - - if (async) - WPI_RXON_LOCK_ASSERT(sc); - - if (assoc && wpi_check_bss_filter(sc) != 0) { - struct wpi_assoc rxon_assoc; - - rxon_assoc.flags = sc->rxon.flags; - rxon_assoc.filter = sc->rxon.filter; - rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask; - rxon_assoc.cck_mask = sc->rxon.cck_mask; - rxon_assoc.reserved = 0; - - error = wpi_cmd(sc, WPI_CMD_RXON_ASSOC, &rxon_assoc, - sizeof (struct wpi_assoc), async); - if (error != 0) { - device_printf(sc->sc_dev, - "RXON_ASSOC command failed, error %d\n", error); - return error; - } - } else { - if (async) { - WPI_NT_LOCK(sc); - error = wpi_cmd(sc, WPI_CMD_RXON, &sc->rxon, - sizeof (struct wpi_rxon), async); - if (error == 0) - wpi_clear_node_table(sc); - WPI_NT_UNLOCK(sc); - } else { - error = wpi_cmd(sc, WPI_CMD_RXON, &sc->rxon, - sizeof (struct wpi_rxon), async); - if (error == 0) - wpi_clear_node_table(sc); - } - - if (error != 0) { - device_printf(sc->sc_dev, - "RXON command failed, error %d\n", error); - return error; - } - - /* Add broadcast node. */ - error = wpi_add_broadcast_node(sc, async); - if (error != 0) { - device_printf(sc->sc_dev, - "could not add broadcast node, error %d\n", error); - return error; - } - } - - /* Configuration has changed, set Tx power accordingly. */ - if ((error = wpi_set_txpower(sc, async)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set TX power, error %d\n", __func__, error); - return error; - } - - return 0; -} - -/** - * Configure the card to listen to a particular channel, this transisions the - * card in to being able to receive frames from remote devices. - */ -static int -wpi_config(struct wpi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_channel *c = ic->ic_curchan; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - /* Set power saving level to CAM during initialization. */ - if ((error = wpi_set_pslevel(sc, 0, 0, 0)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set power saving level\n", __func__); - return error; - } - - /* Configure bluetooth coexistence. */ - if ((error = wpi_send_btcoex(sc)) != 0) { - device_printf(sc->sc_dev, - "could not configure bluetooth coexistence\n"); - return error; - } - - /* Configure adapter. */ - memset(&sc->rxon, 0, sizeof (struct wpi_rxon)); - IEEE80211_ADDR_COPY(sc->rxon.myaddr, vap->iv_myaddr); + /* be very persistant at sending frames out */ +#if 0 + tx->data_ntries = tp->maxretry; +#else + tx->data_ntries = 15; /* XXX way too high */ +#endif - /* Set default channel. */ - sc->rxon.chan = ieee80211_chan2ieee(ic, c); - sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(c)) - sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); + if (ieee80211_radiotap_active_vap(vap)) { + struct wpi_tx_radiotap_header *tap = &sc->sc_txtap; + tap->wt_flags = 0; + tap->wt_rate = rate; + tap->wt_hwqueue = ac; + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) + tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; - sc->rxon.filter = WPI_FILTER_MULTICAST; - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - sc->rxon.mode = WPI_MODE_STA; - break; - case IEEE80211_M_IBSS: - sc->rxon.mode = WPI_MODE_IBSS; - sc->rxon.filter |= WPI_FILTER_BEACON; - break; - case IEEE80211_M_HOSTAP: - /* XXX workaround for beaconing */ - sc->rxon.mode = WPI_MODE_IBSS; - sc->rxon.filter |= WPI_FILTER_ASSOC | WPI_FILTER_PROMISC; - break; - case IEEE80211_M_AHDEMO: - sc->rxon.mode = WPI_MODE_HOSTAP; - break; - case IEEE80211_M_MONITOR: - sc->rxon.mode = WPI_MODE_MONITOR; - break; - default: - device_printf(sc->sc_dev, "unknown opmode %d\n", - ic->ic_opmode); - return EINVAL; + ieee80211_radiotap_tx(vap, m0); } - sc->rxon.filter = htole32(sc->rxon.filter); - wpi_set_promisc(sc); - sc->rxon.cck_mask = 0x0f; /* not yet negotiated */ - sc->rxon.ofdm_mask = 0xff; /* not yet negotiated */ - /* XXX Current configuration may be unusable. */ - if (IEEE80211_IS_CHAN_NOADHOC(c) && sc->rxon.mode == WPI_MODE_IBSS) { - device_printf(sc->sc_dev, - "%s: invalid channel (%d) selected for IBSS mode\n", - __func__, ieee80211_chan2ieee(ic, c)); - return EINVAL; - } + /* save and trim IEEE802.11 header */ + m_copydata(m0, 0, hdrlen, (caddr_t)&tx->wh); + m_adj(m0, hdrlen); - if ((error = wpi_send_rxon(sc, 0, 0)) != 0) { - device_printf(sc->sc_dev, "%s: could not send RXON\n", - __func__); + error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m0, segs, + &nsegs, BUS_DMA_NOWAIT); + if (error != 0 && error != EFBIG) { + device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", + error); + m_freem(m0); return error; } + if (error != 0) { + /* XXX use m_collapse */ + mnew = m_defrag(m0, M_NOWAIT); + if (mnew == NULL) { + device_printf(sc->sc_dev, + "could not defragment mbuf\n"); + m_freem(m0); + return ENOBUFS; + } + m0 = mnew; - /* Setup rate scalling. */ - if ((error = wpi_mrr_setup(sc)) != 0) { - device_printf(sc->sc_dev, "could not setup MRR, error %d\n", - error); - return error; + error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, + m0, segs, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, + "could not map mbuf (error %d)\n", error); + m_freem(m0); + return error; + } } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + data->m = m0; + data->ni = ni; - return 0; -} + DPRINTFN(WPI_DEBUG_TX, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n", + ring->qid, ring->cur, m0->m_pkthdr.len, nsegs)); -static uint16_t -wpi_get_active_dwell_time(struct wpi_softc *sc, - struct ieee80211_channel *c, uint8_t n_probes) -{ - /* No channel? Default to 2GHz settings. */ - if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) { - return (WPI_ACTIVE_DWELL_TIME_2GHZ + - WPI_ACTIVE_DWELL_FACTOR_2GHZ * (n_probes + 1)); + /* first scatter/gather segment is used by the tx data command */ + desc->flags = htole32(WPI_PAD32(m0->m_pkthdr.len) << 28 | + (1 + nsegs) << 24); + desc->segs[0].addr = htole32(ring->cmd_dma.paddr + + ring->cur * sizeof (struct wpi_tx_cmd)); + desc->segs[0].len = htole32(4 + sizeof (struct wpi_cmd_data)); + for (i = 1; i <= nsegs; i++) { + desc->segs[i].addr = htole32(segs[i - 1].ds_addr); + desc->segs[i].len = htole32(segs[i - 1].ds_len); } - /* 5GHz dwell time. */ - return (WPI_ACTIVE_DWELL_TIME_5GHZ + - WPI_ACTIVE_DWELL_FACTOR_5GHZ * (n_probes + 1)); -} - -/* - * Limit the total dwell time. - * - * Returns the dwell time in milliseconds. - */ -static uint16_t -wpi_limit_dwell(struct wpi_softc *sc, uint16_t dwell_time) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - int bintval = 0; + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, + BUS_DMASYNC_PREWRITE); - /* bintval is in TU (1.024mS) */ - if (vap != NULL) - bintval = vap->iv_bss->ni_intval; + ring->queued++; - /* - * If it's non-zero, we should calculate the minimum of - * it and the DWELL_BASE. - * - * XXX Yes, the math should take into account that bintval - * is 1.024mS, not 1mS.. - */ - if (bintval > 0) { - DPRINTF(sc, WPI_DEBUG_SCAN, "%s: bintval=%d\n", __func__, - bintval); - return (MIN(dwell_time, bintval - WPI_CHANNEL_TUNE_TIME * 2)); - } + /* kick ring */ + ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; + WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); - /* No association context? Default. */ - return dwell_time; + return 0; } -static uint16_t -wpi_get_passive_dwell_time(struct wpi_softc *sc, struct ieee80211_channel *c) +/** + * Process data waiting to be sent on the IFNET output queue + */ +static void +wpi_start(struct ifnet *ifp) { - uint16_t passive; - - if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) - passive = WPI_PASSIVE_DWELL_BASE + WPI_PASSIVE_DWELL_TIME_2GHZ; - else - passive = WPI_PASSIVE_DWELL_BASE + WPI_PASSIVE_DWELL_TIME_5GHZ; + struct wpi_softc *sc = ifp->if_softc; - /* Clamp to the beacon interval if we're associated. */ - return (wpi_limit_dwell(sc, passive)); + WPI_LOCK(sc); + wpi_start_locked(ifp); + WPI_UNLOCK(sc); } -static uint32_t -wpi_get_scan_pause_time(uint32_t time, uint16_t bintval) +static void +wpi_start_locked(struct ifnet *ifp) { - uint32_t mod = (time % bintval) * IEEE80211_DUR_TU; - uint32_t nbeacons = time / bintval; + struct wpi_softc *sc = ifp->if_softc; + struct ieee80211_node *ni; + struct mbuf *m; + int ac; + + WPI_LOCK_ASSERT(sc); - if (mod > WPI_PAUSE_MAX_TIME) - mod = WPI_PAUSE_MAX_TIME; + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; - return WPI_PAUSE_SCAN(nbeacons, mod); + for (;;) { + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + break; + ac = M_WME_GETAC(m); + if (sc->txq[ac].queued > sc->txq[ac].count - 8) { + /* there is no place left in this ring */ + IFQ_DRV_PREPEND(&ifp->if_snd, m); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + break; + } + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + if (wpi_tx_data(sc, m, ni, ac) != 0) { + ieee80211_free_node(ni); + ifp->if_oerrors++; + break; + } + sc->sc_tx_timer = 5; + } } -/* - * Send a scan request to the firmware. - */ static int -wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) +wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_scan_state *ss = ic->ic_scan; - struct ieee80211vap *vap = ss->ss_vap; - struct wpi_scan_hdr *hdr; - struct wpi_cmd_data *tx; - struct wpi_scan_essid *essids; - struct wpi_scan_chan *chan; - struct ieee80211_frame *wh; - struct ieee80211_rateset *rs; - uint16_t dwell_active, dwell_passive; - uint8_t *buf, *frm; - int bgscan, bintval, buflen, error, i, nssid; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - /* - * We are absolutely not allowed to send a scan command when another - * scan command is pending. - */ - if (callout_pending(&sc->scan_timeout)) { - device_printf(sc->sc_dev, "%s: called whilst scanning!\n", - __func__); - error = EAGAIN; - goto fail; - } - - bgscan = wpi_check_bss_filter(sc); - bintval = vap->iv_bss->ni_intval; - if (bgscan != 0 && - bintval < WPI_QUIET_TIME_DEFAULT + WPI_CHANNEL_TUNE_TIME * 2) { - error = EOPNOTSUPP; - goto fail; - } + struct ieee80211com *ic = ni->ni_ic; + struct ifnet *ifp = ic->ic_ifp; + struct wpi_softc *sc = ifp->if_softc; - buf = malloc(WPI_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO); - if (buf == NULL) { - device_printf(sc->sc_dev, - "%s: could not allocate buffer for scan command\n", - __func__); - error = ENOMEM; - goto fail; + /* prevent management frames from being sent if we're not ready */ + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + m_freem(m); + ieee80211_free_node(ni); + return ENETDOWN; } - hdr = (struct wpi_scan_hdr *)buf; - - /* - * Move to the next channel if no packets are received within 10 msecs - * after sending the probe request. - */ - hdr->quiet_time = htole16(WPI_QUIET_TIME_DEFAULT); - hdr->quiet_threshold = htole16(1); + WPI_LOCK(sc); - if (bgscan != 0) { - /* - * Max needs to be greater than active and passive and quiet! - * It's also in microseconds! - */ - hdr->max_svc = htole32(250 * IEEE80211_DUR_TU); - hdr->pause_svc = htole32(wpi_get_scan_pause_time(100, - bintval)); + /* management frames go into ring 0 */ + if (sc->txq[0].queued > sc->txq[0].count - 8) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + m_freem(m); + WPI_UNLOCK(sc); + ieee80211_free_node(ni); + return ENOBUFS; /* XXX */ } - hdr->filter = htole32(WPI_FILTER_MULTICAST | WPI_FILTER_BEACON); + ifp->if_opackets++; + if (wpi_tx_data(sc, m, ni, 0) != 0) + goto bad; + sc->sc_tx_timer = 5; + callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc); - tx = (struct wpi_cmd_data *)(hdr + 1); - tx->flags = htole32(WPI_TX_AUTO_SEQ); - tx->id = WPI_ID_BROADCAST; - tx->lifetime = htole32(WPI_LIFETIME_INFINITE); + WPI_UNLOCK(sc); + return 0; +bad: + ifp->if_oerrors++; + WPI_UNLOCK(sc); + ieee80211_free_node(ni); + return EIO; /* XXX */ +} - if (IEEE80211_IS_CHAN_5GHZ(c)) { - /* Send probe requests at 6Mbps. */ - tx->plcp = wpi_ridx_to_plcp[WPI_RIDX_OFDM6]; - rs = &ic->ic_sup_rates[IEEE80211_MODE_11A]; - } else { - hdr->flags = htole32(WPI_RXON_24GHZ | WPI_RXON_AUTO); - /* Send probe requests at 1Mbps. */ - tx->plcp = wpi_ridx_to_plcp[WPI_RIDX_CCK1]; - rs = &ic->ic_sup_rates[IEEE80211_MODE_11G]; - } +static int +wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct wpi_softc *sc = ifp->if_softc; + struct ieee80211com *ic = ifp->if_l2com; + struct ifreq *ifr = (struct ifreq *) data; + int error = 0, startall = 0; - essids = (struct wpi_scan_essid *)(tx + 1); - nssid = MIN(ss->ss_nssid, WPI_SCAN_MAX_ESSIDS); - for (i = 0; i < nssid; i++) { - essids[i].id = IEEE80211_ELEMID_SSID; - essids[i].len = MIN(ss->ss_ssid[i].len, IEEE80211_NWID_LEN); - memcpy(essids[i].data, ss->ss_ssid[i].ssid, essids[i].len); -#ifdef WPI_DEBUG - if (sc->sc_debug & WPI_DEBUG_SCAN) { - printf("Scanning Essid: "); - ieee80211_print_essid(essids[i].data, essids[i].len); - printf("\n"); - } -#endif + switch (cmd) { + case SIOCSIFFLAGS: + WPI_LOCK(sc); + if ((ifp->if_flags & IFF_UP)) { + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + wpi_init_locked(sc, 0); + startall = 1; + } + } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) || + (sc->flags & WPI_FLAG_HW_RADIO_OFF)) + wpi_stop_locked(sc); + WPI_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); + break; + case SIOCGIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); + break; + case SIOCGIFADDR: + error = ether_ioctl(ifp, cmd, data); + break; + default: + error = EINVAL; + break; } + return error; +} - /* - * Build a probe request frame. Most of the following code is a - * copy & paste of what is done in net80211. - */ - wh = (struct ieee80211_frame *)(essids + WPI_SCAN_MAX_ESSIDS); - wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | - IEEE80211_FC0_SUBTYPE_PROBE_REQ; - wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; - IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); - IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); - IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); - *(uint16_t *)&wh->i_dur[0] = 0; /* filled by h/w */ - *(uint16_t *)&wh->i_seq[0] = 0; /* filled by h/w */ - - frm = (uint8_t *)(wh + 1); - frm = ieee80211_add_ssid(frm, NULL, 0); - frm = ieee80211_add_rates(frm, rs); - if (rs->rs_nrates > IEEE80211_RATE_SIZE) - frm = ieee80211_add_xrates(frm, rs); - - /* Set length of probe request. */ - tx->len = htole16(frm - (uint8_t *)wh); - - /* - * Construct information about the channel that we - * want to scan. The firmware expects this to be directly - * after the scan probe request - */ - chan = (struct wpi_scan_chan *)frm; - chan->chan = htole16(ieee80211_chan2ieee(ic, c)); - chan->flags = 0; - if (nssid) { - hdr->crc_threshold = WPI_SCAN_CRC_TH_DEFAULT; - chan->flags |= WPI_CHAN_NPBREQS(nssid); - } else - hdr->crc_threshold = WPI_SCAN_CRC_TH_NEVER; - - if (!IEEE80211_IS_CHAN_PASSIVE(c)) - chan->flags |= WPI_CHAN_ACTIVE; - - /* - * Calculate the active/passive dwell times. - */ - - dwell_active = wpi_get_active_dwell_time(sc, c, nssid); - dwell_passive = wpi_get_passive_dwell_time(sc, c); - - /* Make sure they're valid. */ - if (dwell_active > dwell_passive) - dwell_active = dwell_passive; - - chan->active = htole16(dwell_active); - chan->passive = htole16(dwell_passive); - - chan->dsp_gain = 0x6e; /* Default level */ +/* + * Extract various information from EEPROM. + */ +static void +wpi_read_eeprom(struct wpi_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) +{ + int i; - if (IEEE80211_IS_CHAN_5GHZ(c)) - chan->rf_gain = 0x3b; - else - chan->rf_gain = 0x28; + /* read the hardware capabilities, revision and SKU type */ + wpi_read_prom_data(sc, WPI_EEPROM_CAPABILITIES, &sc->cap,1); + wpi_read_prom_data(sc, WPI_EEPROM_REVISION, &sc->rev,2); + wpi_read_prom_data(sc, WPI_EEPROM_TYPE, &sc->type, 1); - DPRINTF(sc, WPI_DEBUG_SCAN, "Scanning %u Passive: %d\n", - chan->chan, IEEE80211_IS_CHAN_PASSIVE(c)); + /* read the regulatory domain */ + wpi_read_prom_data(sc, WPI_EEPROM_DOMAIN, sc->domain, 4); - hdr->nchan++; + /* read in the hw MAC address */ + wpi_read_prom_data(sc, WPI_EEPROM_MAC, macaddr, 6); - if (hdr->nchan == 1 && sc->rxon.chan == chan->chan) { - /* XXX Force probe request transmission. */ - memcpy(chan + 1, chan, sizeof (struct wpi_scan_chan)); + /* read the list of authorized channels */ + for (i = 0; i < WPI_CHAN_BANDS_COUNT; i++) + wpi_read_eeprom_channels(sc,i); - chan++; + /* read the power level calibration info for each group */ + for (i = 0; i < WPI_POWER_GROUPS_COUNT; i++) + wpi_read_eeprom_group(sc,i); +} - /* Reduce unnecessary delay. */ - chan->flags = 0; - chan->passive = chan->active = hdr->quiet_time; +/* + * Send a command to the firmware. + */ +static int +wpi_cmd(struct wpi_softc *sc, int code, const void *buf, int size, int async) +{ + struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_desc *desc; + struct wpi_tx_cmd *cmd; - hdr->nchan++; +#ifdef WPI_DEBUG + if (!async) { + WPI_LOCK_ASSERT(sc); } +#endif - chan++; + DPRINTFN(WPI_DEBUG_CMD,("wpi_cmd %d size %d async %d\n", code, size, + async)); - buflen = (uint8_t *)chan - buf; - hdr->len = htole16(buflen); + if (sc->flags & WPI_FLAG_BUSY) { + device_printf(sc->sc_dev, "%s: cmd %d not sent, busy\n", + __func__, code); + return EAGAIN; + } + sc->flags|= WPI_FLAG_BUSY; - DPRINTF(sc, WPI_DEBUG_CMD, "sending scan command nchan=%d\n", - hdr->nchan); - error = wpi_cmd(sc, WPI_CMD_SCAN, buf, buflen, 1); - free(buf, M_DEVBUF); + KASSERT(size <= sizeof cmd->data, ("command %d too large: %d bytes", + code, size)); - if (error != 0) - goto fail; + desc = &ring->desc[ring->cur]; + cmd = &ring->cmd[ring->cur]; - callout_reset(&sc->scan_timeout, 5*hz, wpi_scan_timeout, sc); + cmd->code = code; + cmd->flags = 0; + cmd->qid = ring->qid; + cmd->idx = ring->cur; + memcpy(cmd->data, buf, size); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + desc->flags = htole32(WPI_PAD32(size) << 28 | 1 << 24); + desc->segs[0].addr = htole32(ring->cmd_dma.paddr + + ring->cur * sizeof (struct wpi_tx_cmd)); + desc->segs[0].len = htole32(4 + size); - return 0; + /* kick cmd ring */ + ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT; + WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); -fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); + if (async) { + sc->flags &= ~ WPI_FLAG_BUSY; + return 0; + } - return error; + return msleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); } static int -wpi_auth(struct wpi_softc *sc, struct ieee80211vap *vap) +wpi_wme_update(struct ieee80211com *ic) { - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_node *ni = vap->iv_bss; - struct ieee80211_channel *c = ni->ni_chan; - int error; - - WPI_RXON_LOCK(sc); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); +#define WPI_EXP2(v) htole16((1 << (v)) - 1) +#define WPI_USEC(v) htole16(IEEE80211_TXOP_TO_US(v)) + struct wpi_softc *sc = ic->ic_ifp->if_softc; + const struct wmeParams *wmep; + struct wpi_wme_setup wme; + int ac; - /* Update adapter configuration. */ - sc->rxon.associd = 0; - sc->rxon.filter &= ~htole32(WPI_FILTER_BSS); - IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid); - sc->rxon.chan = ieee80211_chan2ieee(ic, c); - sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(c)) - sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); - if (ic->ic_flags & IEEE80211_F_SHSLOT) - sc->rxon.flags |= htole32(WPI_RXON_SHSLOT); - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE); - if (IEEE80211_IS_CHAN_A(c)) { - sc->rxon.cck_mask = 0; - sc->rxon.ofdm_mask = 0x15; - } else if (IEEE80211_IS_CHAN_B(c)) { - sc->rxon.cck_mask = 0x03; - sc->rxon.ofdm_mask = 0; - } else { - /* Assume 802.11b/g. */ - sc->rxon.cck_mask = 0x0f; - sc->rxon.ofdm_mask = 0x15; - } + /* don't override default WME values if WME is not actually enabled */ + if (!(ic->ic_flags & IEEE80211_F_WME)) + return 0; - DPRINTF(sc, WPI_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n", - sc->rxon.chan, sc->rxon.flags, sc->rxon.cck_mask, - sc->rxon.ofdm_mask); + wme.flags = 0; + for (ac = 0; ac < WME_NUM_AC; ac++) { + wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; + wme.ac[ac].aifsn = wmep->wmep_aifsn; + wme.ac[ac].cwmin = WPI_EXP2(wmep->wmep_logcwmin); + wme.ac[ac].cwmax = WPI_EXP2(wmep->wmep_logcwmax); + wme.ac[ac].txop = WPI_USEC(wmep->wmep_txopLimit); - if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { - device_printf(sc->sc_dev, "%s: could not send RXON\n", - __func__); + DPRINTF(("setting WME for queue %d aifsn=%d cwmin=%d cwmax=%d " + "txop=%d\n", ac, wme.ac[ac].aifsn, wme.ac[ac].cwmin, + wme.ac[ac].cwmax, wme.ac[ac].txop)); } - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); - - WPI_RXON_UNLOCK(sc); - - return error; + return wpi_cmd(sc, WPI_CMD_SET_WME, &wme, sizeof wme, 1); +#undef WPI_USEC +#undef WPI_EXP2 } +/* + * Configure h/w multi-rate retries. + */ static int -wpi_config_beacon(struct wpi_vap *wvp) +wpi_mrr_setup(struct wpi_softc *sc) { - struct ieee80211com *ic = wvp->wv_vap.iv_ic; - struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; - struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct wpi_softc *sc = ic->ic_ifp->if_softc; - struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data; - struct ieee80211_tim_ie *tie; - struct mbuf *m; - uint8_t *ptr; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - WPI_VAP_LOCK_ASSERT(wvp); + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_mrr_setup mrr; + int i, error; - cmd->len = htole16(bcn->m->m_pkthdr.len); - cmd->plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ? - wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1]; + memset(&mrr, 0, sizeof (struct wpi_mrr_setup)); - /* XXX seems to be unused */ - if (*(bo->bo_tim) == IEEE80211_ELEMID_TIM) { - tie = (struct ieee80211_tim_ie *) bo->bo_tim; - ptr = mtod(bcn->m, uint8_t *); + /* CCK rates (not used with 802.11a) */ + for (i = WPI_CCK1; i <= WPI_CCK11; i++) { + mrr.rates[i].flags = 0; + mrr.rates[i].signal = wpi_ridx_to_plcp[i]; + /* fallback to the immediate lower CCK rate (if any) */ + mrr.rates[i].next = (i == WPI_CCK1) ? WPI_CCK1 : i - 1; + /* try one time at this rate before falling back to "next" */ + mrr.rates[i].ntries = 1; + } - cmd->tim = htole16(bo->bo_tim - ptr); - cmd->timsz = tie->tim_len; + /* OFDM rates (not used with 802.11b) */ + for (i = WPI_OFDM6; i <= WPI_OFDM54; i++) { + mrr.rates[i].flags = 0; + mrr.rates[i].signal = wpi_ridx_to_plcp[i]; + /* fallback to the immediate lower OFDM rate (if any) */ + /* we allow fallback from OFDM/6 to CCK/2 in 11b/g mode */ + mrr.rates[i].next = (i == WPI_OFDM6) ? + ((ic->ic_curmode == IEEE80211_MODE_11A) ? + WPI_OFDM6 : WPI_CCK2) : + i - 1; + /* try one time at this rate before falling back to "next" */ + mrr.rates[i].ntries = 1; } - /* Necessary for recursion in ieee80211_beacon_update(). */ - m = bcn->m; - bcn->m = m_dup(m, M_NOWAIT); - if (bcn->m == NULL) { + /* setup MRR for control frames */ + mrr.which = WPI_MRR_CTL; + error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0); + if (error != 0) { device_printf(sc->sc_dev, - "%s: could not copy beacon frame\n", __func__); - error = ENOMEM; - goto end; + "could not setup MRR for control frames\n"); + return error; } - if ((error = wpi_cmd2(sc, bcn)) != 0) { + /* setup MRR for data frames */ + mrr.which = WPI_MRR_DATA; + error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0); + if (error != 0) { device_printf(sc->sc_dev, - "%s: could not update beacon frame, error %d", __func__, - error); + "could not setup MRR for data frames\n"); + return error; } - /* Restore mbuf. */ -end: bcn->m = m; - - return error; + return 0; } -static int -wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni) +static void +wpi_set_led(struct wpi_softc *sc, uint8_t which, uint8_t off, uint8_t on) { - struct wpi_vap *wvp = WPI_VAP(ni->ni_vap); - struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; - struct mbuf *m; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + struct wpi_cmd_led led; - if (ni->ni_chan == IEEE80211_CHAN_ANYC) - return EINVAL; + led.which = which; + led.unit = htole32(100000); /* on/off in unit of 100ms */ + led.off = off; + led.on = on; - m = ieee80211_beacon_alloc(ni, bo); - if (m == NULL) { - device_printf(sc->sc_dev, - "%s: could not allocate beacon frame\n", __func__); - return ENOMEM; - } + (void)wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof led, 1); +} - WPI_VAP_LOCK(wvp); - if (bcn->m != NULL) - m_freem(bcn->m); +static void +wpi_enable_tsf(struct wpi_softc *sc, struct ieee80211_node *ni) +{ + struct wpi_cmd_tsf tsf; + uint64_t val, mod; - bcn->m = m; + memset(&tsf, 0, sizeof tsf); + memcpy(&tsf.tstamp, ni->ni_tstamp.data, 8); + tsf.bintval = htole16(ni->ni_intval); + tsf.lintval = htole16(10); - error = wpi_config_beacon(wvp); - WPI_VAP_UNLOCK(wvp); + /* compute remaining time until next beacon */ + val = (uint64_t)ni->ni_intval * 1024; /* msec -> usec */ + mod = le64toh(tsf.tstamp) % val; + tsf.binitval = htole32((uint32_t)(val - mod)); - return error; + if (wpi_cmd(sc, WPI_CMD_TSF, &tsf, sizeof tsf, 1) != 0) + device_printf(sc->sc_dev, "could not enable TSF\n"); } -static void -wpi_update_beacon(struct ieee80211vap *vap, int item) +#if 0 +/* + * Build a beacon frame that the firmware will broadcast periodically in + * IBSS or HostAP modes. + */ +static int +wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni) { - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; - struct wpi_vap *wvp = WPI_VAP(vap); - struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; - struct ieee80211_node *ni = vap->iv_bss; - int mcast = 0; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_desc *desc; + struct wpi_tx_data *data; + struct wpi_tx_cmd *cmd; + struct wpi_cmd_beacon *bcn; + struct ieee80211_beacon_offsets bo; + struct mbuf *m0; + bus_addr_t physaddr; + int error; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + desc = &ring->desc[ring->cur]; + data = &ring->data[ring->cur]; - WPI_VAP_LOCK(wvp); - if (bcn->m == NULL) { - bcn->m = ieee80211_beacon_alloc(ni, bo); - if (bcn->m == NULL) { - device_printf(sc->sc_dev, - "%s: could not allocate beacon frame\n", __func__); + m0 = ieee80211_beacon_alloc(ic, ni, &bo); + if (m0 == NULL) { + device_printf(sc->sc_dev, "could not allocate beacon frame\n"); + return ENOMEM; + } - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, - __func__); + cmd = &ring->cmd[ring->cur]; + cmd->code = WPI_CMD_SET_BEACON; + cmd->flags = 0; + cmd->qid = ring->qid; + cmd->idx = ring->cur; - WPI_VAP_UNLOCK(wvp); - return; - } + bcn = (struct wpi_cmd_beacon *)cmd->data; + memset(bcn, 0, sizeof (struct wpi_cmd_beacon)); + bcn->id = WPI_ID_BROADCAST; + bcn->ofdm_mask = 0xff; + bcn->cck_mask = 0x0f; + bcn->lifetime = htole32(WPI_LIFETIME_INFINITE); + bcn->len = htole16(m0->m_pkthdr.len); + bcn->rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? + wpi_plcp_signal(12) : wpi_plcp_signal(2); + bcn->flags = htole32(WPI_TX_AUTO_SEQ | WPI_TX_INSERT_TSTAMP); + + /* save and trim IEEE802.11 header */ + m_copydata(m0, 0, sizeof (struct ieee80211_frame), (caddr_t)&bcn->wh); + m_adj(m0, sizeof (struct ieee80211_frame)); + + /* assume beacon frame is contiguous */ + error = bus_dmamap_load(ring->data_dmat, data->map, mtod(m0, void *), + m0->m_pkthdr.len, wpi_dma_map_addr, &physaddr, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not map beacon\n"); + m_freem(m0); + return error; } - WPI_VAP_UNLOCK(wvp); - if (item == IEEE80211_BEACON_TIM) - mcast = 1; /* TODO */ + data->m = m0; - setbit(bo->bo_flags, item); - ieee80211_beacon_update(ni, bo, bcn->m, mcast); + /* first scatter/gather segment is used by the beacon command */ + desc->flags = htole32(WPI_PAD32(m0->m_pkthdr.len) << 28 | 2 << 24); + desc->segs[0].addr = htole32(ring->cmd_dma.paddr + + ring->cur * sizeof (struct wpi_tx_cmd)); + desc->segs[0].len = htole32(4 + sizeof (struct wpi_cmd_beacon)); + desc->segs[1].addr = htole32(physaddr); + desc->segs[1].len = htole32(m0->m_pkthdr.len); - WPI_VAP_LOCK(wvp); - wpi_config_beacon(wvp); - WPI_VAP_UNLOCK(wvp); + /* kick cmd ring */ + ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT; + WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + return 0; } +#endif -static void -wpi_newassoc(struct ieee80211_node *ni, int isnew) +static int +wpi_auth(struct wpi_softc *sc, struct ieee80211vap *vap) { - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni = vap->iv_bss; + struct wpi_node_info node; int error; - WPI_NT_LOCK(sc); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + /* update adapter's configuration */ + sc->config.associd = 0; + sc->config.filter &= ~htole32(WPI_FILTER_BSS); + IEEE80211_ADDR_COPY(sc->config.bssid, ni->ni_bssid); + sc->config.chan = ieee80211_chan2ieee(ic, ni->ni_chan); + if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { + sc->config.flags |= htole32(WPI_CONFIG_AUTO | + WPI_CONFIG_24GHZ); + } else { + sc->config.flags &= ~htole32(WPI_CONFIG_AUTO | + WPI_CONFIG_24GHZ); + } + if (IEEE80211_IS_CHAN_A(ni->ni_chan)) { + sc->config.cck_mask = 0; + sc->config.ofdm_mask = 0x15; + } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) { + sc->config.cck_mask = 0x03; + sc->config.ofdm_mask = 0; + } else { + /* XXX assume 802.11b/g */ + sc->config.cck_mask = 0x0f; + sc->config.ofdm_mask = 0x15; + } + + DPRINTF(("config chan %d flags %x cck %x ofdm %x\n", sc->config.chan, + sc->config.flags, sc->config.cck_mask, sc->config.ofdm_mask)); + error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config, + sizeof (struct wpi_config), 1); + if (error != 0) { + device_printf(sc->sc_dev, "could not configure\n"); + return error; + } - if (vap->iv_opmode != IEEE80211_M_STA && wn->id == WPI_ID_UNDEFINED) { - if ((error = wpi_add_ibss_node(sc, ni)) != 0) { - device_printf(sc->sc_dev, - "%s: could not add IBSS node, error %d\n", - __func__, error); - } + /* configuration has changed, set Tx power accordingly */ + if ((error = wpi_set_txpower(sc, ni->ni_chan, 1)) != 0) { + device_printf(sc->sc_dev, "could not set Tx power\n"); + return error; } - WPI_NT_UNLOCK(sc); + + /* add default node */ + memset(&node, 0, sizeof node); + IEEE80211_ADDR_COPY(node.bssid, ni->ni_bssid); + node.id = WPI_ID_BSS; + node.rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? + wpi_plcp_signal(12) : wpi_plcp_signal(2); + node.action = htole32(WPI_ACTION_SET_RATE); + node.antenna = WPI_ANTENNA_BOTH; + error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1); + if (error != 0) + device_printf(sc->sc_dev, "could not add BSS node\n"); + + return (error); } static int @@ -4467,1096 +2492,1054 @@ wpi_run(struct wpi_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni = vap->iv_bss; - struct ieee80211_channel *c = ni->ni_chan; int error; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (vap->iv_opmode == IEEE80211_M_MONITOR) { - /* Link LED blinks while monitoring. */ + /* link LED blinks while monitoring */ wpi_set_led(sc, WPI_LED_LINK, 5, 5); return 0; } - /* XXX kernel panic workaround */ - if (c == IEEE80211_CHAN_ANYC) { - device_printf(sc->sc_dev, "%s: incomplete configuration\n", - __func__); - return EINVAL; - } - - if ((error = wpi_set_timing(sc, ni)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set timing, error %d\n", __func__, error); - return error; - } + wpi_enable_tsf(sc, ni); - /* Update adapter configuration. */ - WPI_RXON_LOCK(sc); - IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid); - sc->rxon.associd = htole16(IEEE80211_NODE_AID(ni)); - sc->rxon.chan = ieee80211_chan2ieee(ic, c); - sc->rxon.flags = htole32(WPI_RXON_TSF | WPI_RXON_CTS_TO_SELF); - if (IEEE80211_IS_CHAN_2GHZ(c)) - sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ); + /* update adapter's configuration */ + sc->config.associd = htole16(ni->ni_associd & ~0xc000); + /* short preamble/slot time are negotiated when associating */ + sc->config.flags &= ~htole32(WPI_CONFIG_SHPREAMBLE | + WPI_CONFIG_SHSLOT); if (ic->ic_flags & IEEE80211_F_SHSLOT) - sc->rxon.flags |= htole32(WPI_RXON_SHSLOT); + sc->config.flags |= htole32(WPI_CONFIG_SHSLOT); if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE); - if (IEEE80211_IS_CHAN_A(c)) { - sc->rxon.cck_mask = 0; - sc->rxon.ofdm_mask = 0x15; - } else if (IEEE80211_IS_CHAN_B(c)) { - sc->rxon.cck_mask = 0x03; - sc->rxon.ofdm_mask = 0; - } else { - /* Assume 802.11b/g. */ - sc->rxon.cck_mask = 0x0f; - sc->rxon.ofdm_mask = 0x15; - } - sc->rxon.filter |= htole32(WPI_FILTER_BSS); + sc->config.flags |= htole32(WPI_CONFIG_SHPREAMBLE); + sc->config.filter |= htole32(WPI_FILTER_BSS); - DPRINTF(sc, WPI_DEBUG_STATE, "rxon chan %d flags %x\n", - sc->rxon.chan, sc->rxon.flags); + /* XXX put somewhere HC_QOS_SUPPORT_ASSOC + HC_IBSS_START */ - if ((error = wpi_send_rxon(sc, 0, 1)) != 0) { - device_printf(sc->sc_dev, "%s: could not send RXON\n", - __func__); + DPRINTF(("config chan %d flags %x\n", sc->config.chan, + sc->config.flags)); + error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config, sizeof (struct + wpi_config), 1); + if (error != 0) { + device_printf(sc->sc_dev, "could not update configuration\n"); return error; } - /* Start periodic calibration timer. */ - callout_reset(&sc->calib_to, 60*hz, wpi_calib_timeout, sc); - - WPI_RXON_UNLOCK(sc); - - if (vap->iv_opmode == IEEE80211_M_IBSS || - vap->iv_opmode == IEEE80211_M_HOSTAP) { - if ((error = wpi_setup_beacon(sc, ni)) != 0) { - device_printf(sc->sc_dev, - "%s: could not setup beacon, error %d\n", __func__, - error); - return error; - } - } - - if (vap->iv_opmode == IEEE80211_M_STA) { - /* Add BSS node. */ - WPI_NT_LOCK(sc); - error = wpi_add_sta_node(sc, ni); - WPI_NT_UNLOCK(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not add BSS node, error %d\n", __func__, - error); - return error; - } + error = wpi_set_txpower(sc, ni->ni_chan, 1); + if (error != 0) { + device_printf(sc->sc_dev, "could set txpower\n"); + return error; } - /* Link LED always on while associated. */ + /* link LED always on while associated */ wpi_set_led(sc, WPI_LED_LINK, 0, 1); - /* Enable power-saving mode if requested by user. */ - if ((vap->iv_flags & IEEE80211_F_PMGTON) && - vap->iv_opmode != IEEE80211_M_IBSS) - (void)wpi_set_pslevel(sc, 0, 3, 1); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + /* start automatic rate control timer */ + callout_reset(&sc->calib_to, 60*hz, wpi_calib_timeout, sc); - return 0; + return (error); } +/* + * Send a scan request to the firmware. Since this command is huge, we map it + * into a mbufcluster instead of using the pre-allocated set of commands. Note, + * much of this code is similar to that in wpi_cmd but because we must manually + * construct the probe & channels, we duplicate what's needed here. XXX In the + * future, this function should be modified to use wpi_cmd to help cleanup the + * code base. + */ static int -wpi_load_key(struct ieee80211_node *ni, const struct ieee80211_key *k) +wpi_scan(struct wpi_softc *sc) { - const struct ieee80211_cipher *cip = k->wk_cipher; - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); - struct wpi_node_info node; - uint16_t kflags; - int error; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211_scan_state *ss = ic->ic_scan; + struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_desc *desc; + struct wpi_tx_data *data; + struct wpi_tx_cmd *cmd; + struct wpi_scan_hdr *hdr; + struct wpi_scan_chan *chan; + struct ieee80211_frame *wh; + struct ieee80211_rateset *rs; + struct ieee80211_channel *c; + enum ieee80211_phymode mode; + uint8_t *frm; + int nrates, pktlen, error, i, nssid; + bus_addr_t physaddr; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + desc = &ring->desc[ring->cur]; + data = &ring->data[ring->cur]; - if (wpi_check_node_entry(sc, wn->id) == 0) { - device_printf(sc->sc_dev, "%s: node does not exist\n", - __func__); - return 0; + data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (data->m == NULL) { + device_printf(sc->sc_dev, + "could not allocate mbuf for scan command\n"); + return ENOMEM; } - switch (cip->ic_cipher) { - case IEEE80211_CIPHER_AES_CCM: - kflags = WPI_KFLAG_CCMP; - break; + cmd = mtod(data->m, struct wpi_tx_cmd *); + cmd->code = WPI_CMD_SCAN; + cmd->flags = 0; + cmd->qid = ring->qid; + cmd->idx = ring->cur; - default: - device_printf(sc->sc_dev, "%s: unknown cipher %d\n", __func__, - cip->ic_cipher); - return 0; - } + hdr = (struct wpi_scan_hdr *)cmd->data; + memset(hdr, 0, sizeof(struct wpi_scan_hdr)); - kflags |= WPI_KFLAG_KID(k->wk_keyix); - if (k->wk_flags & IEEE80211_KEY_GROUP) - kflags |= WPI_KFLAG_MULTICAST; + /* + * Move to the next channel if no packets are received within 5 msecs + * after sending the probe request (this helps to reduce the duration + * of active scans). + */ + hdr->quiet = htole16(5); + hdr->threshold = htole16(1); - memset(&node, 0, sizeof node); - node.id = wn->id; - node.control = WPI_NODE_UPDATE; - node.flags = WPI_FLAG_KEY_SET; - node.kflags = htole16(kflags); - memcpy(node.key, k->wk_key, k->wk_keylen); -again: - DPRINTF(sc, WPI_DEBUG_KEY, - "%s: setting %s key id %d for node %d (%s)\n", __func__, - (kflags & WPI_KFLAG_MULTICAST) ? "group" : "ucast", k->wk_keyix, - node.id, ether_sprintf(ni->ni_macaddr)); + if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) { + /* send probe requests at 6Mbps */ + hdr->tx.rate = wpi_ridx_to_plcp[WPI_OFDM6]; - error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1); - if (error != 0) { - device_printf(sc->sc_dev, "can't update node info, error %d\n", - error); - return !error; + /* Enable crc checking */ + hdr->promotion = htole16(1); + } else { + hdr->flags = htole32(WPI_CONFIG_24GHZ | WPI_CONFIG_AUTO); + /* send probe requests at 1Mbps */ + hdr->tx.rate = wpi_ridx_to_plcp[WPI_CCK1]; } + hdr->tx.id = WPI_ID_BROADCAST; + hdr->tx.lifetime = htole32(WPI_LIFETIME_INFINITE); + hdr->tx.flags = htole32(WPI_TX_AUTO_SEQ); - if (!(kflags & WPI_KFLAG_MULTICAST) && &vap->iv_nw_keys[0] <= k && - k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { - kflags |= WPI_KFLAG_MULTICAST; - node.kflags = htole16(kflags); - - goto again; + memset(hdr->scan_essids, 0, sizeof(hdr->scan_essids)); + nssid = MIN(ss->ss_nssid, WPI_SCAN_MAX_ESSIDS); + for (i = 0; i < nssid; i++) { + hdr->scan_essids[i].id = IEEE80211_ELEMID_SSID; + hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, 32); + memcpy(hdr->scan_essids[i].essid, ss->ss_ssid[i].ssid, + hdr->scan_essids[i].esslen); +#ifdef WPI_DEBUG + if (wpi_debug & WPI_DEBUG_SCANNING) { + printf("Scanning Essid: "); + ieee80211_print_essid(hdr->scan_essids[i].essid, + hdr->scan_essids[i].esslen); + printf("\n"); + } +#endif } - return 1; -} + /* + * Build a probe request frame. Most of the following code is a + * copy & paste of what is done in net80211. + */ + wh = (struct ieee80211_frame *)&hdr->scan_essids[4]; + wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | + IEEE80211_FC0_SUBTYPE_PROBE_REQ; + wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; + IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp)); + IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); + *(u_int16_t *)&wh->i_dur[0] = 0; /* filled by h/w */ + *(u_int16_t *)&wh->i_seq[0] = 0; /* filled by h/w */ -static void -wpi_load_key_cb(void *arg, struct ieee80211_node *ni) -{ - const struct ieee80211_key *k = arg; - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); - int error; + frm = (uint8_t *)(wh + 1); - if (vap->iv_bss == ni && wn->id == WPI_ID_UNDEFINED) - return; + /* add essid IE, the hardware will fill this in for us */ + *frm++ = IEEE80211_ELEMID_SSID; + *frm++ = 0; + + mode = ieee80211_chan2mode(ic->ic_curchan); + rs = &ic->ic_sup_rates[mode]; - WPI_NT_LOCK(sc); - error = wpi_load_key(ni, k); - WPI_NT_UNLOCK(sc); + /* add supported rates IE */ + *frm++ = IEEE80211_ELEMID_RATES; + nrates = rs->rs_nrates; + if (nrates > IEEE80211_RATE_SIZE) + nrates = IEEE80211_RATE_SIZE; + *frm++ = nrates; + memcpy(frm, rs->rs_rates, nrates); + frm += nrates; - if (error == 0) { - device_printf(sc->sc_dev, "%s: error while setting key\n", - __func__); + /* add supported xrates IE */ + if (rs->rs_nrates > IEEE80211_RATE_SIZE) { + nrates = rs->rs_nrates - IEEE80211_RATE_SIZE; + *frm++ = IEEE80211_ELEMID_XRATES; + *frm++ = nrates; + memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates); + frm += nrates; } -} -static int -wpi_set_global_keys(struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_key *wk = &vap->iv_nw_keys[0]; - int error = 1; + /* setup length of probe request */ + hdr->tx.len = htole16(frm - (uint8_t *)wh); - for (; wk < &vap->iv_nw_keys[IEEE80211_WEP_NKID] && error; wk++) - if (wk->wk_keyix != IEEE80211_KEYIX_NONE) - error = wpi_load_key(ni, wk); + /* + * Construct information about the channel that we + * want to scan. The firmware expects this to be directly + * after the scan probe request + */ + c = ic->ic_curchan; + chan = (struct wpi_scan_chan *)frm; + chan->chan = ieee80211_chan2ieee(ic, c); + chan->flags = 0; + if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) { + chan->flags |= WPI_CHAN_ACTIVE; + if (nssid != 0) + chan->flags |= WPI_CHAN_DIRECT; + } + chan->gain_dsp = 0x6e; /* Default level */ + if (IEEE80211_IS_CHAN_5GHZ(c)) { + chan->active = htole16(10); + chan->passive = htole16(ss->ss_maxdwell); + chan->gain_radio = 0x3b; + } else { + chan->active = htole16(20); + chan->passive = htole16(ss->ss_maxdwell); + chan->gain_radio = 0x28; + } - return !error; -} + DPRINTFN(WPI_DEBUG_SCANNING, + ("Scanning %u Passive: %d\n", + chan->chan, + c->ic_flags & IEEE80211_CHAN_PASSIVE)); -static int -wpi_del_key(struct ieee80211_node *ni, const struct ieee80211_key *k) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); - struct wpi_node_info node; - uint16_t kflags; - int error; + hdr->nchan++; + chan++; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + frm += sizeof (struct wpi_scan_chan); +#if 0 + // XXX All Channels.... + for (c = &ic->ic_channels[1]; + c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) { + if ((c->ic_flags & ic->ic_curchan->ic_flags) != ic->ic_curchan->ic_flags) + continue; - if (wpi_check_node_entry(sc, wn->id) == 0) { - DPRINTF(sc, WPI_DEBUG_KEY, "%s: node was removed\n", __func__); - return 1; /* Nothing to do. */ - } + chan->chan = ieee80211_chan2ieee(ic, c); + chan->flags = 0; + if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) { + chan->flags |= WPI_CHAN_ACTIVE; + if (ic->ic_des_ssid[0].len != 0) + chan->flags |= WPI_CHAN_DIRECT; + } + chan->gain_dsp = 0x6e; /* Default level */ + if (IEEE80211_IS_CHAN_5GHZ(c)) { + chan->active = htole16(10); + chan->passive = htole16(110); + chan->gain_radio = 0x3b; + } else { + chan->active = htole16(20); + chan->passive = htole16(120); + chan->gain_radio = 0x28; + } - kflags = WPI_KFLAG_KID(k->wk_keyix); - if (k->wk_flags & IEEE80211_KEY_GROUP) - kflags |= WPI_KFLAG_MULTICAST; + DPRINTFN(WPI_DEBUG_SCANNING, + ("Scanning %u Passive: %d\n", + chan->chan, + c->ic_flags & IEEE80211_CHAN_PASSIVE)); - memset(&node, 0, sizeof node); - node.id = wn->id; - node.control = WPI_NODE_UPDATE; - node.flags = WPI_FLAG_KEY_SET; - node.kflags = htole16(kflags); -again: - DPRINTF(sc, WPI_DEBUG_KEY, "%s: deleting %s key %d for node %d (%s)\n", - __func__, (kflags & WPI_KFLAG_MULTICAST) ? "group" : "ucast", - k->wk_keyix, node.id, ether_sprintf(ni->ni_macaddr)); + hdr->nchan++; + chan++; - error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1); - if (error != 0) { - device_printf(sc->sc_dev, "can't update node info, error %d\n", - error); - return !error; + frm += sizeof (struct wpi_scan_chan); } +#endif - if (!(kflags & WPI_KFLAG_MULTICAST) && &vap->iv_nw_keys[0] <= k && - k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { - kflags |= WPI_KFLAG_MULTICAST; - node.kflags = htole16(kflags); + hdr->len = htole16(frm - (uint8_t *)hdr); + pktlen = frm - (uint8_t *)cmd; - goto again; + error = bus_dmamap_load(ring->data_dmat, data->map, cmd, pktlen, + wpi_dma_map_addr, &physaddr, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, "could not map scan command\n"); + m_freem(data->m); + data->m = NULL; + return error; } - return 1; -} - -static void -wpi_del_key_cb(void *arg, struct ieee80211_node *ni) -{ - const struct ieee80211_key *k = arg; - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; - struct wpi_node *wn = WPI_NODE(ni); - int error; + desc->flags = htole32(WPI_PAD32(pktlen) << 28 | 1 << 24); + desc->segs[0].addr = htole32(physaddr); + desc->segs[0].len = htole32(pktlen); - if (vap->iv_bss == ni && wn->id == WPI_ID_UNDEFINED) - return; + bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); - WPI_NT_LOCK(sc); - error = wpi_del_key(ni, k); - WPI_NT_UNLOCK(sc); + /* kick cmd ring */ + ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT; + WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); - if (error == 0) { - device_printf(sc->sc_dev, "%s: error while deleting key\n", - __func__); - } + sc->sc_scan_timer = 5; + return 0; /* will be notified async. of failure/success */ } +/** + * Configure the card to listen to a particular channel, this transisions the + * card in to being able to receive frames from remote devices. + */ static int -wpi_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, - int set) +wpi_config(struct wpi_softc *sc) { - struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; - struct wpi_vap *wvp = WPI_VAP(vap); - struct ieee80211_node *ni; - int error, ni_ref = 0; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_power power; + struct wpi_bluetooth bluetooth; + struct wpi_node_info node; + int error; - if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { - /* Not for us. */ - return 1; + /* set power mode */ + memset(&power, 0, sizeof power); + power.flags = htole32(WPI_POWER_CAM|0x8); + error = wpi_cmd(sc, WPI_CMD_SET_POWER_MODE, &power, sizeof power, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not set power mode\n"); + return error; } - if (!(k->wk_flags & IEEE80211_KEY_RECV)) { - /* XMIT keys are handled in wpi_tx_data(). */ - return 1; + /* configure bluetooth coexistence */ + memset(&bluetooth, 0, sizeof bluetooth); + bluetooth.flags = 3; + bluetooth.lead = 0xaa; + bluetooth.kill = 1; + error = wpi_cmd(sc, WPI_CMD_BLUETOOTH, &bluetooth, sizeof bluetooth, + 0); + if (error != 0) { + device_printf(sc->sc_dev, + "could not configure bluetooth coexistence\n"); + return error; } - /* Handle group keys. */ - if (&vap->iv_nw_keys[0] <= k && - k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { - WPI_NT_LOCK(sc); - if (set) - wvp->wv_gtk |= WPI_VAP_KEY(k->wk_keyix); - else - wvp->wv_gtk &= ~WPI_VAP_KEY(k->wk_keyix); - WPI_NT_UNLOCK(sc); - - if (vap->iv_state == IEEE80211_S_RUN) { - ieee80211_iterate_nodes(&ic->ic_sta, - set ? wpi_load_key_cb : wpi_del_key_cb, - __DECONST(void *, k)); - } - - return 1; + /* configure adapter */ + memset(&sc->config, 0, sizeof (struct wpi_config)); + IEEE80211_ADDR_COPY(sc->config.myaddr, IF_LLADDR(ifp)); + /*set default channel*/ + sc->config.chan = htole16(ieee80211_chan2ieee(ic, ic->ic_curchan)); + sc->config.flags = htole32(WPI_CONFIG_TSF); + if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) { + sc->config.flags |= htole32(WPI_CONFIG_AUTO | + WPI_CONFIG_24GHZ); } - - switch (vap->iv_opmode) { + sc->config.filter = 0; + switch (ic->ic_opmode) { case IEEE80211_M_STA: - ni = vap->iv_bss; + case IEEE80211_M_WDS: /* No know setup, use STA for now */ + sc->config.mode = WPI_MODE_STA; + sc->config.filter |= htole32(WPI_FILTER_MULTICAST); break; - case IEEE80211_M_IBSS: case IEEE80211_M_AHDEMO: + sc->config.mode = WPI_MODE_IBSS; + sc->config.filter |= htole32(WPI_FILTER_BEACON | + WPI_FILTER_MULTICAST); + break; case IEEE80211_M_HOSTAP: - ni = ieee80211_find_vap_node(&ic->ic_sta, vap, k->wk_macaddr); - if (ni == NULL) - return 0; /* should not happen */ - - ni_ref = 1; + sc->config.mode = WPI_MODE_HOSTAP; + break; + case IEEE80211_M_MONITOR: + sc->config.mode = WPI_MODE_MONITOR; + sc->config.filter |= htole32(WPI_FILTER_MULTICAST | + WPI_FILTER_CTL | WPI_FILTER_PROMISC); break; - default: - device_printf(sc->sc_dev, "%s: unknown opmode %d\n", __func__, - vap->iv_opmode); - return 0; + device_printf(sc->sc_dev, "unknown opmode %d\n", ic->ic_opmode); + return EINVAL; + } + sc->config.cck_mask = 0x0f; /* not yet negotiated */ + sc->config.ofdm_mask = 0xff; /* not yet negotiated */ + error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config, + sizeof (struct wpi_config), 0); + if (error != 0) { + device_printf(sc->sc_dev, "configure command failed\n"); + return error; } - WPI_NT_LOCK(sc); - if (set) - error = wpi_load_key(ni, k); - else - error = wpi_del_key(ni, k); - WPI_NT_UNLOCK(sc); + /* configuration has changed, set Tx power accordingly */ + if ((error = wpi_set_txpower(sc, ic->ic_curchan, 0)) != 0) { + device_printf(sc->sc_dev, "could not set Tx power\n"); + return error; + } - if (ni_ref) - ieee80211_node_decref(ni); + /* add broadcast node */ + memset(&node, 0, sizeof node); + IEEE80211_ADDR_COPY(node.bssid, ifp->if_broadcastaddr); + node.id = WPI_ID_BROADCAST; + node.rate = wpi_plcp_signal(2); + error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not add broadcast node\n"); + return error; + } - return error; -} + /* Setup rate scalling */ + error = wpi_mrr_setup(sc); + if (error != 0) { + device_printf(sc->sc_dev, "could not setup MRR\n"); + return error; + } -static int -wpi_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - return wpi_process_key(vap, k, 1); + return 0; } -static int -wpi_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) +static void +wpi_stop_master(struct wpi_softc *sc) { - return wpi_process_key(vap, k, 0); -} + uint32_t tmp; + int ntries; -/* - * This function is called after the runtime firmware notifies us of its - * readiness (called in a process context). - */ -static int -wpi_post_alive(struct wpi_softc *sc) -{ - int ntries, error; + DPRINTFN(WPI_DEBUG_HW,("Disabling Firmware execution\n")); - /* Check (again) that the radio is not disabled. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; + tmp = WPI_READ(sc, WPI_RESET); + WPI_WRITE(sc, WPI_RESET, tmp | WPI_STOP_MASTER | WPI_NEVO_RESET); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + tmp = WPI_READ(sc, WPI_GPIO_CTL); + if ((tmp & WPI_GPIO_PWR_STATUS) == WPI_GPIO_PWR_SLEEP) + return; /* already asleep */ - /* NB: Runtime firmware must be up and running. */ - if (!(wpi_prph_read(sc, WPI_APMG_RFKILL) & 1)) { - device_printf(sc->sc_dev, - "RF switch: radio disabled (%s)\n", __func__); - wpi_nic_unlock(sc); - return EPERM; /* :-) */ + for (ntries = 0; ntries < 100; ntries++) { + if (WPI_READ(sc, WPI_RESET) & WPI_MASTER_DISABLED) + break; + DELAY(10); + } + if (ntries == 100) { + device_printf(sc->sc_dev, "timeout waiting for master\n"); } - wpi_nic_unlock(sc); +} - /* Wait for thermal sensor to calibrate. */ - for (ntries = 0; ntries < 1000; ntries++) { - if ((sc->temp = (int)WPI_READ(sc, WPI_UCODE_GP2)) != 0) +static int +wpi_power_up(struct wpi_softc *sc) +{ + uint32_t tmp; + int ntries; + + wpi_mem_lock(sc); + tmp = wpi_mem_read(sc, WPI_MEM_POWER); + wpi_mem_write(sc, WPI_MEM_POWER, tmp & ~0x03000000); + wpi_mem_unlock(sc); + + for (ntries = 0; ntries < 5000; ntries++) { + if (WPI_READ(sc, WPI_GPIO_STATUS) & WPI_POWERED) break; DELAY(10); } - - if (ntries == 1000) { + if (ntries == 5000) { device_printf(sc->sc_dev, - "timeout waiting for thermal sensor calibration\n"); + "timeout waiting for NIC to power up\n"); return ETIMEDOUT; } - - DPRINTF(sc, WPI_DEBUG_TEMP, "temperature %d\n", sc->temp); return 0; } -/* - * The firmware boot code is small and is intended to be copied directly into - * the NIC internal memory (no DMA transfer). - */ static int -wpi_load_bootcode(struct wpi_softc *sc, const uint8_t *ucode, int size) +wpi_reset(struct wpi_softc *sc) { - int error, ntries; - - DPRINTF(sc, WPI_DEBUG_HW, "Loading microcode size 0x%x\n", size); + uint32_t tmp; + int ntries; - size /= sizeof (uint32_t); + DPRINTFN(WPI_DEBUG_HW, + ("Resetting the card - clearing any uploaded firmware\n")); - if ((error = wpi_nic_lock(sc)) != 0) - return error; + /* clear any pending interrupts */ + WPI_WRITE(sc, WPI_INTR, 0xffffffff); - /* Copy microcode image into NIC memory. */ - wpi_prph_write_region_4(sc, WPI_BSM_SRAM_BASE, - (const uint32_t *)ucode, size); + tmp = WPI_READ(sc, WPI_PLL_CTL); + WPI_WRITE(sc, WPI_PLL_CTL, tmp | WPI_PLL_INIT); - wpi_prph_write(sc, WPI_BSM_WR_MEM_SRC, 0); - wpi_prph_write(sc, WPI_BSM_WR_MEM_DST, WPI_FW_TEXT_BASE); - wpi_prph_write(sc, WPI_BSM_WR_DWCOUNT, size); + tmp = WPI_READ(sc, WPI_CHICKEN); + WPI_WRITE(sc, WPI_CHICKEN, tmp | WPI_CHICKEN_RXNOLOS); - /* Start boot load now. */ - wpi_prph_write(sc, WPI_BSM_WR_CTRL, WPI_BSM_WR_CTRL_START); + tmp = WPI_READ(sc, WPI_GPIO_CTL); + WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_INIT); - /* Wait for transfer to complete. */ - for (ntries = 0; ntries < 1000; ntries++) { - uint32_t status = WPI_READ(sc, WPI_FH_TX_STATUS); - DPRINTF(sc, WPI_DEBUG_HW, - "firmware status=0x%x, val=0x%x, result=0x%x\n", status, - WPI_FH_TX_STATUS_IDLE(6), - status & WPI_FH_TX_STATUS_IDLE(6)); - if (status & WPI_FH_TX_STATUS_IDLE(6)) { - DPRINTF(sc, WPI_DEBUG_HW, - "Status Match! - ntries = %d\n", ntries); + /* wait for clock stabilization */ + for (ntries = 0; ntries < 25000; ntries++) { + if (WPI_READ(sc, WPI_GPIO_CTL) & WPI_GPIO_CLOCK) break; - } DELAY(10); } - if (ntries == 1000) { - device_printf(sc->sc_dev, "%s: could not load boot firmware\n", - __func__); - wpi_nic_unlock(sc); + if (ntries == 25000) { + device_printf(sc->sc_dev, + "timeout waiting for clock stabilization\n"); return ETIMEDOUT; } - /* Enable boot after power up. */ - wpi_prph_write(sc, WPI_BSM_WR_CTRL, WPI_BSM_WR_CTRL_START_EN); + /* initialize EEPROM */ + tmp = WPI_READ(sc, WPI_EEPROM_STATUS); + + if ((tmp & WPI_EEPROM_VERSION) == 0) { + device_printf(sc->sc_dev, "EEPROM not found\n"); + return EIO; + } + WPI_WRITE(sc, WPI_EEPROM_STATUS, tmp & ~WPI_EEPROM_LOCKED); - wpi_nic_unlock(sc); return 0; } -static int -wpi_load_firmware(struct wpi_softc *sc) +static void +wpi_hw_config(struct wpi_softc *sc) { - struct wpi_fw_info *fw = &sc->fw; - struct wpi_dma_info *dma = &sc->fw_dma; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - /* Copy initialization sections into pre-allocated DMA-safe memory. */ - memcpy(dma->vaddr, fw->init.data, fw->init.datasz); - bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); - memcpy(dma->vaddr + WPI_FW_DATA_MAXSZ, fw->init.text, fw->init.textsz); - bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); + uint32_t rev, hw; - /* Tell adapter where to find initialization sections. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; - wpi_prph_write(sc, WPI_BSM_DRAM_DATA_ADDR, dma->paddr); - wpi_prph_write(sc, WPI_BSM_DRAM_DATA_SIZE, fw->init.datasz); - wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_ADDR, - dma->paddr + WPI_FW_DATA_MAXSZ); - wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_SIZE, fw->init.textsz); - wpi_nic_unlock(sc); - - /* Load firmware boot code. */ - error = wpi_load_bootcode(sc, fw->boot.text, fw->boot.textsz); - if (error != 0) { - device_printf(sc->sc_dev, "%s: could not load boot firmware\n", - __func__); - return error; - } + /* voodoo from the Linux "driver".. */ + hw = WPI_READ(sc, WPI_HWCONFIG); - /* Now press "execute". */ - WPI_WRITE(sc, WPI_RESET, 0); + rev = pci_read_config(sc->sc_dev, PCIR_REVID, 1); + if ((rev & 0xc0) == 0x40) + hw |= WPI_HW_ALM_MB; + else if (!(rev & 0x80)) + hw |= WPI_HW_ALM_MM; - /* Wait at most one second for first alive notification. */ - if ((error = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) { - device_printf(sc->sc_dev, - "%s: timeout waiting for adapter to initialize, error %d\n", - __func__, error); - return error; - } + if (sc->cap == 0x80) + hw |= WPI_HW_SKU_MRC; - /* Copy runtime sections into pre-allocated DMA-safe memory. */ - memcpy(dma->vaddr, fw->main.data, fw->main.datasz); - bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); - memcpy(dma->vaddr + WPI_FW_DATA_MAXSZ, fw->main.text, fw->main.textsz); - bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE); + hw &= ~WPI_HW_REV_D; + if ((le16toh(sc->rev) & 0xf0) == 0xd0) + hw |= WPI_HW_REV_D; - /* Tell adapter where to find runtime sections. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; - wpi_prph_write(sc, WPI_BSM_DRAM_DATA_ADDR, dma->paddr); - wpi_prph_write(sc, WPI_BSM_DRAM_DATA_SIZE, fw->main.datasz); - wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_ADDR, - dma->paddr + WPI_FW_DATA_MAXSZ); - wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_SIZE, - WPI_FW_UPDATED | fw->main.textsz); - wpi_nic_unlock(sc); + if (sc->type > 1) + hw |= WPI_HW_TYPE_B; - return 0; + WPI_WRITE(sc, WPI_HWCONFIG, hw); } -static int -wpi_read_firmware(struct wpi_softc *sc) +static void +wpi_rfkill_resume(struct wpi_softc *sc) { - const struct firmware *fp; - struct wpi_fw_info *fw = &sc->fw; - const struct wpi_firmware_hdr *hdr; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - DPRINTF(sc, WPI_DEBUG_FIRMWARE, - "Attempting Loading Firmware from %s module\n", WPI_FW_NAME); + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + int ntries; - WPI_UNLOCK(sc); - fp = firmware_get(WPI_FW_NAME); - WPI_LOCK(sc); + /* enable firmware again */ + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF); + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD); - if (fp == NULL) { - device_printf(sc->sc_dev, - "could not load firmware image '%s'\n", WPI_FW_NAME); - return EINVAL; + /* wait for thermal sensors to calibrate */ + for (ntries = 0; ntries < 1000; ntries++) { + if ((sc->temp = (int)WPI_READ(sc, WPI_TEMPERATURE)) != 0) + break; + DELAY(10); } - sc->fw_fp = fp; - - if (fp->datasize < sizeof (struct wpi_firmware_hdr)) { + if (ntries == 1000) { device_printf(sc->sc_dev, - "firmware file too short: %zu bytes\n", fp->datasize); - error = EINVAL; - goto fail; + "timeout waiting for thermal calibration\n"); + return; } + DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp)); - fw->size = fp->datasize; - fw->data = (const uint8_t *)fp->data; - - /* Extract firmware header information. */ - hdr = (const struct wpi_firmware_hdr *)fw->data; + if (wpi_config(sc) != 0) { + device_printf(sc->sc_dev, "device config failed\n"); + return; + } - /* | RUNTIME FIRMWARE | INIT FIRMWARE | BOOT FW | - |HDR|<--TEXT-->|<--DATA-->|<--TEXT-->|<--DATA-->|<--TEXT-->| */ + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->flags &= ~WPI_FLAG_HW_RADIO_OFF; - fw->main.textsz = le32toh(hdr->rtextsz); - fw->main.datasz = le32toh(hdr->rdatasz); - fw->init.textsz = le32toh(hdr->itextsz); - fw->init.datasz = le32toh(hdr->idatasz); - fw->boot.textsz = le32toh(hdr->btextsz); - fw->boot.datasz = 0; - - /* Sanity-check firmware header. */ - if (fw->main.textsz > WPI_FW_TEXT_MAXSZ || - fw->main.datasz > WPI_FW_DATA_MAXSZ || - fw->init.textsz > WPI_FW_TEXT_MAXSZ || - fw->init.datasz > WPI_FW_DATA_MAXSZ || - fw->boot.textsz > WPI_FW_BOOT_TEXT_MAXSZ || - (fw->boot.textsz & 3) != 0) { - device_printf(sc->sc_dev, "invalid firmware header\n"); - error = EINVAL; - goto fail; + if (vap != NULL) { + if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + if (vap->iv_opmode != IEEE80211_M_MONITOR) { + ieee80211_beacon_miss(ic); + wpi_set_led(sc, WPI_LED_LINK, 0, 1); + } else + wpi_set_led(sc, WPI_LED_LINK, 5, 5); + } else { + ieee80211_scan_next(vap); + wpi_set_led(sc, WPI_LED_LINK, 20, 2); + } } - /* Check that all firmware sections fit. */ - if (fw->size < sizeof (*hdr) + fw->main.textsz + fw->main.datasz + - fw->init.textsz + fw->init.datasz + fw->boot.textsz) { - device_printf(sc->sc_dev, - "firmware file too short: %zu bytes\n", fw->size); - error = EINVAL; - goto fail; - } + callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc); +} - /* Get pointers to firmware sections. */ - fw->main.text = (const uint8_t *)(hdr + 1); - fw->main.data = fw->main.text + fw->main.textsz; - fw->init.text = fw->main.data + fw->main.datasz; - fw->init.data = fw->init.text + fw->init.textsz; - fw->boot.text = fw->init.data + fw->init.datasz; +static void +wpi_init_locked(struct wpi_softc *sc, int force) +{ + struct ifnet *ifp = sc->sc_ifp; + uint32_t tmp; + int ntries, qid; - DPRINTF(sc, WPI_DEBUG_FIRMWARE, - "Firmware Version: Major %d, Minor %d, Driver %d, \n" - "runtime (text: %u, data: %u) init (text: %u, data %u) " - "boot (text %u)\n", hdr->major, hdr->minor, le32toh(hdr->driver), - fw->main.textsz, fw->main.datasz, - fw->init.textsz, fw->init.datasz, fw->boot.textsz); + wpi_stop_locked(sc); + (void)wpi_reset(sc); - DPRINTF(sc, WPI_DEBUG_FIRMWARE, "fw->main.text %p\n", fw->main.text); - DPRINTF(sc, WPI_DEBUG_FIRMWARE, "fw->main.data %p\n", fw->main.data); - DPRINTF(sc, WPI_DEBUG_FIRMWARE, "fw->init.text %p\n", fw->init.text); - DPRINTF(sc, WPI_DEBUG_FIRMWARE, "fw->init.data %p\n", fw->init.data); - DPRINTF(sc, WPI_DEBUG_FIRMWARE, "fw->boot.text %p\n", fw->boot.text); + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_CLOCK1, 0xa00); + DELAY(20); + tmp = wpi_mem_read(sc, WPI_MEM_PCIDEV); + wpi_mem_write(sc, WPI_MEM_PCIDEV, tmp | 0x800); + wpi_mem_unlock(sc); - return 0; + (void)wpi_power_up(sc); + wpi_hw_config(sc); -fail: wpi_unload_firmware(sc); - return error; -} + /* init Rx ring */ + wpi_mem_lock(sc); + WPI_WRITE(sc, WPI_RX_BASE, sc->rxq.desc_dma.paddr); + WPI_WRITE(sc, WPI_RX_RIDX_PTR, sc->shared_dma.paddr + + offsetof(struct wpi_shared, next)); + WPI_WRITE(sc, WPI_RX_WIDX, (WPI_RX_RING_COUNT - 1) & ~7); + WPI_WRITE(sc, WPI_RX_CONFIG, 0xa9601010); + wpi_mem_unlock(sc); + + /* init Tx rings */ + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_MODE, 2); /* bypass mode */ + wpi_mem_write(sc, WPI_MEM_RA, 1); /* enable RA0 */ + wpi_mem_write(sc, WPI_MEM_TXCFG, 0x3f); /* enable all 6 Tx rings */ + wpi_mem_write(sc, WPI_MEM_BYPASS1, 0x10000); + wpi_mem_write(sc, WPI_MEM_BYPASS2, 0x30002); + wpi_mem_write(sc, WPI_MEM_MAGIC4, 4); + wpi_mem_write(sc, WPI_MEM_MAGIC5, 5); + + WPI_WRITE(sc, WPI_TX_BASE_PTR, sc->shared_dma.paddr); + WPI_WRITE(sc, WPI_MSG_CONFIG, 0xffff05a5); + + for (qid = 0; qid < 6; qid++) { + WPI_WRITE(sc, WPI_TX_CTL(qid), 0); + WPI_WRITE(sc, WPI_TX_BASE(qid), 0); + WPI_WRITE(sc, WPI_TX_CONFIG(qid), 0x80200008); + } + wpi_mem_unlock(sc); + + /* clear "radio off" and "disable command" bits (reversed logic) */ + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF); + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD); + sc->flags &= ~WPI_FLAG_HW_RADIO_OFF; + + /* clear any pending interrupts */ + WPI_WRITE(sc, WPI_INTR, 0xffffffff); + + /* enable interrupts */ + WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK); + + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF); + WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF); + + if ((wpi_load_firmware(sc)) != 0) { + device_printf(sc->sc_dev, + "A problem occurred loading the firmware to the driver\n"); + return; + } + + /* At this point the firmware is up and running. If the hardware + * RF switch is turned off thermal calibration will fail, though + * the card is still happy to continue to accept commands, catch + * this case and schedule a task to watch for it to be turned on. + */ + wpi_mem_lock(sc); + tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF); + wpi_mem_unlock(sc); -/** - * Free the referenced firmware image - */ -static void -wpi_unload_firmware(struct wpi_softc *sc) -{ - if (sc->fw_fp != NULL) { - firmware_put(sc->fw_fp, FIRMWARE_UNLOAD); - sc->fw_fp = NULL; + if (!(tmp & 0x1)) { + sc->flags |= WPI_FLAG_HW_RADIO_OFF; + device_printf(sc->sc_dev,"Radio Transmitter is switched off\n"); + goto out; } -} -static int -wpi_clock_wait(struct wpi_softc *sc) -{ - int ntries; + /* wait for thermal sensors to calibrate */ + for (ntries = 0; ntries < 1000; ntries++) { + if ((sc->temp = (int)WPI_READ(sc, WPI_TEMPERATURE)) != 0) + break; + DELAY(10); + } - /* Set "initialization complete" bit. */ - WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_INIT_DONE); + if (ntries == 1000) { + device_printf(sc->sc_dev, + "timeout waiting for thermal sensors calibration\n"); + return; + } + DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp)); - /* Wait for clock stabilization. */ - for (ntries = 0; ntries < 2500; ntries++) { - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_MAC_CLOCK_READY) - return 0; - DELAY(100); + if (wpi_config(sc) != 0) { + device_printf(sc->sc_dev, "device config failed\n"); + return; } - device_printf(sc->sc_dev, - "%s: timeout waiting for clock stabilization\n", __func__); - return ETIMEDOUT; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + ifp->if_drv_flags |= IFF_DRV_RUNNING; +out: + callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc); } -static int -wpi_apm_init(struct wpi_softc *sc) +static void +wpi_init(void *arg) { - uint32_t reg; - int error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + struct wpi_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; - /* Disable L0s exit timer (NMI bug workaround). */ - WPI_SETBITS(sc, WPI_GIO_CHICKEN, WPI_GIO_CHICKEN_DIS_L0S_TIMER); - /* Don't wait for ICH L0s (ICH bug workaround). */ - WPI_SETBITS(sc, WPI_GIO_CHICKEN, WPI_GIO_CHICKEN_L1A_NO_L0S_RX); + WPI_LOCK(sc); + wpi_init_locked(sc, 0); + WPI_UNLOCK(sc); - /* Set FH wait threshold to max (HW bug under stress workaround). */ - WPI_SETBITS(sc, WPI_DBG_HPET_MEM, 0xffff0000); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ieee80211_start_all(ic); /* start all vaps */ +} - /* Retrieve PCIe Active State Power Management (ASPM). */ - reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1); - /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */ - if (reg & 0x02) /* L1 Entry enabled. */ - WPI_SETBITS(sc, WPI_GIO, WPI_GIO_L0S_ENA); - else - WPI_CLRBITS(sc, WPI_GIO, WPI_GIO_L0S_ENA); +static void +wpi_stop_locked(struct wpi_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + uint32_t tmp; + int ac; - WPI_SETBITS(sc, WPI_ANA_PLL, WPI_ANA_PLL_INIT); + sc->sc_tx_timer = 0; + sc->sc_scan_timer = 0; + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->flags &= ~WPI_FLAG_HW_RADIO_OFF; + callout_stop(&sc->watchdog_to); + callout_stop(&sc->calib_to); - /* Wait for clock stabilization before accessing prph. */ - if ((error = wpi_clock_wait(sc)) != 0) - return error; + /* disable interrupts */ + WPI_WRITE(sc, WPI_MASK, 0); + WPI_WRITE(sc, WPI_INTR, WPI_INTR_MASK); + WPI_WRITE(sc, WPI_INTR_STATUS, 0xff); + WPI_WRITE(sc, WPI_INTR_STATUS, 0x00070000); - if ((error = wpi_nic_lock(sc)) != 0) - return error; - /* Cleanup. */ - wpi_prph_write(sc, WPI_APMG_CLK_DIS, 0x00000400); - wpi_prph_clrbits(sc, WPI_APMG_PS, 0x00000200); + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_MODE, 0); + wpi_mem_unlock(sc); - /* Enable DMA and BSM (Bootstrap State Machine). */ - wpi_prph_write(sc, WPI_APMG_CLK_EN, - WPI_APMG_CLK_CTRL_DMA_CLK_RQT | WPI_APMG_CLK_CTRL_BSM_CLK_RQT); - DELAY(20); - /* Disable L1-Active. */ - wpi_prph_setbits(sc, WPI_APMG_PCI_STT, WPI_APMG_PCI_STT_L1A_DIS); - wpi_nic_unlock(sc); + /* reset all Tx rings */ + for (ac = 0; ac < 4; ac++) + wpi_reset_tx_ring(sc, &sc->txq[ac]); + wpi_reset_tx_ring(sc, &sc->cmdq); - return 0; -} + /* reset Rx ring */ + wpi_reset_rx_ring(sc, &sc->rxq); -static void -wpi_apm_stop_master(struct wpi_softc *sc) -{ - int ntries; + wpi_mem_lock(sc); + wpi_mem_write(sc, WPI_MEM_CLOCK2, 0x200); + wpi_mem_unlock(sc); - /* Stop busmaster DMA activity. */ - WPI_SETBITS(sc, WPI_RESET, WPI_RESET_STOP_MASTER); + DELAY(5); - if ((WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_PS_MASK) == - WPI_GP_CNTRL_MAC_PS) - return; /* Already asleep. */ + wpi_stop_master(sc); - for (ntries = 0; ntries < 100; ntries++) { - if (WPI_READ(sc, WPI_RESET) & WPI_RESET_MASTER_DISABLED) - return; - DELAY(10); - } - device_printf(sc->sc_dev, "%s: timeout waiting for master\n", - __func__); + tmp = WPI_READ(sc, WPI_RESET); + WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET); + sc->flags &= ~WPI_FLAG_BUSY; } static void -wpi_apm_stop(struct wpi_softc *sc) +wpi_stop(struct wpi_softc *sc) { - wpi_apm_stop_master(sc); - - /* Reset the entire device. */ - WPI_SETBITS(sc, WPI_RESET, WPI_RESET_SW); - DELAY(10); - /* Clear "initialization complete" bit. */ - WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_INIT_DONE); + WPI_LOCK(sc); + wpi_stop_locked(sc); + WPI_UNLOCK(sc); } static void -wpi_nic_config(struct wpi_softc *sc) +wpi_calib_timeout(void *arg) { - uint32_t rev; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + struct wpi_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + int temp; - /* voodoo from the Linux "driver".. */ - rev = pci_read_config(sc->sc_dev, PCIR_REVID, 1); - if ((rev & 0xc0) == 0x40) - WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_ALM_MB); - else if (!(rev & 0x80)) - WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_ALM_MM); + if (vap->iv_state != IEEE80211_S_RUN) + return; - if (sc->cap == 0x80) - WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_SKU_MRC); + /* update sensor data */ + temp = (int)WPI_READ(sc, WPI_TEMPERATURE); + DPRINTFN(WPI_DEBUG_TEMP,("Temp in calibration is: %d\n", temp)); - if ((sc->rev & 0xf0) == 0xd0) - WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_REV_D); - else - WPI_CLRBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_REV_D); + wpi_power_calibration(sc, temp); - if (sc->type > 1) - WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_TYPE_B); + callout_reset(&sc->calib_to, 60*hz, wpi_calib_timeout, sc); } -static int -wpi_hw_init(struct wpi_softc *sc) +/* + * This function is called periodically (every 60 seconds) to adjust output + * power to temperature changes. + */ +static void +wpi_power_calibration(struct wpi_softc *sc, int temp) { - int chnl, ntries, error; - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - - /* Clear pending interrupts. */ - WPI_WRITE(sc, WPI_INT, 0xffffffff); - - if ((error = wpi_apm_init(sc)) != 0) { - device_printf(sc->sc_dev, - "%s: could not power ON adapter, error %d\n", __func__, - error); - return error; - } + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - /* Select VMAIN power source. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; - wpi_prph_clrbits(sc, WPI_APMG_PS, WPI_APMG_PS_PWR_SRC_MASK); - wpi_nic_unlock(sc); - /* Spin until VMAIN gets selected. */ - for (ntries = 0; ntries < 5000; ntries++) { - if (WPI_READ(sc, WPI_GPIO_IN) & WPI_GPIO_IN_VMAIN) - break; - DELAY(10); - } - if (ntries == 5000) { - device_printf(sc->sc_dev, "timeout selecting power source\n"); - return ETIMEDOUT; + /* sanity-check read value */ + if (temp < -260 || temp > 25) { + /* this can't be correct, ignore */ + DPRINTFN(WPI_DEBUG_TEMP, + ("out-of-range temperature reported: %d\n", temp)); + return; } - /* Perform adapter initialization. */ - wpi_nic_config(sc); + DPRINTFN(WPI_DEBUG_TEMP,("temperature %d->%d\n", sc->temp, temp)); - /* Initialize RX ring. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; - /* Set physical address of RX ring. */ - WPI_WRITE(sc, WPI_FH_RX_BASE, sc->rxq.desc_dma.paddr); - /* Set physical address of RX read pointer. */ - WPI_WRITE(sc, WPI_FH_RX_RPTR_ADDR, sc->shared_dma.paddr + - offsetof(struct wpi_shared, next)); - WPI_WRITE(sc, WPI_FH_RX_WPTR, 0); - /* Enable RX. */ - WPI_WRITE(sc, WPI_FH_RX_CONFIG, - WPI_FH_RX_CONFIG_DMA_ENA | - WPI_FH_RX_CONFIG_RDRBD_ENA | - WPI_FH_RX_CONFIG_WRSTATUS_ENA | - WPI_FH_RX_CONFIG_MAXFRAG | - WPI_FH_RX_CONFIG_NRBD(WPI_RX_RING_COUNT_LOG) | - WPI_FH_RX_CONFIG_IRQ_DST_HOST | - WPI_FH_RX_CONFIG_IRQ_TIMEOUT(1)); - (void)WPI_READ(sc, WPI_FH_RSSR_TBL); /* barrier */ - wpi_nic_unlock(sc); - WPI_WRITE(sc, WPI_FH_RX_WPTR, (WPI_RX_RING_COUNT - 1) & ~7); - - /* Initialize TX rings. */ - if ((error = wpi_nic_lock(sc)) != 0) - return error; - wpi_prph_write(sc, WPI_ALM_SCHED_MODE, 2); /* bypass mode */ - wpi_prph_write(sc, WPI_ALM_SCHED_ARASTAT, 1); /* enable RA0 */ - /* Enable all 6 TX rings. */ - wpi_prph_write(sc, WPI_ALM_SCHED_TXFACT, 0x3f); - wpi_prph_write(sc, WPI_ALM_SCHED_SBYPASS_MODE1, 0x10000); - wpi_prph_write(sc, WPI_ALM_SCHED_SBYPASS_MODE2, 0x30002); - wpi_prph_write(sc, WPI_ALM_SCHED_TXF4MF, 4); - wpi_prph_write(sc, WPI_ALM_SCHED_TXF5MF, 5); - /* Set physical address of TX rings. */ - WPI_WRITE(sc, WPI_FH_TX_BASE, sc->shared_dma.paddr); - WPI_WRITE(sc, WPI_FH_MSG_CONFIG, 0xffff05a5); - - /* Enable all DMA channels. */ - for (chnl = 0; chnl < WPI_NDMACHNLS; chnl++) { - WPI_WRITE(sc, WPI_FH_CBBC_CTRL(chnl), 0); - WPI_WRITE(sc, WPI_FH_CBBC_BASE(chnl), 0); - WPI_WRITE(sc, WPI_FH_TX_CONFIG(chnl), 0x80200008); - } - wpi_nic_unlock(sc); - (void)WPI_READ(sc, WPI_FH_TX_BASE); /* barrier */ - - /* Clear "radio off" and "commands blocked" bits. */ - WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL); - WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_CMD_BLOCKED); - - /* Clear pending interrupts. */ - WPI_WRITE(sc, WPI_INT, 0xffffffff); - /* Enable interrupts. */ - WPI_WRITE(sc, WPI_INT_MASK, WPI_INT_MASK_DEF); - - /* _Really_ make sure "radio off" bit is cleared! */ - WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL); - WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL); - - if ((error = wpi_load_firmware(sc)) != 0) { - device_printf(sc->sc_dev, - "%s: could not load firmware, error %d\n", __func__, - error); - return error; - } - /* Wait at most one second for firmware alive notification. */ - if ((error = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) { - device_printf(sc->sc_dev, - "%s: timeout waiting for adapter to initialize, error %d\n", - __func__, error); - return error; - } + /* adjust Tx power if need be */ + if (abs(temp - sc->temp) <= 6) + return; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + sc->temp = temp; - /* Do post-firmware initialization. */ - return wpi_post_alive(sc); + if (wpi_set_txpower(sc, vap->iv_bss->ni_chan, 1) != 0) { + /* just warn, too bad for the automatic calibration... */ + device_printf(sc->sc_dev,"could not adjust Tx power\n"); + } } +/** + * Read the eeprom to find out what channels are valid for the given + * band and update net80211 with what we find. + */ static void -wpi_hw_stop(struct wpi_softc *sc) +wpi_read_eeprom_channels(struct wpi_softc *sc, int n) { - int chnl, qid, ntries; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + const struct wpi_chan_band *band = &wpi_bands[n]; + struct wpi_eeprom_chan channels[WPI_MAX_CHAN_PER_BAND]; + struct ieee80211_channel *c; + int chan, i, passive; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + wpi_read_prom_data(sc, band->addr, channels, + band->nchan * sizeof (struct wpi_eeprom_chan)); - if (WPI_READ(sc, WPI_UCODE_GP1) & WPI_UCODE_GP1_MAC_SLEEP) - wpi_nic_lock(sc); + for (i = 0; i < band->nchan; i++) { + if (!(channels[i].flags & WPI_EEPROM_CHAN_VALID)) { + DPRINTFN(WPI_DEBUG_HW, + ("Channel Not Valid: %d, band %d\n", + band->chan[i],n)); + continue; + } - WPI_WRITE(sc, WPI_RESET, WPI_RESET_NEVO); + passive = 0; + chan = band->chan[i]; + c = &ic->ic_channels[ic->ic_nchans++]; - /* Disable interrupts. */ - WPI_WRITE(sc, WPI_INT_MASK, 0); - WPI_WRITE(sc, WPI_INT, 0xffffffff); - WPI_WRITE(sc, WPI_FH_INT, 0xffffffff); + /* is active scan allowed on this channel? */ + if (!(channels[i].flags & WPI_EEPROM_CHAN_ACTIVE)) { + passive = IEEE80211_CHAN_PASSIVE; + } - /* Make sure we no longer hold the NIC lock. */ - wpi_nic_unlock(sc); + if (n == 0) { /* 2GHz band */ + c->ic_ieee = chan; + c->ic_freq = ieee80211_ieee2mhz(chan, + IEEE80211_CHAN_2GHZ); + c->ic_flags = IEEE80211_CHAN_B | passive; - if (wpi_nic_lock(sc) == 0) { - /* Stop TX scheduler. */ - wpi_prph_write(sc, WPI_ALM_SCHED_MODE, 0); - wpi_prph_write(sc, WPI_ALM_SCHED_TXFACT, 0); + c = &ic->ic_channels[ic->ic_nchans++]; + c->ic_ieee = chan; + c->ic_freq = ieee80211_ieee2mhz(chan, + IEEE80211_CHAN_2GHZ); + c->ic_flags = IEEE80211_CHAN_G | passive; - /* Stop all DMA channels. */ - for (chnl = 0; chnl < WPI_NDMACHNLS; chnl++) { - WPI_WRITE(sc, WPI_FH_TX_CONFIG(chnl), 0); - for (ntries = 0; ntries < 200; ntries++) { - if (WPI_READ(sc, WPI_FH_TX_STATUS) & - WPI_FH_TX_STATUS_IDLE(chnl)) - break; - DELAY(10); - } + } else { /* 5GHz band */ + /* + * Some 3945ABG adapters support channels 7, 8, 11 + * and 12 in the 2GHz *and* 5GHz bands. + * Because of limitations in our net80211(9) stack, + * we can't support these channels in 5GHz band. + * XXX not true; just need to map to proper frequency + */ + if (chan <= 14) + continue; + + c->ic_ieee = chan; + c->ic_freq = ieee80211_ieee2mhz(chan, + IEEE80211_CHAN_5GHZ); + c->ic_flags = IEEE80211_CHAN_A | passive; } - wpi_nic_unlock(sc); - } - /* Stop RX ring. */ - wpi_reset_rx_ring(sc); + /* save maximum allowed power for this channel */ + sc->maxpwr[chan] = channels[i].maxpwr; - /* Reset all TX rings. */ - for (qid = 0; qid < WPI_NTXQUEUES; qid++) - wpi_reset_tx_ring(sc, &sc->txq[qid]); +#if 0 + // XXX We can probably use this an get rid of maxpwr - ben 20070617 + ic->ic_channels[chan].ic_maxpower = channels[i].maxpwr; + //ic->ic_channels[chan].ic_minpower... + //ic->ic_channels[chan].ic_maxregtxpower... +#endif - if (wpi_nic_lock(sc) == 0) { - wpi_prph_write(sc, WPI_APMG_CLK_DIS, - WPI_APMG_CLK_CTRL_DMA_CLK_RQT); - wpi_nic_unlock(sc); + DPRINTF(("adding chan %d (%dMHz) flags=0x%x maxpwr=%d" + " passive=%d, offset %d\n", chan, c->ic_freq, + channels[i].flags, sc->maxpwr[chan], + (c->ic_flags & IEEE80211_CHAN_PASSIVE) != 0, + ic->ic_nchans)); } - DELAY(5); - /* Power OFF adapter. */ - wpi_apm_stop(sc); } static void -wpi_radio_on(void *arg0, int pending) +wpi_read_eeprom_group(struct wpi_softc *sc, int n) { - struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - device_printf(sc->sc_dev, "RF switch: radio enabled\n"); - - if (vap != NULL) { - wpi_init(sc); - ieee80211_init(vap); - } + struct wpi_power_group *group = &sc->groups[n]; + struct wpi_eeprom_group rgroup; + int i; - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL) { - WPI_LOCK(sc); - callout_stop(&sc->watchdog_rfkill); - WPI_UNLOCK(sc); - } -} + wpi_read_prom_data(sc, WPI_EEPROM_POWER_GRP + n * 32, &rgroup, + sizeof rgroup); -static void -wpi_radio_off(void *arg0, int pending) -{ - struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + /* save power group information */ + group->chan = rgroup.chan; + group->maxpwr = rgroup.maxpwr; + /* temperature at which the samples were taken */ + group->temp = (int16_t)le16toh(rgroup.temp); - device_printf(sc->sc_dev, "RF switch: radio disabled\n"); + DPRINTF(("power group %d: chan=%d maxpwr=%d temp=%d\n", n, + group->chan, group->maxpwr, group->temp)); - wpi_stop(sc); - if (vap != NULL) - ieee80211_stop(vap); + for (i = 0; i < WPI_SAMPLES_COUNT; i++) { + group->samples[i].index = rgroup.samples[i].index; + group->samples[i].power = rgroup.samples[i].power; - WPI_LOCK(sc); - callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill, sc); - WPI_UNLOCK(sc); + DPRINTF(("\tsample %d: index=%d power=%d\n", i, + group->samples[i].index, group->samples[i].power)); + } } -static void -wpi_init(void *arg) +/* + * Update Tx power to match what is defined for channel `c'. + */ +static int +wpi_set_txpower(struct wpi_softc *sc, struct ieee80211_channel *c, int async) { - struct wpi_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - int error; - - WPI_LOCK(sc); + struct wpi_power_group *group; + struct wpi_cmd_txpower txpower; + u_int chan; + int i; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + /* get channel number */ + chan = ieee80211_chan2ieee(ic, c); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - goto end; + /* find the power group to which this channel belongs */ + if (IEEE80211_IS_CHAN_5GHZ(c)) { + for (group = &sc->groups[1]; group < &sc->groups[4]; group++) + if (chan <= group->chan) + break; + } else + group = &sc->groups[0]; - /* Check that the radio is not disabled by hardware switch. */ - if (!(WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL)) { - device_printf(sc->sc_dev, - "RF switch: radio disabled (%s)\n", __func__); - callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill, - sc); - goto end; - } + memset(&txpower, 0, sizeof txpower); + txpower.band = IEEE80211_IS_CHAN_5GHZ(c) ? 0 : 1; + txpower.channel = htole16(chan); - /* Read firmware images from the filesystem. */ - if ((error = wpi_read_firmware(sc)) != 0) { - device_printf(sc->sc_dev, - "%s: could not read firmware, error %d\n", __func__, - error); - goto fail; - } + /* set Tx power for all OFDM and CCK rates */ + for (i = 0; i <= 11 ; i++) { + /* retrieve Tx power for this channel/rate combination */ + int idx = wpi_get_power_index(sc, group, c, + wpi_ridx_to_rate[i]); - /* Initialize hardware and upload firmware. */ - error = wpi_hw_init(sc); - wpi_unload_firmware(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not initialize hardware, error %d\n", __func__, - error); - goto fail; - } + txpower.rates[i].rate = wpi_ridx_to_plcp[i]; - /* Configure adapter now that it is ready. */ - sc->txq_active = 1; - if ((error = wpi_config(sc)) != 0) { - device_printf(sc->sc_dev, - "%s: could not configure device, error %d\n", __func__, - error); - goto fail; + if (IEEE80211_IS_CHAN_5GHZ(c)) { + txpower.rates[i].gain_radio = wpi_rf_gain_5ghz[idx]; + txpower.rates[i].gain_dsp = wpi_dsp_gain_5ghz[idx]; + } else { + txpower.rates[i].gain_radio = wpi_rf_gain_2ghz[idx]; + txpower.rates[i].gain_dsp = wpi_dsp_gain_2ghz[idx]; + } + DPRINTFN(WPI_DEBUG_TEMP,("chan %d/rate %d: power index %d\n", + chan, wpi_ridx_to_rate[i], idx)); } - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - IF_UNLOCK(&ifp->if_snd); - - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); + return wpi_cmd(sc, WPI_CMD_TXPOWER, &txpower, sizeof txpower, async); +} - WPI_UNLOCK(sc); +/* + * Determine Tx power index for a given channel/rate combination. + * This takes into account the regulatory information from EEPROM and the + * current temperature. + */ +static int +wpi_get_power_index(struct wpi_softc *sc, struct wpi_power_group *group, + struct ieee80211_channel *c, int rate) +{ +/* fixed-point arithmetic division using a n-bit fractional part */ +#define fdivround(a, b, n) \ + ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n)) - ieee80211_start_all(ic); +/* linear interpolation */ +#define interpolate(x, x1, y1, x2, y2, n) \ + ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n)) - return; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct wpi_power_sample *sample; + int pwr, idx; + u_int chan; -fail: wpi_stop_locked(sc); -end: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); - WPI_UNLOCK(sc); -} + /* get channel number */ + chan = ieee80211_chan2ieee(ic, c); -static void -wpi_stop_locked(struct wpi_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; + /* default power is group's maximum power - 3dB */ + pwr = group->maxpwr / 2; - WPI_LOCK_ASSERT(sc); + /* decrease power for highest OFDM rates to reduce distortion */ + switch (rate) { + case 72: /* 36Mb/s */ + pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 0 : 5; + break; + case 96: /* 48Mb/s */ + pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 7 : 10; + break; + case 108: /* 54Mb/s */ + pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 9 : 12; + break; + } - WPI_TXQ_LOCK(sc); - sc->txq_active = 0; - WPI_TXQ_UNLOCK(sc); + /* never exceed channel's maximum allowed Tx power */ + pwr = min(pwr, sc->maxpwr[chan]); - WPI_TXQ_STATE_LOCK(sc); - callout_stop(&sc->tx_timeout); - WPI_TXQ_STATE_UNLOCK(sc); + /* retrieve power index into gain tables from samples */ + for (sample = group->samples; sample < &group->samples[3]; sample++) + if (pwr > sample[1].power) + break; + /* fixed-point linear interpolation using a 19-bit fractional part */ + idx = interpolate(pwr, sample[0].power, sample[0].index, + sample[1].power, sample[1].index, 19); - WPI_RXON_LOCK(sc); - callout_stop(&sc->scan_timeout); - callout_stop(&sc->calib_to); - WPI_RXON_UNLOCK(sc); + /* + * Adjust power index based on current temperature + * - if colder than factory-calibrated: decreate output power + * - if warmer than factory-calibrated: increase output power + */ + idx -= (sc->temp - group->temp) * 11 / 100; - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - IF_UNLOCK(&ifp->if_snd); + /* decrease power for CCK rates (-5dB) */ + if (!WPI_RATE_IS_OFDM(rate)) + idx += 10; - /* Power OFF hardware. */ - wpi_hw_stop(sc); -} + /* keep power index in a valid range */ + if (idx < 0) + return 0; + if (idx > WPI_MAX_PWR_INDEX) + return WPI_MAX_PWR_INDEX; + return idx; -static void -wpi_stop(struct wpi_softc *sc) -{ - WPI_LOCK(sc); - wpi_stop_locked(sc); - WPI_UNLOCK(sc); +#undef interpolate +#undef fdivround } -/* - * Callback from net80211 to start a scan. +/** + * Called by net80211 framework to indicate that a scan + * is starting. This function doesn't actually do the scan, + * wpi_scan_curchan starts things off. This function is more + * of an early warning from the framework we should get ready + * for the scan. */ static void wpi_scan_start(struct ieee80211com *ic) { - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct ifnet *ifp = ic->ic_ifp; + struct wpi_softc *sc = ifp->if_softc; + WPI_LOCK(sc); wpi_set_led(sc, WPI_LED_LINK, 20, 2); + WPI_UNLOCK(sc); } -/* - * Callback from net80211 to terminate a scan. +/** + * Called by the net80211 framework, indicates that the + * scan has ended. If there is a scan in progress on the card + * then it should be aborted. */ static void wpi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (vap->iv_state == IEEE80211_S_RUN) - wpi_set_led(sc, WPI_LED_LINK, 0, 1); + /* XXX ignore */ } /** @@ -5566,41 +3549,21 @@ wpi_scan_end(struct ieee80211com *ic) static void wpi_set_channel(struct ieee80211com *ic) { - const struct ieee80211_channel *c = ic->ic_curchan; struct ifnet *ifp = ic->ic_ifp; struct wpi_softc *sc = ifp->if_softc; int error; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); - - WPI_LOCK(sc); - sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); - WPI_UNLOCK(sc); - WPI_TX_LOCK(sc); - sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); - sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); - WPI_TX_UNLOCK(sc); - /* * Only need to set the channel in Monitor mode. AP scanning and auth * are already taken care of by their respective firmware commands. */ if (ic->ic_opmode == IEEE80211_M_MONITOR) { - WPI_RXON_LOCK(sc); - sc->rxon.chan = ieee80211_chan2ieee(ic, c); - if (IEEE80211_IS_CHAN_2GHZ(c)) { - sc->rxon.flags |= htole32(WPI_RXON_AUTO | - WPI_RXON_24GHZ); - } else { - sc->rxon.flags &= ~htole32(WPI_RXON_AUTO | - WPI_RXON_24GHZ); - } - if ((error = wpi_send_rxon(sc, 0, 1)) != 0) + WPI_LOCK(sc); + error = wpi_config(sc); + WPI_UNLOCK(sc); + if (error != 0) device_printf(sc->sc_dev, - "%s: error %d setting channel\n", __func__, - error); - WPI_RXON_UNLOCK(sc); + "error %d settting channel\n", error); } } @@ -5613,15 +3576,13 @@ static void wpi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) { struct ieee80211vap *vap = ss->ss_vap; - struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; - int error; + struct ifnet *ifp = vap->iv_ic->ic_ifp; + struct wpi_softc *sc = ifp->if_softc; - WPI_RXON_LOCK(sc); - error = wpi_scan(sc, ic->ic_curchan); - WPI_RXON_UNLOCK(sc); - if (error != 0) + WPI_LOCK(sc); + if (wpi_scan(sc)) ieee80211_cancel_scan(vap); + WPI_UNLOCK(sc); } /** @@ -5637,22 +3598,118 @@ wpi_scan_mindwell(struct ieee80211_scan_state *ss) } static void -wpi_hw_reset(void *arg, int pending) +wpi_hwreset(void *arg, int pending) +{ + struct wpi_softc *sc = arg; + + WPI_LOCK(sc); + wpi_init_locked(sc, 0); + WPI_UNLOCK(sc); +} + +static void +wpi_rfreset(void *arg, int pending) +{ + struct wpi_softc *sc = arg; + + WPI_LOCK(sc); + wpi_rfkill_resume(sc); + WPI_UNLOCK(sc); +} + +/* + * Allocate DMA-safe memory for firmware transfer. + */ +static int +wpi_alloc_fwmem(struct wpi_softc *sc) +{ + /* allocate enough contiguous space to store text and data */ + return wpi_dma_contig_alloc(sc, &sc->fw_dma, NULL, + WPI_FW_MAIN_TEXT_MAXSZ + WPI_FW_MAIN_DATA_MAXSZ, 1, + BUS_DMA_NOWAIT); +} + +static void +wpi_free_fwmem(struct wpi_softc *sc) +{ + wpi_dma_contig_free(&sc->fw_dma); +} + +/** + * Called every second, wpi_watchdog used by the watch dog timer + * to check that the card is still alive + */ +static void +wpi_watchdog(void *arg) { struct wpi_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + uint32_t tmp; - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + DPRINTFN(WPI_DEBUG_WATCHDOG,("Watchdog: tick\n")); - if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN)) - ieee80211_cancel_scan(vap); + if (sc->flags & WPI_FLAG_HW_RADIO_OFF) { + /* No need to lock firmware memory */ + tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF); + + if ((tmp & 0x1) == 0) { + /* Radio kill switch is still off */ + callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc); + return; + } + + device_printf(sc->sc_dev, "Hardware Switch Enabled\n"); + ieee80211_runtask(ic, &sc->sc_radiotask); + return; + } + + if (sc->sc_tx_timer > 0) { + if (--sc->sc_tx_timer == 0) { + device_printf(sc->sc_dev,"device timeout\n"); + ifp->if_oerrors++; + ieee80211_runtask(ic, &sc->sc_restarttask); + } + } + if (sc->sc_scan_timer > 0) { + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + if (--sc->sc_scan_timer == 0 && vap != NULL) { + device_printf(sc->sc_dev,"scan timeout\n"); + ieee80211_cancel_scan(vap); + ieee80211_runtask(ic, &sc->sc_restarttask); + } + } + + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc); +} + +#ifdef WPI_DEBUG +static const char *wpi_cmd_str(int cmd) +{ + switch (cmd) { + case WPI_DISABLE_CMD: return "WPI_DISABLE_CMD"; + case WPI_CMD_CONFIGURE: return "WPI_CMD_CONFIGURE"; + case WPI_CMD_ASSOCIATE: return "WPI_CMD_ASSOCIATE"; + case WPI_CMD_SET_WME: return "WPI_CMD_SET_WME"; + case WPI_CMD_TSF: return "WPI_CMD_TSF"; + case WPI_CMD_ADD_NODE: return "WPI_CMD_ADD_NODE"; + case WPI_CMD_TX_DATA: return "WPI_CMD_TX_DATA"; + case WPI_CMD_MRR_SETUP: return "WPI_CMD_MRR_SETUP"; + case WPI_CMD_SET_LED: return "WPI_CMD_SET_LED"; + case WPI_CMD_SET_POWER_MODE: return "WPI_CMD_SET_POWER_MODE"; + case WPI_CMD_SCAN: return "WPI_CMD_SCAN"; + case WPI_CMD_SET_BEACON:return "WPI_CMD_SET_BEACON"; + case WPI_CMD_TXPOWER: return "WPI_CMD_TXPOWER"; + case WPI_CMD_BLUETOOTH: return "WPI_CMD_BLUETOOTH"; - wpi_stop(sc); - if (vap != NULL) - ieee80211_stop(vap); - wpi_init(sc); - if (vap != NULL) - ieee80211_init(vap); + default: + KASSERT(1, ("Unknown Command: %d\n", cmd)); + return "UNKNOWN CMD"; /* Make the compiler happy */ + } } +#endif + +MODULE_DEPEND(wpi, pci, 1, 1, 1); +MODULE_DEPEND(wpi, wlan, 1, 1, 1); +MODULE_DEPEND(wpi, firmware, 1, 1, 1); diff --git a/sys/dev/wpi/if_wpi_debug.h b/sys/dev/wpi/if_wpi_debug.h deleted file mode 100644 index 6b78ace..0000000 --- a/sys/dev/wpi/if_wpi_debug.h +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * Copyright (c) 2006,2007 - * Damien Bergamini - * Benjamin Close - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef __IF_WPI_DEBUG_H__ -#define __IF_WPI_DEBUG_H__ - -#ifdef WPI_DEBUG -enum { - WPI_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - WPI_DEBUG_RECV = 0x00000002, /* basic recv operation */ - WPI_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */ - WPI_DEBUG_HW = 0x00000008, /* Stage 1 (eeprom) debugging */ - WPI_DEBUG_RESET = 0x00000010, /* reset processing */ - WPI_DEBUG_FIRMWARE = 0x00000020, /* firmware(9) loading debug */ - WPI_DEBUG_BEACON = 0x00000040, /* beacon handling */ - WPI_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ - WPI_DEBUG_INTR = 0x00000100, /* ISR */ - WPI_DEBUG_SCAN = 0x00000200, /* Scan related operations */ - WPI_DEBUG_NOTIFY = 0x00000400, /* State 2 Notif intr debug */ - WPI_DEBUG_TEMP = 0x00000800, /* TXPower/Temp Calibration */ - WPI_DEBUG_CMD = 0x00001000, /* cmd submission */ - WPI_DEBUG_TRACE = 0x00002000, /* Print begin and start driver function */ - WPI_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ - WPI_DEBUG_EEPROM = 0x00008000, /* EEPROM info */ - WPI_DEBUG_NODE = 0x00010000, /* node addition/removal */ - WPI_DEBUG_KEY = 0x00020000, /* node key management */ - WPI_DEBUG_EDCA = 0x00040000, /* WME info */ - WPI_DEBUG_REGISTER = 0x00080000, /* print chipset register */ - WPI_DEBUG_BMISS = 0x00100000, /* print number of missed beacons */ - WPI_DEBUG_ANY = 0xffffffff -}; - -#define DPRINTF(sc, m, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(__VA_ARGS__); \ -} while (0) - -#define TRACE_STR_BEGIN "->%s: begin\n" -#define TRACE_STR_DOING "->Doing %s\n" -#define TRACE_STR_END "->%s: end\n" -#define TRACE_STR_END_ERR "->%s: end in error\n" - -#define WPI_DESC(x) case x: return #x - -static const char *wpi_cmd_str(int cmd) -{ - switch (cmd) { - /* Notifications. */ - WPI_DESC(WPI_UC_READY); - WPI_DESC(WPI_RX_DONE); - WPI_DESC(WPI_START_SCAN); - WPI_DESC(WPI_SCAN_RESULTS); - WPI_DESC(WPI_STOP_SCAN); - WPI_DESC(WPI_BEACON_SENT); - WPI_DESC(WPI_RX_STATISTICS); - WPI_DESC(WPI_BEACON_STATISTICS); - WPI_DESC(WPI_STATE_CHANGED); - WPI_DESC(WPI_BEACON_MISSED); - - /* Command notifications. */ - WPI_DESC(WPI_CMD_RXON); - WPI_DESC(WPI_CMD_RXON_ASSOC); - WPI_DESC(WPI_CMD_EDCA_PARAMS); - WPI_DESC(WPI_CMD_TIMING); - WPI_DESC(WPI_CMD_ADD_NODE); - WPI_DESC(WPI_CMD_DEL_NODE); - WPI_DESC(WPI_CMD_TX_DATA); - WPI_DESC(WPI_CMD_MRR_SETUP); - WPI_DESC(WPI_CMD_SET_LED); - WPI_DESC(WPI_CMD_SET_POWER_MODE); - WPI_DESC(WPI_CMD_SCAN); - WPI_DESC(WPI_CMD_SCAN_ABORT); - WPI_DESC(WPI_CMD_SET_BEACON); - WPI_DESC(WPI_CMD_TXPOWER); - WPI_DESC(WPI_CMD_BT_COEX); - - default: - return "UNKNOWN CMD"; - } -} - -/* - * Translate CSR code to string - */ -static const char *wpi_get_csr_string(size_t csr) -{ - switch (csr) { - WPI_DESC(WPI_HW_IF_CONFIG); - WPI_DESC(WPI_INT); - WPI_DESC(WPI_INT_MASK); - WPI_DESC(WPI_FH_INT); - WPI_DESC(WPI_GPIO_IN); - WPI_DESC(WPI_RESET); - WPI_DESC(WPI_GP_CNTRL); - WPI_DESC(WPI_EEPROM); - WPI_DESC(WPI_EEPROM_GP); - WPI_DESC(WPI_GIO); - WPI_DESC(WPI_UCODE_GP1); - WPI_DESC(WPI_UCODE_GP2); - WPI_DESC(WPI_GIO_CHICKEN); - WPI_DESC(WPI_ANA_PLL); - WPI_DESC(WPI_DBG_HPET_MEM); - default: - KASSERT(0, ("Unknown CSR: %d\n", csr)); - return "UNKNOWN CSR"; - } -} - -static const char *wpi_get_prph_string(size_t prph) -{ - switch (prph) { - WPI_DESC(WPI_APMG_CLK_CTRL); - WPI_DESC(WPI_APMG_PS); - WPI_DESC(WPI_APMG_PCI_STT); - WPI_DESC(WPI_APMG_RFKILL); - default: - KASSERT(0, ("Unknown register: %d\n", prph)); - return "UNKNOWN PRPH"; - } -} - -#else -#define DPRINTF(sc, m, ...) do { (void) sc; } while (0) -#endif - -#endif /* __IF_WPI_DEBUG_H__ */ diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h index b0aa35c..df71b3d 100644 --- a/sys/dev/wpi/if_wpireg.h +++ b/sys/dev/wpi/if_wpireg.h @@ -18,264 +18,181 @@ */ #define WPI_TX_RING_COUNT 256 -#define WPI_TX_RING_LOMARK 192 -#define WPI_TX_RING_HIMARK 224 - -#ifdef DIAGNOSTIC -#define WPI_RX_RING_COUNT_LOG 8 -#else -#define WPI_RX_RING_COUNT_LOG 6 -#endif - -#define WPI_RX_RING_COUNT (1 << WPI_RX_RING_COUNT_LOG) - -#define WPI_NTXQUEUES 8 -#define WPI_DRV_NTXQUEUES 5 -#define WPI_CMD_QUEUE_NUM 4 - -#define WPI_NDMACHNLS 6 - -/* Maximum scatter/gather. */ -#define WPI_MAX_SCATTER 4 +#define WPI_CMD_RING_COUNT 256 +#define WPI_RX_RING_COUNT 64 /* * Rings must be aligned on a 16K boundary. */ #define WPI_RING_DMA_ALIGN 0x4000 -/* Maximum Rx buffer size. */ +/* maximum scatter/gather */ +#define WPI_MAX_SCATTER 4 + +/* maximum Rx buffer size */ #define WPI_RBUF_SIZE ( 3 * 1024 ) /* XXX 3000 but must be aligned */ /* * Control and status registers. */ -#define WPI_HW_IF_CONFIG 0x000 -#define WPI_INT 0x008 -#define WPI_INT_MASK 0x00c -#define WPI_FH_INT 0x010 -#define WPI_GPIO_IN 0x018 +#define WPI_HWCONFIG 0x000 +#define WPI_INTR 0x008 +#define WPI_MASK 0x00c +#define WPI_INTR_STATUS 0x010 +#define WPI_GPIO_STATUS 0x018 #define WPI_RESET 0x020 -#define WPI_GP_CNTRL 0x024 -#define WPI_EEPROM 0x02c -#define WPI_EEPROM_GP 0x030 -#define WPI_GIO 0x03c -#define WPI_UCODE_GP1 0x054 -#define WPI_UCODE_GP1_SET 0x058 -#define WPI_UCODE_GP1_CLR 0x05c -#define WPI_UCODE_GP2 0x060 -#define WPI_GIO_CHICKEN 0x100 -#define WPI_ANA_PLL 0x20c -#define WPI_DBG_HPET_MEM 0x240 -#define WPI_MEM_RADDR 0x40c -#define WPI_MEM_WADDR 0x410 -#define WPI_MEM_WDATA 0x418 -#define WPI_MEM_RDATA 0x41c -#define WPI_PRPH_WADDR 0x444 -#define WPI_PRPH_RADDR 0x448 -#define WPI_PRPH_WDATA 0x44c -#define WPI_PRPH_RDATA 0x450 -#define WPI_HBUS_TARG_WRPTR 0x460 - -/* - * Flow-Handler registers. - */ -#define WPI_FH_CBBC_CTRL(qid) (0x940 + (qid) * 8) -#define WPI_FH_CBBC_BASE(qid) (0x944 + (qid) * 8) -#define WPI_FH_RX_CONFIG 0xc00 -#define WPI_FH_RX_BASE 0xc04 -#define WPI_FH_RX_WPTR 0xc20 -#define WPI_FH_RX_RPTR_ADDR 0xc24 -#define WPI_FH_RSSR_TBL 0xcc0 -#define WPI_FH_RX_STATUS 0xcc4 -#define WPI_FH_TX_CONFIG(qid) (0xd00 + (qid) * 32) -#define WPI_FH_TX_BASE 0xe80 -#define WPI_FH_MSG_CONFIG 0xe88 -#define WPI_FH_TX_STATUS 0xe90 +#define WPI_GPIO_CTL 0x024 +#define WPI_EEPROM_CTL 0x02c +#define WPI_EEPROM_STATUS 0x030 +#define WPI_UCODE_SET 0x058 +#define WPI_UCODE_CLR 0x05c +#define WPI_TEMPERATURE 0x060 +#define WPI_CHICKEN 0x100 +#define WPI_PLL_CTL 0x20c +#define WPI_WRITE_MEM_ADDR 0x444 +#define WPI_READ_MEM_ADDR 0x448 +#define WPI_WRITE_MEM_DATA 0x44c +#define WPI_READ_MEM_DATA 0x450 +#define WPI_TX_WIDX 0x460 +#define WPI_TX_CTL(qid) (0x940 + (qid) * 8) +#define WPI_TX_BASE(qid) (0x944 + (qid) * 8) +#define WPI_TX_DESC(qid) (0x980 + (qid) * 80) +#define WPI_RX_CONFIG 0xc00 +#define WPI_RX_BASE 0xc04 +#define WPI_RX_WIDX 0xc20 +#define WPI_RX_RIDX_PTR 0xc24 +#define WPI_RX_CTL 0xcc0 +#define WPI_RX_STATUS 0xcc4 +#define WPI_TX_CONFIG(qid) (0xd00 + (qid) * 32) +#define WPI_TX_CREDIT(qid) (0xd04 + (qid) * 32) +#define WPI_TX_STATE(qid) (0xd08 + (qid) * 32) +#define WPI_TX_BASE_PTR 0xe80 +#define WPI_MSG_CONFIG 0xe88 +#define WPI_TX_STATUS 0xe90 /* * NIC internal memory offsets. */ -#define WPI_ALM_SCHED_MODE 0x2e00 -#define WPI_ALM_SCHED_ARASTAT 0x2e04 -#define WPI_ALM_SCHED_TXFACT 0x2e10 -#define WPI_ALM_SCHED_TXF4MF 0x2e14 -#define WPI_ALM_SCHED_TXF5MF 0x2e20 -#define WPI_ALM_SCHED_SBYPASS_MODE1 0x2e2c -#define WPI_ALM_SCHED_SBYPASS_MODE2 0x2e30 -#define WPI_APMG_CLK_CTRL 0x3000 -#define WPI_APMG_CLK_EN 0x3004 -#define WPI_APMG_CLK_DIS 0x3008 -#define WPI_APMG_PS 0x300c -#define WPI_APMG_PCI_STT 0x3010 -#define WPI_APMG_RFKILL 0x3014 -#define WPI_BSM_WR_CTRL 0x3400 -#define WPI_BSM_WR_MEM_SRC 0x3404 -#define WPI_BSM_WR_MEM_DST 0x3408 -#define WPI_BSM_WR_DWCOUNT 0x340c -#define WPI_BSM_DRAM_TEXT_ADDR 0x3490 -#define WPI_BSM_DRAM_TEXT_SIZE 0x3494 -#define WPI_BSM_DRAM_DATA_ADDR 0x3498 -#define WPI_BSM_DRAM_DATA_SIZE 0x349c -#define WPI_BSM_SRAM_BASE 0x3800 - - -/* Possible flags for register WPI_HW_IF_CONFIG. */ -#define WPI_HW_IF_CONFIG_ALM_MB (1 << 8) -#define WPI_HW_IF_CONFIG_ALM_MM (1 << 9) -#define WPI_HW_IF_CONFIG_SKU_MRC (1 << 10) -#define WPI_HW_IF_CONFIG_REV_D (1 << 11) -#define WPI_HW_IF_CONFIG_TYPE_B (1 << 12) - -/* Possible flags for registers WPI_PRPH_RADDR/WPI_PRPH_WADDR. */ -#define WPI_PRPH_DWORD ((sizeof (uint32_t) - 1) << 24) - -/* Possible values for WPI_BSM_WR_MEM_DST. */ -#define WPI_FW_TEXT_BASE 0x00000000 -#define WPI_FW_DATA_BASE 0x00800000 - -/* Possible flags for WPI_GPIO_IN. */ -#define WPI_GPIO_IN_VMAIN (1 << 9) - -/* Possible flags for register WPI_RESET. */ -#define WPI_RESET_NEVO (1 << 0) -#define WPI_RESET_SW (1 << 7) -#define WPI_RESET_MASTER_DISABLED (1 << 8) -#define WPI_RESET_STOP_MASTER (1 << 9) - -/* Possible flags for register WPI_GP_CNTRL. */ -#define WPI_GP_CNTRL_MAC_ACCESS_ENA (1 << 0) -#define WPI_GP_CNTRL_MAC_CLOCK_READY (1 << 0) -#define WPI_GP_CNTRL_INIT_DONE (1 << 2) -#define WPI_GP_CNTRL_MAC_ACCESS_REQ (1 << 3) -#define WPI_GP_CNTRL_SLEEP (1 << 4) -#define WPI_GP_CNTRL_PS_MASK (7 << 24) -#define WPI_GP_CNTRL_MAC_PS (4 << 24) -#define WPI_GP_CNTRL_RFKILL (1 << 27) - -/* Possible flags for register WPI_GIO_CHICKEN. */ -#define WPI_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23) -#define WPI_GIO_CHICKEN_DIS_L0S_TIMER (1 << 29) - -/* Possible flags for register WPI_GIO. */ -#define WPI_GIO_L0S_ENA (1 << 1) - -/* Possible flags for register WPI_FH_RX_CONFIG. */ -#define WPI_FH_RX_CONFIG_DMA_ENA (1U << 31) -#define WPI_FH_RX_CONFIG_RDRBD_ENA (1 << 29) -#define WPI_FH_RX_CONFIG_WRSTATUS_ENA (1 << 27) -#define WPI_FH_RX_CONFIG_MAXFRAG (1 << 24) -#define WPI_FH_RX_CONFIG_NRBD(x) ((x) << 20) -#define WPI_FH_RX_CONFIG_IRQ_DST_HOST (1 << 12) -#define WPI_FH_RX_CONFIG_IRQ_TIMEOUT(x) ((x) << 4) - -/* Possible flags for register WPI_ANA_PLL. */ -#define WPI_ANA_PLL_INIT (1 << 24) - -/* Possible flags for register WPI_UCODE_GP1*. */ -#define WPI_UCODE_GP1_MAC_SLEEP (1 << 0) -#define WPI_UCODE_GP1_RFKILL (1 << 1) -#define WPI_UCODE_GP1_CMD_BLOCKED (1 << 2) - -/* Possible flags for register WPI_FH_RX_STATUS. */ -#define WPI_FH_RX_STATUS_IDLE (1 << 24) - -/* Possible flags for register WPI_BSM_WR_CTRL. */ -#define WPI_BSM_WR_CTRL_START_EN (1 << 30) -#define WPI_BSM_WR_CTRL_START (1U << 31) - -/* Possible flags for register WPI_INT. */ -#define WPI_INT_ALIVE (1 << 0) -#define WPI_INT_WAKEUP (1 << 1) -#define WPI_INT_SW_RX (1 << 3) -#define WPI_INT_SW_ERR (1 << 25) -#define WPI_INT_FH_TX (1 << 27) -#define WPI_INT_HW_ERR (1 << 29) -#define WPI_INT_FH_RX (1U << 31) - -/* Shortcut. */ -#define WPI_INT_MASK_DEF \ - (WPI_INT_SW_ERR | WPI_INT_HW_ERR | WPI_INT_FH_TX | \ - WPI_INT_FH_RX | WPI_INT_ALIVE | WPI_INT_WAKEUP | \ - WPI_INT_SW_RX) - -/* Possible flags for register WPI_FH_INT. */ -#define WPI_FH_INT_RX_CHNL(x) (1 << ((x) + 16)) -#define WPI_FH_INT_HI_PRIOR (1 << 30) -/* Shortcuts for the above. */ -#define WPI_FH_INT_RX \ - (WPI_FH_INT_RX_CHNL(0) | \ - WPI_FH_INT_RX_CHNL(1) | \ - WPI_FH_INT_RX_CHNL(2) | \ - WPI_FH_INT_HI_PRIOR) - -/* Possible flags for register WPI_FH_TX_STATUS. */ -#define WPI_FH_TX_STATUS_IDLE(qid) \ - (1 << ((qid) + 24) | 1 << ((qid) + 16)) - -/* Possible flags for register WPI_EEPROM. */ -#define WPI_EEPROM_READ_VALID (1 << 0) - -/* Possible flags for register WPI_EEPROM_GP. */ +#define WPI_MEM_MODE 0x2e00 +#define WPI_MEM_RA 0x2e04 +#define WPI_MEM_TXCFG 0x2e10 +#define WPI_MEM_MAGIC4 0x2e14 +#define WPI_MEM_MAGIC5 0x2e20 +#define WPI_MEM_BYPASS1 0x2e2c +#define WPI_MEM_BYPASS2 0x2e30 +#define WPI_MEM_CLOCK1 0x3004 +#define WPI_MEM_CLOCK2 0x3008 +#define WPI_MEM_POWER 0x300c +#define WPI_MEM_PCIDEV 0x3010 +#define WPI_MEM_HW_RADIO_OFF 0x3014 +#define WPI_MEM_UCODE_CTL 0x3400 +#define WPI_MEM_UCODE_SRC 0x3404 +#define WPI_MEM_UCODE_DST 0x3408 +#define WPI_MEM_UCODE_SIZE 0x340c +#define WPI_MEM_UCODE_BASE 0x3800 + +#define WPI_MEM_TEXT_BASE 0x3490 +#define WPI_MEM_TEXT_SIZE 0x3494 +#define WPI_MEM_DATA_BASE 0x3498 +#define WPI_MEM_DATA_SIZE 0x349c + + +/* possible flags for register WPI_HWCONFIG */ +#define WPI_HW_ALM_MB (1 << 8) +#define WPI_HW_ALM_MM (1 << 9) +#define WPI_HW_SKU_MRC (1 << 10) +#define WPI_HW_REV_D (1 << 11) +#define WPI_HW_TYPE_B (1 << 12) + +/* possible flags for registers WPI_READ_MEM_ADDR/WPI_WRITE_MEM_ADDR */ +#define WPI_MEM_4 ((sizeof (uint32_t) - 1) << 24) + +/* possible values for WPI_MEM_UCODE_DST */ +#define WPI_FW_TEXT 0x00000000 + +/* possible flags for WPI_GPIO_STATUS */ +#define WPI_POWERED (1 << 9) + +/* possible flags for register WPI_RESET */ +#define WPI_NEVO_RESET (1 << 0) +#define WPI_SW_RESET (1 << 7) +#define WPI_MASTER_DISABLED (1 << 8) +#define WPI_STOP_MASTER (1 << 9) + +/* possible flags for register WPI_GPIO_CTL */ +#define WPI_GPIO_CLOCK (1 << 0) +#define WPI_GPIO_INIT (1 << 2) +#define WPI_GPIO_MAC (1 << 3) +#define WPI_GPIO_SLEEP (1 << 4) +#define WPI_GPIO_PWR_STATUS 0x07000000 +#define WPI_GPIO_PWR_SLEEP (4 << 24) + +/* possible flags for register WPI_CHICKEN */ +#define WPI_CHICKEN_RXNOLOS (1 << 23) + +/* possible flags for register WPI_PLL_CTL */ +#define WPI_PLL_INIT (1 << 24) + +/* possible flags for register WPI_UCODE_CLR */ +#define WPI_RADIO_OFF (1 << 1) +#define WPI_DISABLE_CMD (1 << 2) + +/* possible flags for WPI_RX_STATUS */ +#define WPI_RX_IDLE (1 << 24) + +/* possible flags for register WPI_UC_CTL */ +#define WPI_UC_ENABLE (1 << 30) +#define WPI_UC_RUN (1U << 31) + +/* possible flags for register WPI_INTR_CSR */ +#define WPI_ALIVE_INTR (1 << 0) +#define WPI_WAKEUP_INTR (1 << 1) +#define WPI_SW_ERROR (1 << 25) +#define WPI_TX_INTR (1 << 27) +#define WPI_HW_ERROR (1 << 29) +#define WPI_RX_INTR (1U << 31) + +#define WPI_INTR_MASK \ + (WPI_SW_ERROR | WPI_HW_ERROR | WPI_TX_INTR | WPI_RX_INTR | \ + WPI_ALIVE_INTR | WPI_WAKEUP_INTR) + +/* possible flags for register WPI_TX_STATUS */ +#define WPI_TX_IDLE(qid) (1 << ((qid) + 24) | 1 << ((qid) + 16)) + +/* possible flags for register WPI_EEPROM_CTL */ +#define WPI_EEPROM_READY (1 << 0) + +/* possible flags for register WPI_EEPROM_STATUS */ #define WPI_EEPROM_VERSION 0x00000007 -#define WPI_EEPROM_GP_IF_OWNER 0x00000180 - -/* Possible flags for register WPI_APMG_PS. */ -#define WPI_APMG_PS_PWR_SRC_MASK (3 << 24) +#define WPI_EEPROM_LOCKED 0x00000180 -/* Possible flags for registers WPI_APMG_CLK_*. */ -#define WPI_APMG_CLK_CTRL_DMA_CLK_RQT (1 << 9) -#define WPI_APMG_CLK_CTRL_BSM_CLK_RQT (1 << 11) - -/* Possible flags for register WPI_APMG_PCI_STT. */ -#define WPI_APMG_PCI_STT_L1A_DIS (1 << 11) struct wpi_shared { - uint32_t txbase[WPI_NTXQUEUES]; + uint32_t txbase[8]; uint32_t next; uint32_t reserved[2]; } __packed; #define WPI_MAX_SEG_LEN 65520 struct wpi_tx_desc { - uint8_t reserved1[3]; - uint8_t nsegs; + uint32_t flags; #define WPI_PAD32(x) (roundup2(x, 4) - (x)) struct { uint32_t addr; uint32_t len; - } __packed segs[WPI_MAX_SCATTER]; - uint8_t reserved2[28]; + } __attribute__((__packed__)) segs[WPI_MAX_SCATTER]; + uint8_t reserved[28]; } __packed; struct wpi_tx_stat { - uint8_t rtsfailcnt; - uint8_t ackfailcnt; - uint8_t btkillcnt; + uint8_t nrts; + uint8_t ntries; + uint8_t nkill; uint8_t rate; uint32_t duration; uint32_t status; -#define WPI_TX_STATUS_SUCCESS 0x01 -#define WPI_TX_STATUS_DIRECT_DONE 0x02 -#define WPI_TX_STATUS_FAIL 0x80 -#define WPI_TX_STATUS_FAIL_SHORT_LIMIT 0x82 -#define WPI_TX_STATUS_FAIL_LONG_LIMIT 0x83 -#define WPI_TX_STATUS_FAIL_FIFO_UNDERRUN 0x84 -#define WPI_TX_STATUS_FAIL_MGMNT_ABORT 0x85 -#define WPI_TX_STATUS_FAIL_NEXT_FRAG 0x86 -#define WPI_TX_STATUS_FAIL_LIFE_EXPIRE 0x87 -#define WPI_TX_STATUS_FAIL_NODE_PS 0x88 -#define WPI_TX_STATUS_FAIL_ABORTED 0x89 -#define WPI_TX_STATUS_FAIL_BT_RETRY 0x8a -#define WPI_TX_STATUS_FAIL_NODE_INVALID 0x8b -#define WPI_TX_STATUS_FAIL_FRAG_DROPPED 0x8c -#define WPI_TX_STATUS_FAIL_TID_DISABLE 0x8d -#define WPI_TX_STATUS_FAIL_FRAME_FLUSHED 0x8e -#define WPI_TX_STATUS_FAIL_INSUFFICIENT_CF_POLL 0x8f -#define WPI_TX_STATUS_FAIL_TX_LOCKED 0x90 -#define WPI_TX_STATUS_FAIL_NO_BEACON_ON_RADAR 0x91 - } __packed; struct wpi_rx_desc { @@ -287,27 +204,21 @@ struct wpi_rx_desc { #define WPI_START_SCAN 130 #define WPI_SCAN_RESULTS 131 #define WPI_STOP_SCAN 132 -#define WPI_BEACON_SENT 144 -#define WPI_RX_STATISTICS 156 -#define WPI_BEACON_STATISTICS 157 #define WPI_STATE_CHANGED 161 -#define WPI_BEACON_MISSED 162 +#define WPI_MISSED_BEACON 162 uint8_t flags; uint8_t idx; uint8_t qid; } __packed; -#define WPI_RX_DESC_QID_MSK 0x07 -#define WPI_UNSOLICITED_RX_NOTIF 0x80 - struct wpi_rx_stat { uint8_t len; #define WPI_STAT_MAXLEN 20 uint8_t id; uint8_t rssi; /* received signal strength */ -#define WPI_RSSI_OFFSET -95 +#define WPI_RSSI_OFFSET 95 uint8_t agc; /* access gain control */ uint16_t signal; @@ -317,10 +228,8 @@ struct wpi_rx_stat { struct wpi_rx_head { uint16_t chan; uint16_t flags; -#define WPI_STAT_FLAG_SHPREAMBLE (1 << 2) - uint8_t reserved; - uint8_t plcp; + uint8_t rate; uint16_t len; } __packed; @@ -330,47 +239,39 @@ struct wpi_rx_tail { #define WPI_RX_NO_OVFL_ERR (1 << 1) /* shortcut for the above */ #define WPI_RX_NOERROR (WPI_RX_NO_CRC_ERR | WPI_RX_NO_OVFL_ERR) -#define WPI_RX_CIPHER_MASK (7 << 8) -#define WPI_RX_CIPHER_CCMP (2 << 8) -#define WPI_RX_DECRYPT_MASK (3 << 11) -#define WPI_RX_DECRYPT_OK (3 << 11) - uint64_t tstamp; uint32_t tbeacon; } __packed; struct wpi_tx_cmd { uint8_t code; -#define WPI_CMD_RXON 16 -#define WPI_CMD_RXON_ASSOC 17 -#define WPI_CMD_EDCA_PARAMS 19 -#define WPI_CMD_TIMING 20 +#define WPI_CMD_CONFIGURE 16 +#define WPI_CMD_ASSOCIATE 17 +#define WPI_CMD_SET_WME 19 +#define WPI_CMD_TSF 20 #define WPI_CMD_ADD_NODE 24 -#define WPI_CMD_DEL_NODE 25 #define WPI_CMD_TX_DATA 28 #define WPI_CMD_MRR_SETUP 71 #define WPI_CMD_SET_LED 72 #define WPI_CMD_SET_POWER_MODE 119 #define WPI_CMD_SCAN 128 -#define WPI_CMD_SCAN_ABORT 129 #define WPI_CMD_SET_BEACON 145 #define WPI_CMD_TXPOWER 151 -#define WPI_CMD_BT_COEX 155 -#define WPI_CMD_GET_STATISTICS 156 +#define WPI_CMD_BLUETOOTH 155 uint8_t flags; uint8_t idx; uint8_t qid; - uint8_t data[124]; + uint8_t data[360]; } __packed; -/* Structure for command WPI_CMD_RXON. */ -struct wpi_rxon { +/* structure for WPI_CMD_CONFIGURE */ +struct wpi_config { uint8_t myaddr[IEEE80211_ADDR_LEN]; uint16_t reserved1; uint8_t bssid[IEEE80211_ADDR_LEN]; uint16_t reserved2; - uint8_t wlap[IEEE80211_ADDR_LEN]; + uint8_t wlap_bssid_addr[6]; uint16_t reserved3; uint8_t mode; #define WPI_MODE_HOSTAP 1 @@ -378,22 +279,21 @@ struct wpi_rxon { #define WPI_MODE_IBSS 4 #define WPI_MODE_MONITOR 6 - uint8_t air; + uint8_t air_propogation; uint16_t reserved4; uint8_t ofdm_mask; uint8_t cck_mask; uint16_t associd; uint32_t flags; -#define WPI_RXON_24GHZ (1 << 0) -#define WPI_RXON_CCK (1 << 1) -#define WPI_RXON_AUTO (1 << 2) -#define WPI_RXON_SHSLOT (1 << 4) -#define WPI_RXON_SHPREAMBLE (1 << 5) -#define WPI_RXON_NODIVERSITY (1 << 7) -#define WPI_RXON_ANTENNA_A (1 << 8) -#define WPI_RXON_ANTENNA_B (1 << 9) -#define WPI_RXON_TSF (1 << 15) -#define WPI_RXON_CTS_TO_SELF (1 << 30) +#define WPI_CONFIG_24GHZ (1 << 0) +#define WPI_CONFIG_CCK (1 << 1) +#define WPI_CONFIG_AUTO (1 << 2) +#define WPI_CONFIG_SHSLOT (1 << 4) +#define WPI_CONFIG_SHPREAMBLE (1 << 5) +#define WPI_CONFIG_NODIVERSITY (1 << 7) +#define WPI_CONFIG_ANTENNA_A (1 << 8) +#define WPI_CONFIG_ANTENNA_B (1 << 9) +#define WPI_CONFIG_TSF (1 << 15) uint32_t filter; #define WPI_FILTER_PROMISC (1 << 0) @@ -402,13 +302,12 @@ struct wpi_rxon { #define WPI_FILTER_NODECRYPT (1 << 3) #define WPI_FILTER_BSS (1 << 5) #define WPI_FILTER_BEACON (1 << 6) -#define WPI_FILTER_ASSOC (1 << 7) /* Accept associaton requests. */ uint8_t chan; - uint16_t reserved5; + uint16_t reserved6; } __packed; -/* Structure for command WPI_CMD_RXON_ASSOC. */ +/* structure for command WPI_CMD_ASSOCIATE */ struct wpi_assoc { uint32_t flags; uint32_t filter; @@ -417,22 +316,20 @@ struct wpi_assoc { uint16_t reserved; } __packed; -/* Structure for command WPI_CMD_EDCA_PARAMS. */ -struct wpi_edca_params { +/* structure for command WPI_CMD_SET_WME */ +struct wpi_wme_setup { uint32_t flags; -#define WPI_EDCA_UPDATE (1 << 0) - struct { uint16_t cwmin; uint16_t cwmax; uint8_t aifsn; uint8_t reserved; - uint16_t txoplimit; + uint16_t txop; } __packed ac[WME_NUM_AC]; } __packed; -/* Structure for command WPI_CMD_TIMING. */ -struct wpi_cmd_timing { +/* structure for command WPI_CMD_TSF */ +struct wpi_cmd_tsf { uint64_t tstamp; uint16_t bintval; uint16_t atim; @@ -441,102 +338,77 @@ struct wpi_cmd_timing { uint16_t reserved; } __packed; -/* Structure for command WPI_CMD_ADD_NODE. */ +/* structure for WPI_CMD_ADD_NODE */ struct wpi_node_info { uint8_t control; -#define WPI_NODE_UPDATE (1 << 0) +#define WPI_NODE_UPDATE (1 << 0) uint8_t reserved1[3]; - uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint8_t bssid[IEEE80211_ADDR_LEN]; uint16_t reserved2; uint8_t id; #define WPI_ID_BSS 0 -#define WPI_ID_IBSS_MIN 2 -#define WPI_ID_IBSS_MAX 23 #define WPI_ID_BROADCAST 24 -#define WPI_ID_UNDEFINED (uint8_t)-1 uint8_t flags; -#define WPI_FLAG_KEY_SET (1 << 0) - uint16_t reserved3; - uint16_t kflags; -#define WPI_KFLAG_CCMP (1 << 1) -#define WPI_KFLAG_KID(kid) ((kid) << 8) -#define WPI_KFLAG_MULTICAST (1 << 14) - - uint8_t tsc2; + uint16_t key_flags; + uint8_t tkip; uint8_t reserved4; uint16_t ttak[5]; uint16_t reserved5; uint8_t key[IEEE80211_KEYBUF_SIZE]; uint32_t action; -#define WPI_ACTION_SET_RATE (1 << 2) - +#define WPI_ACTION_SET_RATE 4 uint32_t mask; uint16_t tid; - uint8_t plcp; + uint8_t rate; uint8_t antenna; -#define WPI_ANTENNA_A (1 << 6) -#define WPI_ANTENNA_B (1 << 7) -#define WPI_ANTENNA_BOTH (WPI_ANTENNA_A | WPI_ANTENNA_B) - +#define WPI_ANTENNA_A (1<<6) +#define WPI_ANTENNA_B (1<<7) +#define WPI_ANTENNA_BOTH (WPI_ANTENNA_A|WPI_ANTENNA_B) uint8_t add_imm; uint8_t del_imm; uint16_t add_imm_start; } __packed; -/* Structure for command WPI_CMD_DEL_NODE. */ -struct wpi_cmd_del_node { - uint8_t count; - uint8_t reserved1[3]; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - uint16_t reserved2; -} __packed; - -/* Structure for command WPI_CMD_TX_DATA. */ +/* structure for command WPI_CMD_TX_DATA */ struct wpi_cmd_data { uint16_t len; uint16_t lnext; uint32_t flags; #define WPI_TX_NEED_RTS (1 << 1) -#define WPI_TX_NEED_CTS (1 << 2) +#define WPI_TX_NEED_CTS (1 << 2) #define WPI_TX_NEED_ACK (1 << 3) #define WPI_TX_FULL_TXOP (1 << 7) -#define WPI_TX_BT_DISABLE (1 << 12) /* bluetooth coexistence */ +#define WPI_TX_BT_DISABLE (1 << 12) /* bluetooth coexistence */ #define WPI_TX_AUTO_SEQ (1 << 13) -#define WPI_TX_MORE_FRAG (1 << 14) #define WPI_TX_INSERT_TSTAMP (1 << 16) - uint8_t plcp; + uint8_t rate; uint8_t id; uint8_t tid; uint8_t security; -#define WPI_CIPHER_WEP 1 -#define WPI_CIPHER_CCMP 2 -#define WPI_CIPHER_TKIP 3 -#define WPI_CIPHER_WEP104 9 - uint8_t key[IEEE80211_KEYBUF_SIZE]; uint8_t tkip[IEEE80211_WEP_MICLEN]; uint32_t fnext; uint32_t lifetime; #define WPI_LIFETIME_INFINITE 0xffffffff - uint8_t ofdm_mask; uint8_t cck_mask; uint8_t rts_ntries; uint8_t data_ntries; uint16_t timeout; uint16_t txop; + struct ieee80211_frame wh; } __packed; -/* Structure for command WPI_CMD_SET_BEACON. */ +/* structure for command WPI_CMD_SET_BEACON */ struct wpi_cmd_beacon { uint16_t len; uint16_t reserved1; uint32_t flags; /* same as wpi_cmd_data */ - uint8_t plcp; + uint8_t rate; uint8_t id; uint8_t reserved2[30]; uint32_t lifetime; @@ -546,35 +418,41 @@ struct wpi_cmd_beacon { uint16_t tim; uint8_t timsz; uint8_t reserved4; + struct ieee80211_frame wh; } __packed; -/* Structure for notification WPI_BEACON_MISSED. */ -struct wpi_beacon_missed { - uint32_t consecutive; - uint32_t total; - uint32_t expected; - uint32_t received; +/* structure for notification WPI_MISSED_BEACON */ +struct wpi_missed_beacon { + uint32_t consecutive; + uint32_t total; + uint32_t expected; + uint32_t received; } __packed; -/* Structure for command WPI_CMD_MRR_SETUP. */ -#define WPI_RIDX_MAX 11 +/* structure for WPI_CMD_MRR_SETUP */ struct wpi_mrr_setup { - uint32_t which; + uint8_t which; #define WPI_MRR_CTL 0 #define WPI_MRR_DATA 1 + uint8_t reserved[3]; + struct { - uint8_t plcp; + uint8_t signal; uint8_t flags; uint8_t ntries; -#define WPI_NTRIES_DEFAULT 2 - uint8_t next; - } __packed rates[WPI_RIDX_MAX + 1]; +#define WPI_OFDM6 0 +#define WPI_OFDM54 7 +#define WPI_CCK1 8 +#define WPI_CCK2 9 +#define WPI_CCK11 11 + + } __attribute__((__packed__)) rates[WPI_CCK11 + 1]; } __packed; -/* Structure for command WPI_CMD_SET_LED. */ +/* structure for WPI_CMD_SET_LED */ struct wpi_cmd_led { uint32_t unit; /* multiplier (in usecs) */ uint8_t which; @@ -586,133 +464,136 @@ struct wpi_cmd_led { uint8_t reserved; } __packed; -/* Structure for command WPI_CMD_SET_POWER_MODE. */ -struct wpi_pmgt_cmd { - uint16_t flags; -#define WPI_PS_ALLOW_SLEEP (1 << 0) -#define WPI_PS_NOTIFY (1 << 1) -#define WPI_PS_SLEEP_OVER_DTIM (1 << 2) -#define WPI_PS_PCI_PMGT (1 << 3) - - uint8_t reserved[2]; - uint32_t rxtimeout; - uint32_t txtimeout; - uint32_t intval[5]; -} __packed; - -/* Structures for command WPI_CMD_SCAN. */ -#define WPI_SCAN_MAX_ESSIDS 4 -struct wpi_scan_essid { - uint8_t id; - uint8_t len; - uint8_t data[IEEE80211_NWID_LEN]; +/* structure for WPI_CMD_SET_POWER_MODE */ +struct wpi_power { + uint32_t flags; +#define WPI_POWER_CAM 0 /* constantly awake mode */ + uint32_t rx_timeout; + uint32_t tx_timeout; + uint32_t sleep[5]; } __packed; +/* structure for command WPI_CMD_SCAN */ struct wpi_scan_hdr { uint16_t len; uint8_t reserved1; uint8_t nchan; - uint16_t quiet_time; /* timeout in milliseconds */ -#define WPI_QUIET_TIME_DEFAULT 10 - - uint16_t quiet_threshold; /* min # of packets */ - uint16_t crc_threshold; + uint16_t quiet; + uint16_t threshold; + uint16_t promotion; uint16_t reserved2; - uint32_t max_svc; /* background scans */ - uint32_t pause_svc; /* background scans */ -#define WPI_PAUSE_MAX_TIME ((1 << 20) - 1) -#define WPI_PAUSE_SCAN(nbeacons, time) ((nbeacons << 24) | time) - + uint32_t maxtimeout; + uint32_t suspend; uint32_t flags; uint32_t filter; - /* Followed by a struct wpi_cmd_data. */ - /* Followed by an array of 4 structs wpi_scan_essid. */ - /* Followed by probe request body. */ - /* Followed by an array of ``nchan'' structs wpi_scan_chan. */ +struct { + uint16_t len; + uint16_t lnext; + uint32_t flags; + uint8_t rate; + uint8_t id; + uint8_t tid; + uint8_t security; + uint8_t key[IEEE80211_KEYBUF_SIZE]; + uint8_t tkip[IEEE80211_WEP_MICLEN]; + uint32_t fnext; + uint32_t lifetime; + uint8_t ofdm_mask; + uint8_t cck_mask; + uint8_t rts_ntries; + uint8_t data_ntries; + uint16_t timeout; + uint16_t txop; +} tx __attribute__((__packed__)); + +#define WPI_SCAN_MAX_ESSIDS 4 + struct { + uint8_t id; + uint8_t esslen; + uint8_t essid[32]; + }scan_essids[WPI_SCAN_MAX_ESSIDS]; + /* followed by probe request body */ + /* followed by nchan x wpi_scan_chan */ } __packed; struct wpi_scan_chan { uint8_t flags; -#define WPI_CHAN_ACTIVE (1 << 0) -#define WPI_CHAN_NPBREQS(x) (((1 << (x)) - 1) << 1) - uint8_t chan; - uint8_t rf_gain; - uint8_t dsp_gain; +#define WPI_CHAN_ACTIVE (1 << 0) +#define WPI_CHAN_DIRECT (1 << 1) + uint8_t gain_radio; + uint8_t gain_dsp; uint16_t active; /* msecs */ uint16_t passive; /* msecs */ } __packed; -#define WPI_SCAN_CRC_TH_DEFAULT htole16(1) -#define WPI_SCAN_CRC_TH_NEVER htole16(0xffff) - -/* Maximum size of a scan command. */ -#define WPI_SCAN_MAXSZ (MCLBYTES - 4) - -#define WPI_ACTIVE_DWELL_TIME_2GHZ (30) /* all times in msec */ -#define WPI_ACTIVE_DWELL_TIME_5GHZ (20) -#define WPI_ACTIVE_DWELL_FACTOR_2GHZ ( 3) -#define WPI_ACTIVE_DWELL_FACTOR_5GHZ ( 2) - -#define WPI_PASSIVE_DWELL_TIME_2GHZ ( 20) -#define WPI_PASSIVE_DWELL_TIME_5GHZ ( 10) -#define WPI_PASSIVE_DWELL_BASE (100) -#define WPI_CHANNEL_TUNE_TIME ( 6) +/* structure for WPI_CMD_BLUETOOTH */ +struct wpi_bluetooth { + uint8_t flags; + uint8_t lead; + uint8_t kill; + uint8_t reserved; + uint32_t ack; + uint32_t cts; +} __packed; -/* Structure for command WPI_CMD_TXPOWER. */ +/* structure for command WPI_CMD_TXPOWER */ struct wpi_cmd_txpower { - uint8_t band; -#define WPI_BAND_5GHZ 0 -#define WPI_BAND_2GHZ 1 + uint8_t band; +#define WPI_RATE_5GHZ 0 +#define WPI_RATE_2GHZ 1 uint8_t reserved; - uint16_t chan; + uint16_t channel; +#define WPI_RATE_MAPPING_COUNT 12 struct { - uint8_t plcp; - uint8_t rf_gain; - uint8_t dsp_gain; - uint8_t reserved; - } __packed rates[WPI_RIDX_MAX + 1]; + uint8_t rate; + uint8_t gain_radio; + uint8_t gain_dsp; + uint8_t reserved; + } __packed rates [WPI_RATE_MAPPING_COUNT]; } __packed; -/* Structure for command WPI_CMD_BT_COEX. */ -struct wpi_bluetooth { - uint8_t flags; -#define WPI_BT_COEX_DISABLE 0 -#define WPI_BT_COEX_MODE_2WIRE 1 -#define WPI_BT_COEX_MODE_3WIRE 2 -#define WPI_BT_COEX_MODE_4WIRE 3 - uint8_t lead_time; -#define WPI_BT_LEAD_TIME_DEF 30 - uint8_t max_kill; -#define WPI_BT_MAX_KILL_DEF 5 +#define WPI_FW_MAIN_TEXT_MAXSZ (80 * 1024 ) +#define WPI_FW_MAIN_DATA_MAXSZ (32 * 1024 ) +#define WPI_FW_INIT_TEXT_MAXSZ (80 * 1024 ) +#define WPI_FW_INIT_DATA_MAXSZ (32 * 1024 ) +#define WPI_FW_BOOT_TEXT_MAXSZ 1024 - uint8_t reserved; - uint32_t kill_ack; - uint32_t kill_cts; +#define WPI_FW_UPDATED (1 << 31 ) + +/* firmware image header */ +struct wpi_firmware_hdr { + +#define WPI_FW_MINVERSION 2144 + + uint32_t version; + uint32_t rtextsz; + uint32_t rdatasz; + uint32_t itextsz; + uint32_t idatasz; + uint32_t btextsz; } __packed; -/* Structure for WPI_UC_READY notification. */ +/* structure for WPI_UC_READY notification */ struct wpi_ucode_info { - uint8_t minor; - uint8_t major; - uint16_t reserved1; + uint32_t version; uint8_t revision[8]; uint8_t type; uint8_t subtype; - uint16_t reserved2; + uint16_t reserved; uint32_t logptr; - uint32_t errptr; - uint32_t tstamp; + uint32_t errorptr; + uint32_t timestamp; uint32_t valid; } __packed; -/* Structure for WPI_START_SCAN notification. */ +/* structure for WPI_START_SCAN notification */ struct wpi_start_scan { uint64_t tstamp; uint32_t tbeacon; @@ -722,126 +603,18 @@ struct wpi_start_scan { uint32_t status; } __packed; -/* Structure for WPI_STOP_SCAN notification. */ +/* structure for WPI_STOP_SCAN notification */ struct wpi_stop_scan { uint8_t nchan; uint8_t status; -#define WPI_SCAN_COMPLETED 1 -#define WPI_SCAN_ABORTED 2 - uint8_t reserved; uint8_t chan; uint64_t tsf; } __packed; -/* Structures for WPI_{RX,BEACON}_STATISTICS notification. */ -struct wpi_rx_phy_stats { - uint32_t ina; - uint32_t fina; - uint32_t bad_plcp; - uint32_t bad_crc32; - uint32_t overrun; - uint32_t eoverrun; - uint32_t good_crc32; - uint32_t fa; - uint32_t bad_fina_sync; - uint32_t sfd_timeout; - uint32_t fina_timeout; - uint32_t no_rts_ack; - uint32_t rxe_limit; - uint32_t ack; - uint32_t cts; -} __packed; - -struct wpi_rx_general_stats { - uint32_t bad_cts; - uint32_t bad_ack; - uint32_t not_bss; - uint32_t filtered; - uint32_t bad_chan; -} __packed; - -struct wpi_rx_stats { - struct wpi_rx_phy_stats ofdm; - struct wpi_rx_phy_stats cck; - struct wpi_rx_general_stats general; -} __packed; - -struct wpi_tx_stats { - uint32_t preamble; - uint32_t rx_detected; - uint32_t bt_defer; - uint32_t bt_kill; - uint32_t short_len; - uint32_t cts_timeout; - uint32_t ack_timeout; - uint32_t exp_ack; - uint32_t ack; -} __packed; - -struct wpi_general_stats { - uint32_t temp; - uint32_t burst_check; - uint32_t burst; - uint32_t reserved[4]; - uint32_t sleep; - uint32_t slot_out; - uint32_t slot_idle; - uint32_t ttl_tstamp; - uint32_t tx_ant_a; - uint32_t tx_ant_b; - uint32_t exec; - uint32_t probe; -} __packed; - -struct wpi_stats { - uint32_t flags; - struct wpi_rx_stats rx; - struct wpi_tx_stats tx; - struct wpi_general_stats general; -} __packed; - -/* Possible flags for command WPI_CMD_GET_STATISTICS. */ -#define WPI_STATISTICS_BEACON_DISABLE (1 << 1) - - -/* Firmware error dump entry. */ -struct wpi_fw_dump { - uint32_t desc; - uint32_t time; - uint32_t blink[2]; - uint32_t ilink[2]; - uint32_t data; -} __packed; - -/* Firmware image file header. */ -struct wpi_firmware_hdr { - -#define WPI_FW_MINVERSION 2144 -#define WPI_FW_NAME "wpifw" - - uint16_t driver; - uint8_t minor; - uint8_t major; - uint32_t rtextsz; - uint32_t rdatasz; - uint32_t itextsz; - uint32_t idatasz; - uint32_t btextsz; -} __packed; - -#define WPI_FW_TEXT_MAXSZ ( 80 * 1024 ) -#define WPI_FW_DATA_MAXSZ ( 32 * 1024 ) -#define WPI_FW_BOOT_TEXT_MAXSZ 1024 - -#define WPI_FW_UPDATED (1U << 31 ) - -/* - * Offsets into EEPROM. - */ #define WPI_EEPROM_MAC 0x015 #define WPI_EEPROM_REVISION 0x035 -#define WPI_EEPROM_SKU_CAP 0x045 +#define WPI_EEPROM_CAPABILITIES 0x045 #define WPI_EEPROM_TYPE 0x04a #define WPI_EEPROM_DOMAIN 0x060 #define WPI_EEPROM_BAND1 0x063 @@ -853,66 +626,49 @@ struct wpi_firmware_hdr { struct wpi_eeprom_chan { uint8_t flags; -#define WPI_EEPROM_CHAN_VALID (1 << 0) -#define WPI_EEPROM_CHAN_IBSS (1 << 1) -#define WPI_EEPROM_CHAN_ACTIVE (1 << 3) -#define WPI_EEPROM_CHAN_RADAR (1 << 4) +#define WPI_EEPROM_CHAN_VALID (1<<0) +#define WPI_EEPROM_CHAN_IBSS (1<<1) +#define WPI_EEPROM_CHAN_ACTIVE (1<<3) +#define WPI_EEPROM_CHAN_RADAR (1<<4) int8_t maxpwr; } __packed; struct wpi_eeprom_sample { - uint8_t index; - int8_t power; - uint16_t volt; -} __packed; + uint8_t index; + int8_t power; + uint16_t volt; +}; #define WPI_POWER_GROUPS_COUNT 5 + struct wpi_eeprom_group { - struct wpi_eeprom_sample samples[5]; - int32_t coef[5]; - int32_t corr[5]; - int8_t maxpwr; - uint8_t chan; - int16_t temp; + struct wpi_eeprom_sample samples[5]; + int32_t coef[5]; + int32_t corr[5]; + int8_t maxpwr; + uint8_t chan; + int16_t temp; } __packed; -#define WPI_CHAN_BANDS_COUNT 5 +#define WPI_CHAN_BANDS_COUNT 5 #define WPI_MAX_CHAN_PER_BAND 14 -static const struct wpi_chan_band { - uint32_t addr; /* offset in EEPROM */ - uint8_t nchan; - uint8_t chan[WPI_MAX_CHAN_PER_BAND]; -} wpi_bands[] = { - /* 20MHz channels, 2GHz band. */ - { WPI_EEPROM_BAND1, 14, - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } }, - /* 20MHz channels, 5GHz band. */ - { WPI_EEPROM_BAND2, 13, - { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } }, - { WPI_EEPROM_BAND3, 12, - { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } }, - { WPI_EEPROM_BAND4, 11, - { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } }, - { WPI_EEPROM_BAND5, 6, - { 145, 149, 153, 157, 161, 165 } } -}; -/* HW rate indices. */ -#define WPI_RIDX_OFDM6 0 -#define WPI_RIDX_OFDM36 5 -#define WPI_RIDX_OFDM48 6 -#define WPI_RIDX_OFDM54 7 -#define WPI_RIDX_CCK1 8 -#define WPI_RIDX_CCK2 9 -#define WPI_RIDX_CCK11 11 - -static const uint8_t wpi_ridx_to_plcp[] = { - /* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */ - /* R1-R4 (ral/ural is R4-R1) */ - 0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, - /* CCK: device-dependent */ - 10, 20, 55, 110 +static const struct wpi_chan_band { + uint32_t addr; /* offset in EEPROM */ + uint8_t nchan; + uint8_t chan[WPI_MAX_CHAN_PER_BAND]; +} wpi_bands[5] = { + { WPI_EEPROM_BAND1, 14, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }}, + { WPI_EEPROM_BAND2, 13, + { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 }}, + { WPI_EEPROM_BAND3, 12, + { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 }}, + { WPI_EEPROM_BAND4, 11, + { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 }}, + { WPI_EEPROM_BAND5, 6, + { 145, 149, 153, 157, 161, 165 }} }; #define WPI_MAX_PWR_INDEX 77 @@ -922,25 +678,25 @@ static const uint8_t wpi_ridx_to_plcp[] = { * the reference driver.) */ static const uint8_t wpi_rf_gain_2ghz[WPI_MAX_PWR_INDEX + 1] = { - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3, - 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63, - 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03, - 0x03 + 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb, + 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3, + 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63, + 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03, + 0x03 }; static const uint8_t wpi_rf_gain_5ghz[WPI_MAX_PWR_INDEX + 1] = { - 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xbb, 0xbb, 0x9b, 0x9b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x5b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1b, 0x1b, - 0x1b, 0x73, 0x73, 0x73, 0x53, 0x53, 0x53, 0x53, 0x53, 0x33, 0x33, - 0x33, 0x33, 0x13, 0x13, 0x13, 0x13, 0x13, 0xab, 0xab, 0xab, 0x8b, - 0x8b, 0x8b, 0x8b, 0x6b, 0x6b, 0x6b, 0x6b, 0x4b, 0x4b, 0x4b, 0x4b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x0b, 0x0b, 0x0b, 0x0b, 0x83, 0x83, 0x63, - 0x63, 0x63, 0x63, 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, - 0x03 + 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xbb, 0xbb, 0x9b, 0x9b, 0x7b, 0x7b, + 0x7b, 0x7b, 0x5b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1b, 0x1b, + 0x1b, 0x73, 0x73, 0x73, 0x53, 0x53, 0x53, 0x53, 0x53, 0x33, 0x33, + 0x33, 0x33, 0x13, 0x13, 0x13, 0x13, 0x13, 0xab, 0xab, 0xab, 0x8b, + 0x8b, 0x8b, 0x8b, 0x6b, 0x6b, 0x6b, 0x6b, 0x4b, 0x4b, 0x4b, 0x4b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x0b, 0x0b, 0x0b, 0x0b, 0x83, 0x83, 0x63, + 0x63, 0x63, 0x63, 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, + 0x03 }; /* @@ -948,89 +704,34 @@ static const uint8_t wpi_rf_gain_5ghz[WPI_MAX_PWR_INDEX + 1] = { * from the reference driver.) */ static const uint8_t wpi_dsp_gain_2ghz[WPI_MAX_PWR_INDEX + 1] = { - 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c, - 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b, - 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d, - 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74, - 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71, - 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, - 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, - 0x5f + 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c, + 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b, + 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d, + 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74, + 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71, + 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, + 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, + 0x5f }; static const uint8_t wpi_dsp_gain_5ghz[WPI_MAX_PWR_INDEX + 1] = { - 0x7f, 0x78, 0x72, 0x77, 0x65, 0x71, 0x66, 0x72, 0x67, 0x75, 0x6b, - 0x63, 0x5c, 0x6c, 0x7d, 0x76, 0x6d, 0x66, 0x60, 0x5a, 0x68, 0x62, - 0x5c, 0x76, 0x6f, 0x68, 0x7e, 0x79, 0x71, 0x69, 0x63, 0x76, 0x6f, - 0x68, 0x62, 0x74, 0x6d, 0x66, 0x62, 0x5d, 0x71, 0x6b, 0x63, 0x78, - 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, - 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x6b, 0x63, 0x78, - 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, - 0x78 + 0x7f, 0x78, 0x72, 0x77, 0x65, 0x71, 0x66, 0x72, 0x67, 0x75, 0x6b, + 0x63, 0x5c, 0x6c, 0x7d, 0x76, 0x6d, 0x66, 0x60, 0x5a, 0x68, 0x62, + 0x5c, 0x76, 0x6f, 0x68, 0x7e, 0x79, 0x71, 0x69, 0x63, 0x76, 0x6f, + 0x68, 0x62, 0x74, 0x6d, 0x66, 0x62, 0x5d, 0x71, 0x6b, 0x63, 0x78, + 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, + 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x6b, 0x63, 0x78, + 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, 0x78, 0x71, 0x6b, 0x63, + 0x78 }; -/* - * Power saving settings (values obtained from the reference driver.) - */ -#define WPI_NDTIMRANGES 2 -#define WPI_NPOWERLEVELS 6 -static const struct wpi_pmgt { - uint32_t rxtimeout; - uint32_t txtimeout; - uint32_t intval[5]; - int skip_dtim; -} wpi_pmgt[WPI_NDTIMRANGES][WPI_NPOWERLEVELS] = { - /* DTIM <= 10 */ - { - { 0, 0, { 0, 0, 0, 0, 0 }, 0 }, /* CAM */ - { 200, 500, { 1, 2, 3, 4, 4 }, 0 }, /* PS level 1 */ - { 200, 300, { 2, 4, 6, 7, 7 }, 0 }, /* PS level 2 */ - { 50, 100, { 2, 6, 9, 9, 10 }, 0 }, /* PS level 3 */ - { 50, 25, { 2, 7, 9, 9, 10 }, 1 }, /* PS level 4 */ - { 25, 25, { 4, 7, 10, 10, 10 }, 1 } /* PS level 5 */ - }, - /* DTIM >= 11 */ - { - { 0, 0, { 0, 0, 0, 0, 0 }, 0 }, /* CAM */ - { 200, 500, { 1, 2, 3, 4, -1 }, 0 }, /* PS level 1 */ - { 200, 300, { 2, 4, 6, 7, -1 }, 0 }, /* PS level 2 */ - { 50, 100, { 2, 6, 9, 9, -1 }, 0 }, /* PS level 3 */ - { 50, 25, { 2, 7, 9, 9, -1 }, 0 }, /* PS level 4 */ - { 25, 25, { 4, 7, 10, 10, -1 }, 0 } /* PS level 5 */ - } -}; - -/* Firmware errors. */ -static const char * const wpi_fw_errmsg[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT", - "SYSASSERT", - "FATAL_ERROR" -}; #define WPI_READ(sc, reg) \ - bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) + bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) #define WPI_WRITE(sc, reg, val) \ - bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) + bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) #define WPI_WRITE_REGION_4(sc, offset, datap, count) \ - bus_space_write_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \ - (datap), (count)) - -#define WPI_SETBITS(sc, reg, mask) \ - WPI_WRITE(sc, reg, WPI_READ(sc, reg) | (mask)) - -#define WPI_CLRBITS(sc, reg, mask) \ - WPI_WRITE(sc, reg, WPI_READ(sc, reg) & ~(mask)) - -#define WPI_BARRIER_WRITE(sc) \ - bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \ - BUS_SPACE_BARRIER_WRITE) - -#define WPI_BARRIER_READ_WRITE(sc) \ - bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \ - BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) + bus_space_write_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \ + (datap), (count)) diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h index 7a65b72..e579264 100644 --- a/sys/dev/wpi/if_wpivar.h +++ b/sys/dev/wpi/if_wpivar.h @@ -16,6 +16,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + struct wpi_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint64_t wr_tsft; @@ -26,7 +28,7 @@ struct wpi_rx_radiotap_header { int8_t wr_dbm_antsignal; int8_t wr_dbm_antnoise; uint8_t wr_antenna; -} __packed; +}; #define WPI_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ @@ -43,7 +45,8 @@ struct wpi_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed; + uint8_t wt_hwqueue; +}; #define WPI_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ @@ -52,15 +55,16 @@ struct wpi_tx_radiotap_header { struct wpi_dma_info { bus_dma_tag_t tag; - bus_dmamap_t map; - bus_addr_t paddr; - caddr_t vaddr; + bus_dmamap_t map; + bus_addr_t paddr; /* aligned p address */ + bus_addr_t paddr_start; /* possibly unaligned p start*/ + caddr_t vaddr; /* aligned v address */ + caddr_t vaddr_start; /* possibly unaligned v start */ bus_size_t size; }; struct wpi_tx_data { bus_dmamap_t map; - bus_addr_t cmd_paddr; struct mbuf *m; struct ieee80211_node *ni; }; @@ -70,17 +74,19 @@ struct wpi_tx_ring { struct wpi_dma_info cmd_dma; struct wpi_tx_desc *desc; struct wpi_tx_cmd *cmd; - struct wpi_tx_data data[WPI_TX_RING_COUNT]; + struct wpi_tx_data *data; bus_dma_tag_t data_dmat; int qid; + int count; int queued; int cur; - int update; }; +#define WPI_RBUF_COUNT ( WPI_RX_RING_COUNT + 16 ) + struct wpi_rx_data { - struct mbuf *m; - bus_dmamap_t map; + bus_dmamap_t map; + struct mbuf *m; }; struct wpi_rx_ring { @@ -89,14 +95,16 @@ struct wpi_rx_ring { struct wpi_rx_data data[WPI_RX_RING_COUNT]; bus_dma_tag_t data_dmat; int cur; - int update; }; -struct wpi_node { - struct ieee80211_node ni; /* must be the first */ - uint8_t id; +struct wpi_amrr { + struct ieee80211_node ni; /* must be the first */ + int txcnt; + int retrycnt; + int success; + int success_threshold; + int recovery; }; -#define WPI_NODE(ni) ((struct wpi_node *)(ni)) struct wpi_power_sample { uint8_t index; @@ -111,189 +119,84 @@ struct wpi_power_group { int16_t temp; }; -struct wpi_buf { - uint8_t data[56]; /* sizeof(struct wpi_cmd_beacon) */ - struct ieee80211_node *ni; - struct mbuf *m; - size_t size; - int code; - int ac; -}; - struct wpi_vap { - struct ieee80211vap wv_vap; - - struct wpi_buf wv_bcbuf; - struct ieee80211_beacon_offsets wv_boff; - struct mtx wv_mtx; + struct ieee80211vap vap; - uint32_t wv_gtk; -#define WPI_VAP_KEY(kid) (1 << kid) - - int (*wv_newstate)(struct ieee80211vap *, + int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); - void (*wv_recv_mgmt)(struct ieee80211_node *, - struct mbuf *, int, int, int); }; #define WPI_VAP(vap) ((struct wpi_vap *)(vap)) -#define WPI_VAP_LOCK_INIT(_wvp) \ - mtx_init(&(_wvp)->wv_mtx, "lock for wv_bcbuf/wv_boff structures", \ - NULL, MTX_DEF) -#define WPI_VAP_LOCK(_wvp) mtx_lock(&(_wvp)->wv_mtx) -#define WPI_VAP_UNLOCK(_wvp) mtx_unlock(&(_wvp)->wv_mtx) -#define WPI_VAP_LOCK_ASSERT(_wvp) mtx_assert(&(_wvp)->wv_mtx, MA_OWNED) -#define WPI_VAP_LOCK_DESTROY(_wvp) mtx_destroy(&(_wvp)->wv_mtx) - -struct wpi_fw_part { - const uint8_t *text; - uint32_t textsz; - const uint8_t *data; - uint32_t datasz; -}; - -struct wpi_fw_info { - const uint8_t *data; - size_t size; - struct wpi_fw_part init; - struct wpi_fw_part main; - struct wpi_fw_part boot; -}; - struct wpi_softc { device_t sc_dev; - struct ifnet *sc_ifp; - int sc_debug; - - int sc_flags; -#define WPI_PS_PATH (1 << 0) - struct mtx sc_mtx; - struct mtx tx_mtx; - /* Shared area. */ + /* Flags indicating the current state the driver + * expects the hardware to be in + */ + uint32_t flags; +#define WPI_FLAG_HW_RADIO_OFF (1 << 0) +#define WPI_FLAG_BUSY (1 << 1) +#define WPI_FLAG_AUTH (1 << 2) + + /* shared area */ struct wpi_dma_info shared_dma; struct wpi_shared *shared; - struct wpi_tx_ring txq[WPI_NTXQUEUES]; - struct mtx txq_mtx; - struct mtx txq_state_mtx; - uint32_t txq_active; - + struct wpi_tx_ring txq[WME_NUM_AC]; + struct wpi_tx_ring cmdq; struct wpi_rx_ring rxq; - uint64_t rx_tstamp; - /* TX Thermal Callibration. */ + /* TX Thermal Callibration */ struct callout calib_to; int calib_cnt; - struct callout scan_timeout; - struct callout tx_timeout; - - /* Watch dog timer. */ - struct callout watchdog_rfkill; - - /* Firmware image. */ - struct wpi_fw_info fw; - uint32_t errptr; + /* Watch dog timer */ + struct callout watchdog_to; + /* Hardware switch polling timer */ + struct callout hwswitch_to; struct resource *irq; struct resource *mem; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; void *sc_ih; - bus_size_t sc_sz; - int sc_cap_off; /* PCIe Capabilities. */ - - struct wpi_rxon rxon; - struct mtx rxon_mtx; + struct wpi_config config; int temp; - uint32_t qfullmsk; - uint32_t nodesmsk; - struct mtx nt_mtx; - void (*sc_node_free)(struct ieee80211_node *); - void (*sc_update_rx_ring)(struct wpi_softc *); - void (*sc_update_tx_ring)(struct wpi_softc *, - struct wpi_tx_ring *); + int sc_tx_timer; + int sc_scan_timer; + + struct bpf_if *sc_drvbpf; - struct wpi_rx_radiotap_header sc_rxtap; - struct wpi_tx_radiotap_header sc_txtap; + struct wpi_rx_radiotap_header sc_rxtap; + struct wpi_tx_radiotap_header sc_txtap; - /* Firmware image. */ + /* firmware image */ const struct firmware *fw_fp; - /* Firmware DMA transfer. */ + /* firmware DMA transfer */ struct wpi_dma_info fw_dma; - /* Tasks used by the driver. */ - struct task sc_reinittask; - struct task sc_radiooff_task; - struct task sc_radioon_task; - struct task sc_start_task; + /* Tasks used by the driver */ + struct task sc_restarttask; /* reset firmware task */ + struct task sc_radiotask; /* reset rf task */ - /* Taskqueue */ - struct taskqueue *sc_tq; - - /* Eeprom info. */ + /* Eeprom info */ uint8_t cap; uint16_t rev; uint8_t type; - struct wpi_eeprom_chan - eeprom_channels[WPI_CHAN_BANDS_COUNT][WPI_MAX_CHAN_PER_BAND]; struct wpi_power_group groups[WPI_POWER_GROUPS_COUNT]; int8_t maxpwr[IEEE80211_CHAN_MAX]; - char domain[4]; /* Regulatory domain. */ + char domain[4]; /*reglatory domain XXX */ }; - -/* - * Locking order: - * 1. WPI_LOCK; - * 2. WPI_RXON_LOCK; - * 3. WPI_TX_LOCK; - * 4. WPI_NT_LOCK / WPI_VAP_LOCK; - * 5. WPI_TXQ_LOCK; - * 6. WPI_TXQ_STATE_LOCK; - */ - #define WPI_LOCK_INIT(_sc) \ mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ - MTX_NETWORK_LOCK, MTX_DEF) + MTX_NETWORK_LOCK, MTX_DEF) #define WPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define WPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define WPI_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) +#define WPI_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define WPI_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) - -#define WPI_RXON_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->rxon_mtx, "lock for wpi_rxon structure", NULL, MTX_DEF) -#define WPI_RXON_LOCK(_sc) mtx_lock(&(_sc)->rxon_mtx) -#define WPI_RXON_UNLOCK(_sc) mtx_unlock(&(_sc)->rxon_mtx) -#define WPI_RXON_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rxon_mtx, MA_OWNED) -#define WPI_RXON_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rxon_mtx) - -#define WPI_TX_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->tx_mtx, "tx path lock", NULL, MTX_DEF) -#define WPI_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) -#define WPI_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx) -#define WPI_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) - -#define WPI_NT_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->nt_mtx, "node table lock", NULL, MTX_DEF) -#define WPI_NT_LOCK(_sc) mtx_lock(&(_sc)->nt_mtx) -#define WPI_NT_UNLOCK(_sc) mtx_unlock(&(_sc)->nt_mtx) -#define WPI_NT_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->nt_mtx) - -#define WPI_TXQ_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->txq_mtx, "txq/cmdq lock", NULL, MTX_DEF) -#define WPI_TXQ_LOCK(_sc) mtx_lock(&(_sc)->txq_mtx) -#define WPI_TXQ_UNLOCK(_sc) mtx_unlock(&(_sc)->txq_mtx) -#define WPI_TXQ_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->txq_mtx) - -#define WPI_TXQ_STATE_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->txq_state_mtx, "txq state lock", NULL, MTX_DEF) -#define WPI_TXQ_STATE_LOCK(_sc) mtx_lock(&(_sc)->txq_state_mtx) -#define WPI_TXQ_STATE_UNLOCK(_sc) mtx_unlock(&(_sc)->txq_state_mtx) -#define WPI_TXQ_STATE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->txq_state_mtx) -- cgit v1.1