Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/usb/wlan/if_run.c
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
#define RUN_DEBUG | #define RUN_DEBUG | ||||
#endif | #endif | ||||
#ifdef RUN_DEBUG | #ifdef RUN_DEBUG | ||||
int run_debug = 0; | int run_debug = 0; | ||||
static SYSCTL_NODE(_hw_usb, OID_AUTO, run, CTLFLAG_RW, 0, "USB run"); | 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_RWTUN, &run_debug, 0, | ||||
"run debug level"); | "run debug level"); | ||||
enum { | |||||
RUN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ | |||||
RUN_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ | |||||
RUN_DEBUG_RECV = 0x00000004, /* basic recv operation */ | |||||
RUN_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ | |||||
RUN_DEBUG_STATE = 0x00000010, /* 802.11 state transitions */ | |||||
RUN_DEBUG_RATE = 0x00000020, /* rate adaptation */ | |||||
RUN_DEBUG_USB = 0x00000040, /* usb requests */ | |||||
RUN_DEBUG_FIRMWARE = 0x00000080, /* firmware(9) loading debug */ | |||||
RUN_DEBUG_BEACON = 0x00000100, /* beacon handling */ | |||||
RUN_DEBUG_INTR = 0x00000200, /* ISR */ | |||||
RUN_DEBUG_TEMP = 0x00000400, /* temperature calibration */ | |||||
RUN_DEBUG_ROM = 0x00000800, /* various ROM info */ | |||||
RUN_DEBUG_KEY = 0x00001000, /* crypto keys management */ | |||||
RUN_DEBUG_TXPWR = 0x00002000, /* dump Tx power values */ | |||||
RUN_DEBUG_RSSI = 0x00004000, /* dump RSSI lookups */ | |||||
RUN_DEBUG_RESET = 0x00008000, /* initialization progress */ | |||||
RUN_DEBUG_CALIB = 0x00010000, /* calibration progress */ | |||||
RUN_DEBUG_CMD = 0x00010000, /* command queue */ | |||||
RUN_DEBUG_ANY = 0xffffffff | |||||
}; | |||||
#define RUN_DPRINTF(_sc, _m, ...) do { \ | |||||
if (run_debug & (_m)) \ | |||||
device_printf((_sc)->sc_dev, __VA_ARGS__); \ | |||||
} while(0) | |||||
#else | |||||
#define RUN_DPRINTF(_sc, _m, ...) do { (void) _sc; } while (0) | |||||
#endif | #endif | ||||
#define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh) | #define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh) | ||||
/* | /* | ||||
* Because of LOR in run_key_delete(), use atomic instead. | * Because of LOR in run_key_delete(), use atomic instead. | ||||
* '& RUN_CMDQ_MASQ' is to loop cmdq[]. | * '& RUN_CMDQ_MASQ' is to loop cmdq[]. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 878 Lines • ▼ Show 20 Lines | for (i = 0; i < RUN_VAP_MAX; i++) { | ||||
} | } | ||||
} | } | ||||
if (sc->rvp_cnt++ == 0) | if (sc->rvp_cnt++ == 0) | ||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
if (opmode == IEEE80211_M_HOSTAP) | if (opmode == IEEE80211_M_HOSTAP) | ||||
sc->cmdq_run = RUN_CMDQ_GO; | sc->cmdq_run = RUN_CMDQ_GO; | ||||
DPRINTF("rvp_id=%d bmap=%x rvp_cnt=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_STATE, "rvp_id=%d bmap=%x rvp_cnt=%d\n", | ||||
rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt); | rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt); | ||||
return (vap); | return (vap); | ||||
} | } | ||||
static void | static void | ||||
run_vap_delete(struct ieee80211vap *vap) | run_vap_delete(struct ieee80211vap *vap) | ||||
{ | { | ||||
Show All 15 Lines | run_vap_delete(struct ieee80211vap *vap) | ||||
rvp_id = rvp->rvp_id; | rvp_id = rvp->rvp_id; | ||||
sc->ratectl_run &= ~(1 << rvp_id); | sc->ratectl_run &= ~(1 << rvp_id); | ||||
sc->rvp_bmap &= ~(1 << rvp_id); | sc->rvp_bmap &= ~(1 << rvp_id); | ||||
run_set_region_4(sc, RT2860_SKEY(rvp_id, 0), 0, 128); | run_set_region_4(sc, RT2860_SKEY(rvp_id, 0), 0, 128); | ||||
run_set_region_4(sc, RT2860_BCN_BASE(rvp_id), 0, 512); | run_set_region_4(sc, RT2860_BCN_BASE(rvp_id), 0, 512); | ||||
--sc->rvp_cnt; | --sc->rvp_cnt; | ||||
DPRINTF("vap=%p rvp_id=%d bmap=%x rvp_cnt=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_STATE, | ||||
"vap=%p rvp_id=%d bmap=%x rvp_cnt=%d\n", | |||||
vap, rvp_id, sc->rvp_bmap, sc->rvp_cnt); | vap, rvp_id, sc->rvp_bmap, sc->rvp_cnt); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
ieee80211_ratectl_deinit(vap); | ieee80211_ratectl_deinit(vap); | ||||
ieee80211_vap_detach(vap); | ieee80211_vap_detach(vap); | ||||
free(rvp, M_80211_VAP); | free(rvp, M_80211_VAP); | ||||
} | } | ||||
Show All 11 Lines | |||||
{ | { | ||||
struct run_softc *sc = arg; | struct run_softc *sc = arg; | ||||
uint8_t i; | uint8_t i; | ||||
/* call cmdq[].func locked */ | /* call cmdq[].func locked */ | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
for (i = sc->cmdq_exec; sc->cmdq[i].func && pending; | for (i = sc->cmdq_exec; sc->cmdq[i].func && pending; | ||||
i = sc->cmdq_exec, pending--) { | i = sc->cmdq_exec, pending--) { | ||||
DPRINTFN(6, "cmdq_exec=%d pending=%d\n", i, pending); | RUN_DPRINTF(sc, RUN_DEBUG_CMD, "cmdq_exec=%d pending=%d\n", | ||||
i, pending); | |||||
if (sc->cmdq_run == RUN_CMDQ_GO) { | if (sc->cmdq_run == RUN_CMDQ_GO) { | ||||
/* | /* | ||||
* If arg0 is NULL, callback func needs more | * If arg0 is NULL, callback func needs more | ||||
* than one arg. So, pass ptr to cmdq struct. | * than one arg. So, pass ptr to cmdq struct. | ||||
*/ | */ | ||||
if (sc->cmdq[i].arg0) | if (sc->cmdq[i].arg0) | ||||
sc->cmdq[i].func(sc->cmdq[i].arg0); | sc->cmdq[i].func(sc->cmdq[i].arg0); | ||||
else | else | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | run_do_request(struct run_softc *sc, | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
while (ntries--) { | while (ntries--) { | ||||
err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, | err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, | ||||
req, data, 0, NULL, 250 /* ms */); | req, data, 0, NULL, 250 /* ms */); | ||||
if (err == 0) | if (err == 0) | ||||
break; | break; | ||||
DPRINTFN(1, "Control request failed, %s (retrying)\n", | RUN_DPRINTF(sc, RUN_DEBUG_USB, | ||||
"Control request failed, %s (retrying)\n", | |||||
usbd_errstr(err)); | usbd_errstr(err)); | ||||
run_delay(sc, 10); | run_delay(sc, 10); | ||||
} | } | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
run_read(struct run_softc *sc, uint16_t reg, uint32_t *val) | run_read(struct run_softc *sc, uint16_t reg, uint32_t *val) | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | for (i = 0; i < 14; i++) { | ||||
} | } | ||||
if (sc->mac_ver > 0x5390) { | if (sc->mac_ver > 0x5390) { | ||||
if (sc->txpow2[i] < 0 || sc->txpow2[i] > 39) | if (sc->txpow2[i] < 0 || sc->txpow2[i] > 39) | ||||
sc->txpow2[i] = 5; | sc->txpow2[i] = 5; | ||||
} else if (sc->mac_ver < 0x5390) { | } else if (sc->mac_ver < 0x5390) { | ||||
if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) | if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) | ||||
sc->txpow2[i] = 5; | sc->txpow2[i] = 5; | ||||
} | } | ||||
DPRINTF("chan %d: power1=%d, power2=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_TXPWR, | ||||
"chan %d: power1=%d, power2=%d\n", | |||||
rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); | rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); | ||||
} | } | ||||
/* Read power settings for 5GHz channels. */ | /* Read power settings for 5GHz channels. */ | ||||
for (i = 0; i < 40; i += 2) { | for (i = 0; i < 40; i += 2) { | ||||
run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); | run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); | ||||
sc->txpow1[i + 14] = (int8_t)(val & 0xff); | sc->txpow1[i + 14] = (int8_t)(val & 0xff); | ||||
sc->txpow1[i + 15] = (int8_t)(val >> 8); | sc->txpow1[i + 15] = (int8_t)(val >> 8); | ||||
run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); | run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); | ||||
sc->txpow2[i + 14] = (int8_t)(val & 0xff); | sc->txpow2[i + 14] = (int8_t)(val & 0xff); | ||||
sc->txpow2[i + 15] = (int8_t)(val >> 8); | sc->txpow2[i + 15] = (int8_t)(val >> 8); | ||||
} | } | ||||
/* Fix broken Tx power entries. */ | /* Fix broken Tx power entries. */ | ||||
for (i = 0; i < 40; i++ ) { | for (i = 0; i < 40; i++ ) { | ||||
if (sc->mac_ver != 0x5592) { | if (sc->mac_ver != 0x5592) { | ||||
if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) | if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) | ||||
sc->txpow1[14 + i] = 5; | sc->txpow1[14 + i] = 5; | ||||
if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) | if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) | ||||
sc->txpow2[14 + i] = 5; | sc->txpow2[14 + i] = 5; | ||||
} | } | ||||
DPRINTF("chan %d: power1=%d, power2=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_TXPWR, | ||||
"chan %d: power1=%d, power2=%d\n", | |||||
rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], | rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], | ||||
sc->txpow2[14 + i]); | sc->txpow2[14 + i]); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
run_read_eeprom(struct run_softc *sc) | run_read_eeprom(struct run_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
int8_t delta_2ghz, delta_5ghz; | int8_t delta_2ghz, delta_5ghz; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
uint16_t val; | uint16_t val; | ||||
int ridx, ant, i; | int ridx, ant, i; | ||||
/* check whether the ROM is eFUSE ROM or EEPROM */ | /* check whether the ROM is eFUSE ROM or EEPROM */ | ||||
sc->sc_srom_read = run_eeprom_read_2; | sc->sc_srom_read = run_eeprom_read_2; | ||||
if (sc->mac_ver >= 0x3070) { | if (sc->mac_ver >= 0x3070) { | ||||
run_read(sc, RT3070_EFUSE_CTRL, &tmp); | run_read(sc, RT3070_EFUSE_CTRL, &tmp); | ||||
DPRINTF("EFUSE_CTRL=0x%08x\n", tmp); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "EFUSE_CTRL=0x%08x\n", tmp); | ||||
if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593) | if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593) | ||||
sc->sc_srom_read = run_efuse_read_2; | sc->sc_srom_read = run_efuse_read_2; | ||||
} | } | ||||
/* read ROM version */ | /* read ROM version */ | ||||
run_srom_read(sc, RT2860_EEPROM_VERSION, &val); | run_srom_read(sc, RT2860_EEPROM_VERSION, &val); | ||||
DPRINTF("EEPROM rev=%d, FAE=%d\n", val >> 8, val & 0xff); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, | ||||
"EEPROM rev=%d, FAE=%d\n", val >> 8, val & 0xff); | |||||
/* read MAC address */ | /* read MAC address */ | ||||
run_srom_read(sc, RT2860_EEPROM_MAC01, &val); | run_srom_read(sc, RT2860_EEPROM_MAC01, &val); | ||||
ic->ic_macaddr[0] = val & 0xff; | ic->ic_macaddr[0] = val & 0xff; | ||||
ic->ic_macaddr[1] = val >> 8; | ic->ic_macaddr[1] = val >> 8; | ||||
run_srom_read(sc, RT2860_EEPROM_MAC23, &val); | run_srom_read(sc, RT2860_EEPROM_MAC23, &val); | ||||
ic->ic_macaddr[2] = val & 0xff; | ic->ic_macaddr[2] = val & 0xff; | ||||
ic->ic_macaddr[3] = val >> 8; | ic->ic_macaddr[3] = val >> 8; | ||||
run_srom_read(sc, RT2860_EEPROM_MAC45, &val); | run_srom_read(sc, RT2860_EEPROM_MAC45, &val); | ||||
ic->ic_macaddr[4] = val & 0xff; | ic->ic_macaddr[4] = val & 0xff; | ||||
ic->ic_macaddr[5] = val >> 8; | ic->ic_macaddr[5] = val >> 8; | ||||
if (sc->mac_ver < 0x3593) { | if (sc->mac_ver < 0x3593) { | ||||
/* read vender BBP settings */ | /* read vender BBP settings */ | ||||
for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) { | ||||
run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val); | run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val); | ||||
sc->bbp[i].val = val & 0xff; | sc->bbp[i].val = val & 0xff; | ||||
sc->bbp[i].reg = val >> 8; | sc->bbp[i].reg = val >> 8; | ||||
DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, | RUN_DPRINTF(sc, RUN_DEBUG_ROM, | ||||
sc->bbp[i].val); | "BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val); | ||||
} | } | ||||
if (sc->mac_ver >= 0x3071) { | if (sc->mac_ver >= 0x3071) { | ||||
/* read vendor RF settings */ | /* read vendor RF settings */ | ||||
for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) { | ||||
run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, | run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, | ||||
&val); | &val); | ||||
sc->rf[i].val = val & 0xff; | sc->rf[i].val = val & 0xff; | ||||
sc->rf[i].reg = val >> 8; | sc->rf[i].reg = val >> 8; | ||||
DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg, | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "RF%d=0x%02x\n", | ||||
sc->rf[i].val); | sc->rf[i].reg, sc->rf[i].val); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* read RF frequency offset from EEPROM */ | /* read RF frequency offset from EEPROM */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : | ||||
RT3593_EEPROM_FREQ, &val); | RT3593_EEPROM_FREQ, &val); | ||||
sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; | sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; | ||||
DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "EEPROM freq offset %d\n", | ||||
sc->freq & 0xff); | |||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : | ||||
RT3593_EEPROM_FREQ_LEDS, &val); | RT3593_EEPROM_FREQ_LEDS, &val); | ||||
if (val >> 8 != 0xff) { | if (val >> 8 != 0xff) { | ||||
/* read LEDs operating mode */ | /* read LEDs operating mode */ | ||||
sc->leds = val >> 8; | sc->leds = val >> 8; | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 : | ||||
RT3593_EEPROM_LED1, &sc->led[0]); | RT3593_EEPROM_LED1, &sc->led[0]); | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 : | ||||
RT3593_EEPROM_LED2, &sc->led[1]); | RT3593_EEPROM_LED2, &sc->led[1]); | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 : | ||||
RT3593_EEPROM_LED3, &sc->led[2]); | RT3593_EEPROM_LED3, &sc->led[2]); | ||||
} else { | } else { | ||||
/* broken EEPROM, use default settings */ | /* broken EEPROM, use default settings */ | ||||
sc->leds = 0x01; | sc->leds = 0x01; | ||||
sc->led[0] = 0x5555; | sc->led[0] = 0x5555; | ||||
sc->led[1] = 0x2221; | sc->led[1] = 0x2221; | ||||
sc->led[2] = 0x5627; /* differs from RT2860 */ | sc->led[2] = 0x5627; /* differs from RT2860 */ | ||||
} | } | ||||
DPRINTF("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", | RUN_DPRINTF(sc, RUN_DEBUG_ROM, | ||||
"EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", | |||||
sc->leds, sc->led[0], sc->led[1], sc->led[2]); | sc->leds, sc->led[0], sc->led[1], sc->led[2]); | ||||
/* read RF information */ | /* read RF information */ | ||||
if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) | if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) | ||||
run_srom_read(sc, 0x00, &val); | run_srom_read(sc, 0x00, &val); | ||||
else | else | ||||
run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); | run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); | ||||
if (val == 0xffff) { | if (val == 0xffff) { | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"invalid EEPROM antenna info, using default\n"); | "invalid EEPROM antenna info, using default\n"); | ||||
DPRINTF("invalid EEPROM antenna info, using default\n"); | |||||
if (sc->mac_ver == 0x3572) { | if (sc->mac_ver == 0x3572) { | ||||
/* default to RF3052 2T2R */ | /* default to RF3052 2T2R */ | ||||
sc->rf_rev = RT3070_RF_3052; | sc->rf_rev = RT3070_RF_3052; | ||||
sc->ntxchains = 2; | sc->ntxchains = 2; | ||||
sc->nrxchains = 2; | sc->nrxchains = 2; | ||||
} else if (sc->mac_ver >= 0x3070) { | } else if (sc->mac_ver >= 0x3070) { | ||||
/* default to RF3020 1T1R */ | /* default to RF3020 1T1R */ | ||||
sc->rf_rev = RT3070_RF_3020; | sc->rf_rev = RT3070_RF_3020; | ||||
Show All 9 Lines | if (val == 0xffff) { | ||||
if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) { | if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) { | ||||
sc->rf_rev = val; | sc->rf_rev = val; | ||||
run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); | run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); | ||||
} else | } else | ||||
sc->rf_rev = (val >> 8) & 0xf; | sc->rf_rev = (val >> 8) & 0xf; | ||||
sc->ntxchains = (val >> 4) & 0xf; | sc->ntxchains = (val >> 4) & 0xf; | ||||
sc->nrxchains = val & 0xf; | sc->nrxchains = val & 0xf; | ||||
} | } | ||||
DPRINTF("EEPROM RF rev=0x%04x chains=%dT%dR\n", | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "EEPROM RF rev=0x%04x chains=%dT%dR\n", | ||||
sc->rf_rev, sc->ntxchains, sc->nrxchains); | sc->rf_rev, sc->ntxchains, sc->nrxchains); | ||||
/* check if RF supports automatic Tx access gain control */ | /* check if RF supports automatic Tx access gain control */ | ||||
run_srom_read(sc, RT2860_EEPROM_CONFIG, &val); | run_srom_read(sc, RT2860_EEPROM_CONFIG, &val); | ||||
DPRINTF("EEPROM CFG 0x%04x\n", val); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "EEPROM CFG 0x%04x\n", val); | ||||
/* check if driver should patch the DAC issue */ | /* check if driver should patch the DAC issue */ | ||||
if ((val >> 8) != 0xff) | if ((val >> 8) != 0xff) | ||||
sc->patch_dac = (val >> 15) & 1; | sc->patch_dac = (val >> 15) & 1; | ||||
if ((val & 0xff) != 0xff) { | if ((val & 0xff) != 0xff) { | ||||
sc->ext_5ghz_lna = (val >> 3) & 1; | sc->ext_5ghz_lna = (val >> 3) & 1; | ||||
sc->ext_2ghz_lna = (val >> 2) & 1; | sc->ext_2ghz_lna = (val >> 2) & 1; | ||||
/* check if RF supports automatic Tx access gain control */ | /* check if RF supports automatic Tx access gain control */ | ||||
sc->calib_2ghz = sc->calib_5ghz = (val >> 1) & 1; | sc->calib_2ghz = sc->calib_5ghz = (val >> 1) & 1; | ||||
Show All 16 Lines | if (!(val & 0x40)) /* negative number */ | ||||
delta_2ghz = -delta_2ghz; | delta_2ghz = -delta_2ghz; | ||||
} | } | ||||
val >>= 8; | val >>= 8; | ||||
if ((val & 0xff) != 0xff && (val & 0x80)) { | if ((val & 0xff) != 0xff && (val & 0x80)) { | ||||
delta_5ghz = val & 0xf; | delta_5ghz = val & 0xf; | ||||
if (!(val & 0x40)) /* negative number */ | if (!(val & 0x40)) /* negative number */ | ||||
delta_5ghz = -delta_5ghz; | delta_5ghz = -delta_5ghz; | ||||
} | } | ||||
DPRINTF("power compensation=%d (2GHz), %d (5GHz)\n", | RUN_DPRINTF(sc, RUN_DEBUG_ROM | RUN_DEBUG_TXPWR, | ||||
delta_2ghz, delta_5ghz); | "power compensation=%d (2GHz), %d (5GHz)\n", delta_2ghz, delta_5ghz); | ||||
for (ridx = 0; ridx < 5; ridx++) { | for (ridx = 0; ridx < 5; ridx++) { | ||||
uint32_t reg; | uint32_t reg; | ||||
run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val); | run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val); | ||||
reg = val; | reg = val; | ||||
run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val); | run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val); | ||||
reg |= (uint32_t)val << 16; | reg |= (uint32_t)val << 16; | ||||
sc->txpow20mhz[ridx] = reg; | sc->txpow20mhz[ridx] = reg; | ||||
sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); | sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); | ||||
sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); | sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); | ||||
DPRINTF("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " | RUN_DPRINTF(sc, RUN_DEBUG_ROM | RUN_DEBUG_TXPWR, | ||||
"ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " | |||||
"40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], | "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], | ||||
sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]); | sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]); | ||||
} | } | ||||
/* Read RSSI offsets and LNA gains from EEPROM. */ | /* Read RSSI offsets and LNA gains from EEPROM. */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ : | ||||
RT3593_EEPROM_RSSI1_2GHZ, &val); | RT3593_EEPROM_RSSI1_2GHZ, &val); | ||||
sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ | sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ | ||||
sc->rssi_2ghz[1] = val >> 8; /* Ant B */ | sc->rssi_2ghz[1] = val >> 8; /* Ant B */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ : | ||||
RT3593_EEPROM_RSSI2_2GHZ, &val); | RT3593_EEPROM_RSSI2_2GHZ, &val); | ||||
if (sc->mac_ver >= 0x3070) { | if (sc->mac_ver >= 0x3070) { | ||||
if (sc->mac_ver == 0x3593) { | if (sc->mac_ver == 0x3593) { | ||||
sc->txmixgain_2ghz = 0; | sc->txmixgain_2ghz = 0; | ||||
sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ | sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ | ||||
} else { | } else { | ||||
/* | /* | ||||
* On RT3070 chips (limited to 2 Rx chains), this ROM | * On RT3070 chips (limited to 2 Rx chains), this ROM | ||||
* field contains the Tx mixer gain for the 2GHz band. | * field contains the Tx mixer gain for the 2GHz band. | ||||
*/ | */ | ||||
if ((val & 0xff) != 0xff) | if ((val & 0xff) != 0xff) | ||||
sc->txmixgain_2ghz = val & 0x7; | sc->txmixgain_2ghz = val & 0x7; | ||||
} | } | ||||
DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "tx mixer gain=%u (2GHz)\n", | ||||
sc->txmixgain_2ghz); | |||||
} else | } else | ||||
sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ | sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ | ||||
if (sc->mac_ver == 0x3593) | if (sc->mac_ver == 0x3593) | ||||
run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); | run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); | ||||
sc->lna[2] = val >> 8; /* channel group 2 */ | sc->lna[2] = val >> 8; /* channel group 2 */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ : | ||||
RT3593_EEPROM_RSSI1_5GHZ, &val); | RT3593_EEPROM_RSSI1_5GHZ, &val); | ||||
sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ | sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ | ||||
sc->rssi_5ghz[1] = val >> 8; /* Ant B */ | sc->rssi_5ghz[1] = val >> 8; /* Ant B */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ : | ||||
RT3593_EEPROM_RSSI2_5GHZ, &val); | RT3593_EEPROM_RSSI2_5GHZ, &val); | ||||
if (sc->mac_ver == 0x3572) { | if (sc->mac_ver == 0x3572) { | ||||
/* | /* | ||||
* On RT3572 chips (limited to 2 Rx chains), this ROM | * On RT3572 chips (limited to 2 Rx chains), this ROM | ||||
* field contains the Tx mixer gain for the 5GHz band. | * field contains the Tx mixer gain for the 5GHz band. | ||||
*/ | */ | ||||
if ((val & 0xff) != 0xff) | if ((val & 0xff) != 0xff) | ||||
sc->txmixgain_5ghz = val & 0x7; | sc->txmixgain_5ghz = val & 0x7; | ||||
DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, "tx mixer gain=%u (5GHz)\n", | ||||
sc->txmixgain_5ghz); | |||||
} else | } else | ||||
sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ | sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ | ||||
if (sc->mac_ver == 0x3593) { | if (sc->mac_ver == 0x3593) { | ||||
sc->txmixgain_5ghz = 0; | sc->txmixgain_5ghz = 0; | ||||
run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); | run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); | ||||
} | } | ||||
sc->lna[3] = val >> 8; /* channel group 3 */ | sc->lna[3] = val >> 8; /* channel group 3 */ | ||||
run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA : | run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA : | ||||
RT3593_EEPROM_LNA, &val); | RT3593_EEPROM_LNA, &val); | ||||
sc->lna[0] = val & 0xff; /* channel group 0 */ | sc->lna[0] = val & 0xff; /* channel group 0 */ | ||||
sc->lna[1] = val >> 8; /* channel group 1 */ | sc->lna[1] = val >> 8; /* channel group 1 */ | ||||
/* fix broken 5GHz LNA entries */ | /* fix broken 5GHz LNA entries */ | ||||
if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { | if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { | ||||
DPRINTF("invalid LNA for channel group %d\n", 2); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, | ||||
"invalid LNA for channel group %d\n", 2); | |||||
sc->lna[2] = sc->lna[1]; | sc->lna[2] = sc->lna[1]; | ||||
} | } | ||||
if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { | if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { | ||||
DPRINTF("invalid LNA for channel group %d\n", 3); | RUN_DPRINTF(sc, RUN_DEBUG_ROM, | ||||
"invalid LNA for channel group %d\n", 3); | |||||
sc->lna[3] = sc->lna[1]; | sc->lna[3] = sc->lna[1]; | ||||
} | } | ||||
/* fix broken RSSI offset entries */ | /* fix broken RSSI offset entries */ | ||||
for (ant = 0; ant < 3; ant++) { | for (ant = 0; ant < 3; ant++) { | ||||
if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { | if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { | ||||
DPRINTF("invalid RSSI%d offset: %d (2GHz)\n", | RUN_DPRINTF(sc, RUN_DEBUG_ROM | RUN_DEBUG_RSSI, | ||||
"invalid RSSI%d offset: %d (2GHz)\n", | |||||
ant + 1, sc->rssi_2ghz[ant]); | ant + 1, sc->rssi_2ghz[ant]); | ||||
sc->rssi_2ghz[ant] = 0; | sc->rssi_2ghz[ant] = 0; | ||||
} | } | ||||
if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { | if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { | ||||
DPRINTF("invalid RSSI%d offset: %d (5GHz)\n", | RUN_DPRINTF(sc, RUN_DEBUG_ROM | RUN_DEBUG_RSSI, | ||||
"invalid RSSI%d offset: %d (5GHz)\n", | |||||
ant + 1, sc->rssi_5ghz[ant]); | ant + 1, sc->rssi_5ghz[ant]); | ||||
sc->rssi_5ghz[ant] = 0; | sc->rssi_5ghz[ant] = 0; | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct ieee80211_node * | static struct ieee80211_node * | ||||
Show All 28 Lines | if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { | ||||
rate = ic->ic_sup_rates[ic->ic_curmode]. | rate = ic->ic_sup_rates[ic->ic_curmode]. | ||||
rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL; | rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL; | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | ||||
if (rt2860_rates[ridx].rate == rate) | if (rt2860_rates[ridx].rate == rate) | ||||
break; | break; | ||||
ni = ieee80211_ref_node(vap->iv_bss); | ni = ieee80211_ref_node(vap->iv_bss); | ||||
rn = RUN_NODE(ni); | rn = RUN_NODE(ni); | ||||
rn->fix_ridx = ridx; | rn->fix_ridx = ridx; | ||||
DPRINTF("rate=%d, fix_ridx=%d\n", rate, rn->fix_ridx); | RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, fix_ridx=%d\n", | ||||
rate, rn->fix_ridx); | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
} | } | ||||
#if 0 | #if 0 | ||||
if ((ifp->if_flags & IFF_UP) && | if ((ifp->if_flags & IFF_UP) && | ||||
(ifp->if_drv_flags & RUN_RUNNING)){ | (ifp->if_drv_flags & RUN_RUNNING)){ | ||||
run_init_locked(sc); | run_init_locked(sc); | ||||
} | } | ||||
Show All 14 Lines | run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
enum ieee80211_state ostate; | enum ieee80211_state ostate; | ||||
uint32_t sta[3]; | uint32_t sta[3]; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
uint8_t ratectl; | uint8_t ratectl; | ||||
uint8_t restart_ratectl = 0; | uint8_t restart_ratectl = 0; | ||||
uint8_t bid = 1 << rvp->rvp_id; | uint8_t bid = 1 << rvp->rvp_id; | ||||
ostate = vap->iv_state; | ostate = vap->iv_state; | ||||
DPRINTF("%s -> %s\n", | RUN_DPRINTF(sc, RUN_DEBUG_STATE, "%s -> %s\n", | ||||
ieee80211_state_name[ostate], | ieee80211_state_name[ostate], | ||||
ieee80211_state_name[nstate]); | ieee80211_state_name[nstate]); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
ratectl = sc->ratectl_run; /* remember current state */ | ratectl = sc->ratectl_run; /* remember current state */ | ||||
sc->ratectl_run = RUN_RATECTL_OFF; | sc->ratectl_run = RUN_RATECTL_OFF; | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | case IEEE80211_S_RUN: | ||||
/* turn link LED on */ | /* turn link LED on */ | ||||
run_set_leds(sc, RT2860_LED_RADIO | | run_set_leds(sc, RT2860_LED_RADIO | | ||||
(IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? | (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? | ||||
RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); | RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); | ||||
break; | break; | ||||
default: | default: | ||||
DPRINTFN(6, "undefined case\n"); | RUN_DPRINTF(sc, RUN_DEBUG_STATE, "undefined state\n"); | ||||
break; | break; | ||||
} | } | ||||
/* restart amrr for running VAPs */ | /* restart amrr for running VAPs */ | ||||
if ((sc->ratectl_run = ratectl) && restart_ratectl) | if ((sc->ratectl_run = ratectl) && restart_ratectl) | ||||
usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); | usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | run_wme_update(struct ieee80211com *ic) | ||||
if (error) goto err; | if (error) goto err; | ||||
error = run_write(sc, RT2860_WMM_TXOP1_CFG, | error = run_write(sc, RT2860_WMM_TXOP1_CFG, | ||||
ac[WME_AC_VO].wmep_txopLimit << 16 | | ac[WME_AC_VO].wmep_txopLimit << 16 | | ||||
ac[WME_AC_VI].wmep_txopLimit); | ac[WME_AC_VI].wmep_txopLimit); | ||||
err: | err: | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (error) | if (error) | ||||
DPRINTF("WME update failed\n"); | RUN_DPRINTF(sc, RUN_DEBUG_USB, "WME update failed\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
run_key_set_cb(void *arg) | run_key_set_cb(void *arg) | ||||
{ | { | ||||
struct run_cmdq *cmdq = arg; | struct run_cmdq *cmdq = arg; | ||||
Show All 25 Lines | case IEEE80211_CIPHER_WEP: | ||||
break; | break; | ||||
case IEEE80211_CIPHER_TKIP: | case IEEE80211_CIPHER_TKIP: | ||||
mode = RT2860_MODE_TKIP; | mode = RT2860_MODE_TKIP; | ||||
break; | break; | ||||
case IEEE80211_CIPHER_AES_CCM: | case IEEE80211_CIPHER_AES_CCM: | ||||
mode = RT2860_MODE_AES_CCMP; | mode = RT2860_MODE_AES_CCMP; | ||||
break; | break; | ||||
default: | default: | ||||
DPRINTF("undefined case\n"); | RUN_DPRINTF(sc, RUN_DEBUG_KEY, "undefined case\n"); | ||||
return; | return; | ||||
} | } | ||||
DPRINTFN(1, "associd=%x, keyix=%d, mode=%x, type=%s, tx=%s, rx=%s\n", | RUN_DPRINTF(sc, RUN_DEBUG_KEY, | ||||
"associd=%x, keyix=%d, mode=%x, type=%s, tx=%s, rx=%s\n", | |||||
associd, k->wk_keyix, mode, | associd, k->wk_keyix, mode, | ||||
(k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise", | (k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise", | ||||
(k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off", | (k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off", | ||||
(k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off"); | (k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off"); | ||||
if (k->wk_flags & IEEE80211_KEY_GROUP) { | if (k->wk_flags & IEEE80211_KEY_GROUP) { | ||||
wcid = 0; /* NB: update WCID0 for group keys */ | wcid = 0; /* NB: update WCID0 for group keys */ | ||||
base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix); | base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix); | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k) | run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint32_t i; | uint32_t i; | ||||
i = RUN_CMDQ_GET(&sc->cmdq_store); | i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_KEY, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_key_set_cb; | sc->cmdq[i].func = run_key_set_cb; | ||||
sc->cmdq[i].arg0 = NULL; | sc->cmdq[i].arg0 = NULL; | ||||
sc->cmdq[i].arg1 = vap; | sc->cmdq[i].arg1 = vap; | ||||
sc->cmdq[i].k = k; | sc->cmdq[i].k = k; | ||||
IEEE80211_ADDR_COPY(sc->cmdq[i].mac, k->wk_macaddr); | IEEE80211_ADDR_COPY(sc->cmdq[i].mac, k->wk_macaddr); | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
/* | /* | ||||
Show All 22 Lines | run_key_delete_cb(void *arg) | ||||
struct ieee80211_key *k = &cmdq->key; | struct ieee80211_key *k = &cmdq->key; | ||||
uint32_t attr; | uint32_t attr; | ||||
uint8_t wcid; | uint8_t wcid; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
if (k->wk_flags & IEEE80211_KEY_GROUP) { | if (k->wk_flags & IEEE80211_KEY_GROUP) { | ||||
/* remove group key */ | /* remove group key */ | ||||
DPRINTF("removing group key\n"); | RUN_DPRINTF(sc, RUN_DEBUG_KEY, "removing group key\n"); | ||||
run_read(sc, RT2860_SKEY_MODE_0_7, &attr); | run_read(sc, RT2860_SKEY_MODE_0_7, &attr); | ||||
attr &= ~(0xf << (k->wk_keyix * 4)); | attr &= ~(0xf << (k->wk_keyix * 4)); | ||||
run_write(sc, RT2860_SKEY_MODE_0_7, attr); | run_write(sc, RT2860_SKEY_MODE_0_7, attr); | ||||
} else { | } else { | ||||
/* remove pairwise key */ | /* remove pairwise key */ | ||||
DPRINTF("removing key for wcid %x\n", k->wk_pad); | RUN_DPRINTF(sc, RUN_DEBUG_KEY, | ||||
"removing key for wcid %x\n", k->wk_pad); | |||||
/* matching wcid was written to wk_pad in run_key_set() */ | /* matching wcid was written to wk_pad in run_key_set() */ | ||||
wcid = k->wk_pad; | wcid = k->wk_pad; | ||||
run_read(sc, RT2860_WCID_ATTR(wcid), &attr); | run_read(sc, RT2860_WCID_ATTR(wcid), &attr); | ||||
attr &= ~0xf; | attr &= ~0xf; | ||||
run_write(sc, RT2860_WCID_ATTR(wcid), attr); | run_write(sc, RT2860_WCID_ATTR(wcid), attr); | ||||
run_set_region_4(sc, RT2860_WCID_ENTRY(wcid), 0, 8); | run_set_region_4(sc, RT2860_WCID_ENTRY(wcid), 0, 8); | ||||
} | } | ||||
Show All 13 Lines | run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k) | ||||
/* | /* | ||||
* When called back, key might be gone. So, make a copy | * When called back, key might be gone. So, make a copy | ||||
* of some values need to delete keys before deferring. | * of some values need to delete keys before deferring. | ||||
* But, because of LOR with node lock, cannot use lock here. | * But, because of LOR with node lock, cannot use lock here. | ||||
* So, use atomic instead. | * So, use atomic instead. | ||||
*/ | */ | ||||
i = RUN_CMDQ_GET(&sc->cmdq_store); | i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_KEY, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_key_delete_cb; | sc->cmdq[i].func = run_key_delete_cb; | ||||
sc->cmdq[i].arg0 = NULL; | sc->cmdq[i].arg0 = NULL; | ||||
sc->cmdq[i].arg1 = sc; | sc->cmdq[i].arg1 = sc; | ||||
k0 = &sc->cmdq[i].key; | k0 = &sc->cmdq[i].key; | ||||
k0->wk_flags = k->wk_flags; | k0->wk_flags = k->wk_flags; | ||||
k0->wk_keyix = k->wk_keyix; | k0->wk_keyix = k->wk_keyix; | ||||
/* matching wcid was written to wk_pad in run_key_set() */ | /* matching wcid was written to wk_pad in run_key_set() */ | ||||
k0->wk_pad = k->wk_pad; | k0->wk_pad = k->wk_pad; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | run_drain_fifo(void *arg) | ||||
uint8_t wcid, mcs, pid; | uint8_t wcid, mcs, pid; | ||||
int8_t retry; | int8_t retry; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
for (;;) { | for (;;) { | ||||
/* drain Tx status FIFO (maxsize = 16) */ | /* drain Tx status FIFO (maxsize = 16) */ | ||||
run_read(sc, RT2860_TX_STAT_FIFO, &stat); | run_read(sc, RT2860_TX_STAT_FIFO, &stat); | ||||
DPRINTFN(4, "tx stat 0x%08x\n", stat); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "tx stat 0x%08x\n", stat); | ||||
if (!(stat & RT2860_TXQ_VLD)) | if (!(stat & RT2860_TXQ_VLD)) | ||||
break; | break; | ||||
wcid = (stat >> RT2860_TXQ_WCID_SHIFT) & 0xff; | wcid = (stat >> RT2860_TXQ_WCID_SHIFT) & 0xff; | ||||
/* if no ACK was requested, no feedback is available */ | /* if no ACK was requested, no feedback is available */ | ||||
if (!(stat & RT2860_TXQ_ACKREQ) || wcid > RT2870_WCID_MAX || | if (!(stat & RT2860_TXQ_ACKREQ) || wcid > RT2870_WCID_MAX || | ||||
wcid == 0) | wcid == 0) | ||||
Show All 22 Lines | for (;;) { | ||||
*/ | */ | ||||
mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; | mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; | ||||
pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; | pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; | ||||
if ((retry = pid -1 - mcs) > 0) { | if ((retry = pid -1 - mcs) > 0) { | ||||
(*wstat)[RUN_TXCNT] += retry; | (*wstat)[RUN_TXCNT] += retry; | ||||
(*wstat)[RUN_RETRY] += retry; | (*wstat)[RUN_RETRY] += retry; | ||||
} | } | ||||
} | } | ||||
DPRINTFN(3, "count=%d\n", sc->fifo_cnt); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "count=%d\n", sc->fifo_cnt); | ||||
sc->fifo_cnt = 0; | sc->fifo_cnt = 0; | ||||
} | } | ||||
static void | static void | ||||
run_iter_func(void *arg, struct ieee80211_node *ni) | run_iter_func(void *arg, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct run_softc *sc = arg; | struct run_softc *sc = arg; | ||||
Show All 27 Lines | if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, | ||||
le16toh(sta[0].error.fail)); | le16toh(sta[0].error.fail)); | ||||
txs->nretries = le16toh(sta[1].tx.retry); | txs->nretries = le16toh(sta[1].tx.retry); | ||||
txs->nsuccess = le16toh(sta[1].tx.success); | txs->nsuccess = le16toh(sta[1].tx.success); | ||||
/* nretries??? */ | /* nretries??? */ | ||||
txs->nframes = txs->nretries + txs->nsuccess + | txs->nframes = txs->nretries + txs->nsuccess + | ||||
le16toh(sta[0].error.fail); | le16toh(sta[0].error.fail); | ||||
DPRINTFN(3, "retrycnt=%d success=%d failcnt=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_RATE, | ||||
txs->nretries, txs->nsuccess, | "retrycnt=%d success=%d failcnt=%d\n", | ||||
le16toh(sta[0].error.fail)); | txs->nretries, txs->nsuccess, le16toh(sta[0].error.fail)); | ||||
} else { | } else { | ||||
wstat = &(sc->wcid_stats[RUN_AID2WCID(ni->ni_associd)]); | wstat = &(sc->wcid_stats[RUN_AID2WCID(ni->ni_associd)]); | ||||
if (wstat == &(sc->wcid_stats[0]) || | if (wstat == &(sc->wcid_stats[0]) || | ||||
wstat > &(sc->wcid_stats[RT2870_WCID_MAX])) | wstat > &(sc->wcid_stats[RT2870_WCID_MAX])) | ||||
goto fail; | goto fail; | ||||
txs->nretries = (*wstat)[RUN_RETRY]; | txs->nretries = (*wstat)[RUN_RETRY]; | ||||
txs->nsuccess = (*wstat)[RUN_SUCCESS]; | txs->nsuccess = (*wstat)[RUN_SUCCESS]; | ||||
txs->nframes = (*wstat)[RUN_TXCNT]; | txs->nframes = (*wstat)[RUN_TXCNT]; | ||||
DPRINTFN(3, "retrycnt=%d txcnt=%d success=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_RATE, | ||||
"retrycnt=%d txcnt=%d success=%d\n", | |||||
txs->nretries, txs->nframes, txs->nsuccess); | txs->nretries, txs->nframes, txs->nsuccess); | ||||
memset(wstat, 0, sizeof(*wstat)); | memset(wstat, 0, sizeof(*wstat)); | ||||
} | } | ||||
ieee80211_ratectl_tx_update(vap, txs); | ieee80211_ratectl_tx_update(vap, txs); | ||||
rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0); | rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0); | ||||
fail: | fail: | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
DPRINTFN(3, "ridx=%d\n", rn->amrr_ridx); | RUN_DPRINTF(sc, RUN_DEBUG_RATE, "ridx=%d\n", rn->amrr_ridx); | ||||
} | } | ||||
static void | static void | ||||
run_newassoc_cb(void *arg) | run_newassoc_cb(void *arg) | ||||
{ | { | ||||
struct run_cmdq *cmdq = arg; | struct run_cmdq *cmdq = arg; | ||||
struct ieee80211_node *ni = cmdq->arg1; | struct ieee80211_node *ni = cmdq->arg1; | ||||
struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc; | struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc; | ||||
Show All 31 Lines | run_newassoc(struct ieee80211_node *ni, int isnew) | ||||
/* only interested in true associations */ | /* only interested in true associations */ | ||||
if (isnew && ni->ni_associd != 0) { | if (isnew && ni->ni_associd != 0) { | ||||
/* | /* | ||||
* This function could is called though timeout function. | * This function could is called though timeout function. | ||||
* Need to defer. | * Need to defer. | ||||
*/ | */ | ||||
uint32_t cnt = RUN_CMDQ_GET(&sc->cmdq_store); | uint32_t cnt = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", cnt); | RUN_DPRINTF(sc, RUN_DEBUG_STATE, "cmdq_store=%d\n", cnt); | ||||
sc->cmdq[cnt].func = run_newassoc_cb; | sc->cmdq[cnt].func = run_newassoc_cb; | ||||
sc->cmdq[cnt].arg0 = NULL; | sc->cmdq[cnt].arg0 = NULL; | ||||
sc->cmdq[cnt].arg1 = ni; | sc->cmdq[cnt].arg1 = ni; | ||||
sc->cmdq[cnt].wcid = wcid; | sc->cmdq[cnt].wcid = wcid; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
} | } | ||||
DPRINTF("new assoc isnew=%d associd=%x addr=%s\n", | RUN_DPRINTF(sc, RUN_DEBUG_STATE, | ||||
"new assoc isnew=%d associd=%x addr=%s\n", | |||||
isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr)); | isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr)); | ||||
for (i = 0; i < rs->rs_nrates; i++) { | for (i = 0; i < rs->rs_nrates; i++) { | ||||
rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; | rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; | ||||
/* convert 802.11 rate to hardware rate index */ | /* convert 802.11 rate to hardware rate index */ | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | ||||
if (rt2860_rates[ridx].rate == rate) | if (rt2860_rates[ridx].rate == rate) | ||||
break; | break; | ||||
rn->ridx[i] = ridx; | rn->ridx[i] = ridx; | ||||
/* determine rate of control response frames */ | /* determine rate of control response frames */ | ||||
for (j = i; j >= 0; j--) { | for (j = i; j >= 0; j--) { | ||||
if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && | if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && | ||||
rt2860_rates[rn->ridx[i]].phy == | rt2860_rates[rn->ridx[i]].phy == | ||||
rt2860_rates[rn->ridx[j]].phy) | rt2860_rates[rn->ridx[j]].phy) | ||||
break; | break; | ||||
} | } | ||||
if (j >= 0) { | if (j >= 0) { | ||||
rn->ctl_ridx[i] = rn->ridx[j]; | rn->ctl_ridx[i] = rn->ridx[j]; | ||||
} else { | } else { | ||||
/* no basic rate found, use mandatory one */ | /* no basic rate found, use mandatory one */ | ||||
rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; | rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; | ||||
} | } | ||||
DPRINTF("rate=0x%02x ridx=%d ctl_ridx=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | ||||
"rate=0x%02x ridx=%d ctl_ridx=%d\n", | |||||
rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]); | rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]); | ||||
} | } | ||||
rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; | rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | ||||
if (rt2860_rates[ridx].rate == rate) | if (rt2860_rates[ridx].rate == rate) | ||||
break; | break; | ||||
rn->mgt_ridx = ridx; | rn->mgt_ridx = ridx; | ||||
DPRINTF("rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx); | RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | ||||
"rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx); | |||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
if(sc->ratectl_run != RUN_RATECTL_OFF) | if(sc->ratectl_run != RUN_RATECTL_OFF) | ||||
usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); | usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
} | } | ||||
/* | /* | ||||
Show All 30 Lines | if (vap->iv_state == IEEE80211_S_RUN && | ||||
subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { | subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { | ||||
ni_tstamp = le64toh(ni->ni_tstamp.tsf); | ni_tstamp = le64toh(ni->ni_tstamp.tsf); | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
run_get_tsf(sc, &rx_tstamp); | run_get_tsf(sc, &rx_tstamp); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
rx_tstamp = le64toh(rx_tstamp); | rx_tstamp = le64toh(rx_tstamp); | ||||
if (ni_tstamp >= rx_tstamp) { | if (ni_tstamp >= rx_tstamp) { | ||||
DPRINTF("ibss merge, tsf %ju tstamp %ju\n", | RUN_DPRINTF(sc, RUN_DEBUG_RECV | RUN_DEBUG_BEACON, | ||||
"ibss merge, tsf %ju tstamp %ju\n", | |||||
(uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp); | (uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp); | ||||
(void) ieee80211_ibss_merge(ni); | (void) ieee80211_ibss_merge(ni); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) | run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) | ||||
Show All 13 Lines | run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) | ||||
rxwisize = sizeof(struct rt2860_rxwi); | rxwisize = sizeof(struct rt2860_rxwi); | ||||
if (sc->mac_ver == 0x5592) | if (sc->mac_ver == 0x5592) | ||||
rxwisize += sizeof(uint64_t); | rxwisize += sizeof(uint64_t); | ||||
else if (sc->mac_ver == 0x3593) | else if (sc->mac_ver == 0x3593) | ||||
rxwisize += sizeof(uint32_t); | rxwisize += sizeof(uint32_t); | ||||
if (__predict_false(len > dmalen)) { | if (__predict_false(len > dmalen)) { | ||||
m_freem(m); | m_freem(m); | ||||
counter_u64_add(ic->ic_ierrors, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("bad RXWI length %u > %u\n", len, dmalen); | RUN_DPRINTF(sc, RUN_DEBUG_RECV, | ||||
"bad RXWI length %u > %u\n", len, dmalen); | |||||
return; | return; | ||||
} | } | ||||
/* Rx descriptor is located at the end */ | /* Rx descriptor is located at the end */ | ||||
rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen); | rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen); | ||||
flags = le32toh(rxd->flags); | flags = le32toh(rxd->flags); | ||||
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { | if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { | ||||
m_freem(m); | m_freem(m); | ||||
counter_u64_add(ic->ic_ierrors, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV"); | RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n", | ||||
(flags & RT2860_RX_CRCERR)?"CRC":"ICV"); | |||||
return; | return; | ||||
} | } | ||||
m->m_data += rxwisize; | m->m_data += rxwisize; | ||||
m->m_pkthdr.len = m->m_len -= rxwisize; | m->m_pkthdr.len = m->m_len -= rxwisize; | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | ||||
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; | ||||
m->m_flags |= M_WEP; | m->m_flags |= M_WEP; | ||||
} | } | ||||
if (flags & RT2860_RX_L2PAD) { | if (flags & RT2860_RX_L2PAD) { | ||||
DPRINTFN(8, "received RT2860_RX_L2PAD frame\n"); | RUN_DPRINTF(sc, RUN_DEBUG_RECV, | ||||
"received RT2860_RX_L2PAD frame\n"); | |||||
len += 2; | len += 2; | ||||
} | } | ||||
ni = ieee80211_find_rxnode(ic, | ni = ieee80211_find_rxnode(ic, | ||||
mtod(m, struct ieee80211_frame_min *)); | mtod(m, struct ieee80211_frame_min *)); | ||||
if (__predict_false(flags & RT2860_RX_MICERR)) { | if (__predict_false(flags & RT2860_RX_MICERR)) { | ||||
/* report MIC failures to net80211 for TKIP */ | /* report MIC failures to net80211 for TKIP */ | ||||
if (ni != NULL) | if (ni != NULL) | ||||
ieee80211_notify_michael_failure(ni->ni_vap, wh, | ieee80211_notify_michael_failure(ni->ni_vap, wh, | ||||
rxwi->keyidx); | rxwi->keyidx); | ||||
m_freem(m); | m_freem(m); | ||||
counter_u64_add(ic->ic_ierrors, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("MIC error. Someone is lying.\n"); | RUN_DPRINTF(sc, RUN_DEBUG_RECV, | ||||
"MIC error. Someone is lying.\n"); | |||||
return; | return; | ||||
} | } | ||||
ant = run_maxrssi_chain(sc, rxwi); | ant = run_maxrssi_chain(sc, rxwi); | ||||
rssi = rxwi->rssi[ant]; | rssi = rxwi->rssi[ant]; | ||||
nf = run_rssi2dbm(sc, rssi, ant); | nf = run_rssi2dbm(sc, rssi, ant); | ||||
m->m_pkthdr.len = m->m_len = len; | m->m_pkthdr.len = m->m_len = len; | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
else if (sc->mac_ver == 0x3593) | else if (sc->mac_ver == 0x3593) | ||||
rxwisize += sizeof(uint32_t); | rxwisize += sizeof(uint32_t); | ||||
usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL); | usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL); | ||||
switch (USB_GET_STATE(xfer)) { | switch (USB_GET_STATE(xfer)) { | ||||
case USB_ST_TRANSFERRED: | case USB_ST_TRANSFERRED: | ||||
DPRINTFN(15, "rx done, actlen=%d\n", xferlen); | RUN_DPRINTF(sc, RUN_DEBUG_RECV, | ||||
"rx done, actlen=%d\n", xferlen); | |||||
if (xferlen < (int)(sizeof(uint32_t) + rxwisize + | if (xferlen < (int)(sizeof(uint32_t) + rxwisize + | ||||
sizeof(struct rt2870_rxd))) { | sizeof(struct rt2870_rxd))) { | ||||
DPRINTF("xfer too short %d\n", xferlen); | RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB, | ||||
"xfer too short %d\n", xferlen); | |||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
m = sc->rx_m; | m = sc->rx_m; | ||||
sc->rx_m = NULL; | sc->rx_m = NULL; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case USB_ST_SETUP: | case USB_ST_SETUP: | ||||
tr_setup: | tr_setup: | ||||
if (sc->rx_m == NULL) { | if (sc->rx_m == NULL) { | ||||
sc->rx_m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, | sc->rx_m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, | ||||
MJUMPAGESIZE /* xfer can be bigger than MCLBYTES */); | MJUMPAGESIZE /* xfer can be bigger than MCLBYTES */); | ||||
} | } | ||||
if (sc->rx_m == NULL) { | if (sc->rx_m == NULL) { | ||||
DPRINTF("could not allocate mbuf - idle with stall\n"); | RUN_DPRINTF(sc, RUN_DEBUG_RECV | RUN_DEBUG_RECV_DESC, | ||||
"could not allocate mbuf - idle with stall\n"); | |||||
counter_u64_add(ic->ic_ierrors, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
usbd_xfer_set_frames(xfer, 0); | usbd_xfer_set_frames(xfer, 0); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Directly loading a mbuf cluster into DMA to | * Directly loading a mbuf cluster into DMA to | ||||
* save some data copying. This works because | * save some data copying. This works because | ||||
* there is only one cluster. | * there is only one cluster. | ||||
Show All 31 Lines | tr_setup: | ||||
m->m_pkthdr.len = m->m_len = xferlen; | m->m_pkthdr.len = m->m_len = xferlen; | ||||
/* HW can aggregate multiple 802.11 frames in a single USB xfer */ | /* HW can aggregate multiple 802.11 frames in a single USB xfer */ | ||||
for(;;) { | for(;;) { | ||||
dmalen = le32toh(*mtod(m, uint32_t *)) & 0xffff; | dmalen = le32toh(*mtod(m, uint32_t *)) & 0xffff; | ||||
if ((dmalen >= (uint32_t)-8) || (dmalen == 0) || | if ((dmalen >= (uint32_t)-8) || (dmalen == 0) || | ||||
((dmalen & 3) != 0)) { | ((dmalen & 3) != 0)) { | ||||
DPRINTF("bad DMA length %u\n", dmalen); | RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB, | ||||
"bad DMA length %u\n", dmalen); | |||||
break; | break; | ||||
} | } | ||||
if ((dmalen + 8) > (uint32_t)xferlen) { | if ((dmalen + 8) > (uint32_t)xferlen) { | ||||
DPRINTF("bad DMA length %u > %d\n", | RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB, | ||||
"bad DMA length %u > %d\n", | |||||
dmalen + 8, xferlen); | dmalen + 8, xferlen); | ||||
break; | break; | ||||
} | } | ||||
/* If it is the last one or a single frame, we won't copy. */ | /* If it is the last one or a single frame, we won't copy. */ | ||||
if ((xferlen -= dmalen + 8) <= 8) { | if ((xferlen -= dmalen + 8) <= 8) { | ||||
/* trim 32-bit DMA-len header */ | /* trim 32-bit DMA-len header */ | ||||
m->m_data += 4; | m->m_data += 4; | ||||
m->m_pkthdr.len = m->m_len -= 4; | m->m_pkthdr.len = m->m_len -= 4; | ||||
run_rx_frame(sc, m, dmalen); | run_rx_frame(sc, m, dmalen); | ||||
m = NULL; /* don't free source buffer */ | m = NULL; /* don't free source buffer */ | ||||
break; | break; | ||||
} | } | ||||
/* copy aggregated frames to another mbuf */ | /* copy aggregated frames to another mbuf */ | ||||
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | ||||
if (__predict_false(m0 == NULL)) { | if (__predict_false(m0 == NULL)) { | ||||
DPRINTF("could not allocate mbuf\n"); | RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC, | ||||
"could not allocate mbuf\n"); | |||||
counter_u64_add(ic->ic_ierrors, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
break; | break; | ||||
} | } | ||||
m_copydata(m, 4 /* skip 32-bit DMA-len header */, | m_copydata(m, 4 /* skip 32-bit DMA-len header */, | ||||
dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t)); | dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t)); | ||||
m0->m_pkthdr.len = m0->m_len = | m0->m_pkthdr.len = m0->m_len = | ||||
dmalen + sizeof(struct rt2870_rxd); | dmalen + sizeof(struct rt2870_rxd); | ||||
run_rx_frame(sc, m0, dmalen); | run_rx_frame(sc, m0, dmalen); | ||||
Show All 36 Lines | run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) | ||||
usb_frlength_t size; | usb_frlength_t size; | ||||
int actlen; | int actlen; | ||||
int sumlen; | int sumlen; | ||||
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); | usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); | ||||
switch (USB_GET_STATE(xfer)) { | switch (USB_GET_STATE(xfer)) { | ||||
case USB_ST_TRANSFERRED: | case USB_ST_TRANSFERRED: | ||||
DPRINTFN(11, "transfer complete: %d " | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_USB, | ||||
"bytes @ index %d\n", actlen, index); | "transfer complete: %d bytes @ index %d\n", actlen, index); | ||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
run_tx_free(pq, data, 0); | run_tx_free(pq, data, 0); | ||||
usbd_xfer_set_priv(xfer, NULL); | usbd_xfer_set_priv(xfer, NULL); | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case USB_ST_SETUP: | case USB_ST_SETUP: | ||||
tr_setup: | tr_setup: | ||||
data = STAILQ_FIRST(&pq->tx_qh); | data = STAILQ_FIRST(&pq->tx_qh); | ||||
if (data == NULL) | if (data == NULL) | ||||
break; | break; | ||||
STAILQ_REMOVE_HEAD(&pq->tx_qh, next); | STAILQ_REMOVE_HEAD(&pq->tx_qh, next); | ||||
m = data->m; | m = data->m; | ||||
size = (sc->mac_ver == 0x5592) ? | size = (sc->mac_ver == 0x5592) ? | ||||
sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc); | sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc); | ||||
if ((m->m_pkthdr.len + | if ((m->m_pkthdr.len + | ||||
size + 3 + 8) > RUN_MAX_TXSZ) { | size + 3 + 8) > RUN_MAX_TXSZ) { | ||||
DPRINTF("data overflow, %u bytes\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT_DESC | RUN_DEBUG_USB, | ||||
m->m_pkthdr.len); | "data overflow, %u bytes\n", m->m_pkthdr.len); | ||||
run_tx_free(pq, data, 1); | run_tx_free(pq, data, 1); | ||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
pc = usbd_xfer_get_frame(xfer, 0); | pc = usbd_xfer_get_frame(xfer, 0); | ||||
usbd_copy_in(pc, 0, &data->desc, size); | usbd_copy_in(pc, 0, &data->desc, size); | ||||
usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len); | usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len); | ||||
size += m->m_pkthdr.len; | size += m->m_pkthdr.len; | ||||
Show All 16 Lines | if (ieee80211_radiotap_active_vap(vap)) { | ||||
tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); | tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); | ||||
tap->wt_hwqueue = index; | tap->wt_hwqueue = index; | ||||
if (le16toh(txwi->phy) & RT2860_PHY_SHPRE) | if (le16toh(txwi->phy) & RT2860_PHY_SHPRE) | ||||
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||||
ieee80211_radiotap_tx(vap, m); | ieee80211_radiotap_tx(vap, m); | ||||
} | } | ||||
DPRINTFN(11, "sending frame len=%u/%u @ index %d\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_USB, | ||||
"sending frame len=%u/%u @ index %d\n", | |||||
m->m_pkthdr.len, size, index); | m->m_pkthdr.len, size, index); | ||||
usbd_xfer_set_frame_len(xfer, 0, size); | usbd_xfer_set_frame_len(xfer, 0, size); | ||||
usbd_xfer_set_priv(xfer, data); | usbd_xfer_set_priv(xfer, data); | ||||
usbd_transfer_submit(xfer); | usbd_transfer_submit(xfer); | ||||
run_start(sc); | run_start(sc); | ||||
break; | break; | ||||
default: | default: | ||||
DPRINTF("USB transfer error, %s\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_USB, | ||||
usbd_errstr(error)); | "USB transfer error, %s\n", usbd_errstr(error)); | ||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
if (data != NULL) { | if (data != NULL) { | ||||
if(data->ni != NULL) | if(data->ni != NULL) | ||||
vap = data->ni->ni_vap; | vap = data->ni->ni_vap; | ||||
run_tx_free(pq, data, error); | run_tx_free(pq, data, error); | ||||
usbd_xfer_set_priv(xfer, NULL); | usbd_xfer_set_priv(xfer, NULL); | ||||
} | } | ||||
if (vap == NULL) | if (vap == NULL) | ||||
vap = TAILQ_FIRST(&ic->ic_vaps); | vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
if (error == USB_ERR_TIMEOUT) { | if (error == USB_ERR_TIMEOUT) { | ||||
device_printf(sc->sc_dev, "device timeout\n"); | device_printf(sc->sc_dev, "device timeout\n"); | ||||
uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_USB, | ||||
"cmdq_store=%d\n", i); | |||||
sc->cmdq[i].func = run_usb_timeout_cb; | sc->cmdq[i].func = run_usb_timeout_cb; | ||||
sc->cmdq[i].arg0 = vap; | sc->cmdq[i].arg0 = vap; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
} | } | ||||
/* | /* | ||||
* Try to clear stall first, also if other | * Try to clear stall first, also if other | ||||
* errors occur, hence clearing stall | * errors occur, hence clearing stall | ||||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) { | ||||
qid = TID_TO_WME_AC(tid); | qid = TID_TO_WME_AC(tid); | ||||
} else { | } else { | ||||
qos = 0; | qos = 0; | ||||
tid = 0; | tid = 0; | ||||
qid = WME_AC_BE; | qid = WME_AC_BE; | ||||
} | } | ||||
qflags = (qid < 4) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_HCCA; | qflags = (qid < 4) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_HCCA; | ||||
DPRINTFN(8, "qos %d\tqid %d\ttid %d\tqflags %x\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "qos %d\tqid %d\ttid %d\tqflags %x\n", | ||||
qos, qid, tid, qflags); | qos, qid, tid, qflags); | ||||
chan = (ni->ni_chan != IEEE80211_CHAN_ANYC)?ni->ni_chan:ic->ic_curchan; | chan = (ni->ni_chan != IEEE80211_CHAN_ANYC)?ni->ni_chan:ic->ic_curchan; | ||||
tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; | tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; | ||||
/* pickup a rate index */ | /* pickup a rate index */ | ||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1) || | if (IEEE80211_IS_MULTICAST(wh->i_addr1) || | ||||
type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) { | type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) { | ||||
Show All 16 Lines | if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | ||||
dur = rt2860_rates[ctl_ridx].sp_ack_dur; | dur = rt2860_rates[ctl_ridx].sp_ack_dur; | ||||
else | else | ||||
dur = rt2860_rates[ctl_ridx].lp_ack_dur; | dur = rt2860_rates[ctl_ridx].lp_ack_dur; | ||||
USETW(wh->i_dur, dur); | USETW(wh->i_dur, dur); | ||||
} | } | ||||
/* reserve slots for mgmt packets, just in case */ | /* reserve slots for mgmt packets, just in case */ | ||||
if (sc->sc_epq[qid].tx_nfree < 3) { | if (sc->sc_epq[qid].tx_nfree < 3) { | ||||
DPRINTFN(10, "tx ring %d is full\n", qid); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "tx ring %d is full\n", qid); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->sc_epq[qid].tx_fh); | data = STAILQ_FIRST(&sc->sc_epq[qid].tx_fh); | ||||
STAILQ_REMOVE_HEAD(&sc->sc_epq[qid].tx_fh, next); | STAILQ_REMOVE_HEAD(&sc->sc_epq[qid].tx_fh, next); | ||||
sc->sc_epq[qid].tx_nfree--; | sc->sc_epq[qid].tx_nfree--; | ||||
txd = (struct rt2870_txd *)&data->desc; | txd = (struct rt2870_txd *)&data->desc; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (sc->rvp_cnt > 1 || vap->iv_opmode == IEEE80211_M_HOSTAP || | ||||
* Call it early. Otherwise overflow. | * Call it early. Otherwise overflow. | ||||
*/ | */ | ||||
if (sc->fifo_cnt++ == 10) { | if (sc->fifo_cnt++ == 10) { | ||||
/* | /* | ||||
* With multiple vaps or if_bridge, if_start() is called | * With multiple vaps or if_bridge, if_start() is called | ||||
* with a non-sleepable lock, tcpinp. So, need to defer. | * with a non-sleepable lock, tcpinp. So, need to defer. | ||||
*/ | */ | ||||
uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTFN(6, "cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_drain_fifo; | sc->cmdq[i].func = run_drain_fifo; | ||||
sc->cmdq[i].arg0 = sc; | sc->cmdq[i].arg0 = sc; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
} | } | ||||
} | } | ||||
STAILQ_INSERT_TAIL(&sc->sc_epq[qid].tx_qh, data, next); | STAILQ_INSERT_TAIL(&sc->sc_epq[qid].tx_qh, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[qid]); | usbd_transfer_start(sc->sc_xfer[qid]); | ||||
DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | ||||
"sending data frame len=%d rate=%d qid=%d\n", | |||||
m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) + | m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) + | ||||
sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate, qid); | sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate, qid); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
txwi->txop = 0; /* clear leftover garbage bits */ | txwi->txop = 0; /* clear leftover garbage bits */ | ||||
data->m = m; | data->m = m; | ||||
data->ni = ni; | data->ni = ni; | ||||
data->ridx = ridx; | data->ridx = ridx; | ||||
run_set_tx_desc(sc, data); | run_set_tx_desc(sc, data); | ||||
DPRINTFN(10, "sending mgt frame len=%d rate=%d\n", m->m_pkthdr.len + | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending mgt frame len=%d rate=%d\n", | ||||
(int)(sizeof(struct rt2870_txd) + sizeof(struct rt2860_txwi)), | m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) + | ||||
rt2860_rates[ridx].rate); | sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate); | ||||
STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[0]); | usbd_transfer_start(sc->sc_xfer[0]); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (prot == IEEE80211_PROT_RTSCTS) { | ||||
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); | dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); | ||||
xflags |= RT2860_TX_ACK; | xflags |= RT2860_TX_ACK; | ||||
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); | mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); | ||||
} else { | } else { | ||||
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); | mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); | ||||
} | } | ||||
if (mprot == NULL) { | if (mprot == NULL) { | ||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); | ||||
DPRINTF("could not allocate mbuf\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "could not allocate mbuf\n"); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh); | data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh); | ||||
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next); | STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next); | ||||
sc->sc_epq[0].tx_nfree--; | sc->sc_epq[0].tx_nfree--; | ||||
txd = (struct rt2870_txd *)&data->desc; | txd = (struct rt2870_txd *)&data->desc; | ||||
Show All 9 Lines | run_sendprot(struct run_softc *sc, | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | ||||
if (rt2860_rates[ridx].rate == protrate) | if (rt2860_rates[ridx].rate == protrate) | ||||
break; | break; | ||||
data->ridx = ridx; | data->ridx = ridx; | ||||
run_set_tx_desc(sc, data); | run_set_tx_desc(sc, data); | ||||
DPRINTFN(1, "sending prot len=%u rate=%u\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending prot len=%u rate=%u\n", | ||||
m->m_pkthdr.len, rate); | m->m_pkthdr.len, rate); | ||||
STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[0]); | usbd_transfer_start(sc->sc_xfer[0]); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 38 Lines | if (error) { | ||||
/* let caller free mbuf */ | /* let caller free mbuf */ | ||||
return error; | return error; | ||||
} | } | ||||
opflags |= /*XXX RT2573_TX_LONG_RETRY |*/ RT2860_TX_TXOP_SIFS; | opflags |= /*XXX RT2573_TX_LONG_RETRY |*/ RT2860_TX_TXOP_SIFS; | ||||
} | } | ||||
if (sc->sc_epq[0].tx_nfree == 0) { | if (sc->sc_epq[0].tx_nfree == 0) { | ||||
/* let caller free mbuf */ | /* let caller free mbuf */ | ||||
DPRINTF("sending raw frame, but tx ring is full\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | ||||
"sending raw frame, but tx ring is full\n"); | |||||
return (EIO); | return (EIO); | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh); | data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh); | ||||
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next); | STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next); | ||||
sc->sc_epq[0].tx_nfree--; | sc->sc_epq[0].tx_nfree--; | ||||
txd = (struct rt2870_txd *)&data->desc; | txd = (struct rt2870_txd *)&data->desc; | ||||
txd->flags = RT2860_TX_QSEL_EDCA; | txd->flags = RT2860_TX_QSEL_EDCA; | ||||
txwi = (struct rt2860_txwi *)(txd + 1); | txwi = (struct rt2860_txwi *)(txd + 1); | ||||
txwi->wcid = 0xff; | txwi->wcid = 0xff; | ||||
txwi->xflags = xflags; | txwi->xflags = xflags; | ||||
txwi->txop = opflags; | txwi->txop = opflags; | ||||
txwi->flags = 0; /* clear leftover garbage bits */ | txwi->flags = 0; /* clear leftover garbage bits */ | ||||
data->m = m; | data->m = m; | ||||
data->ni = ni; | data->ni = ni; | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | ||||
if (rt2860_rates[ridx].rate == rate) | if (rt2860_rates[ridx].rate == rate) | ||||
break; | break; | ||||
data->ridx = ridx; | data->ridx = ridx; | ||||
run_set_tx_desc(sc, data); | run_set_tx_desc(sc, data); | ||||
DPRINTFN(10, "sending raw frame len=%u rate=%u\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending raw frame len=%u rate=%u\n", | ||||
m->m_pkthdr.len, rate); | m->m_pkthdr.len, rate); | ||||
STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[0]); | usbd_transfer_start(sc->sc_xfer[0]); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 11 Lines | run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | ||||
if (!(sc->sc_flags & RUN_RUNNING)) { | if (!(sc->sc_flags & RUN_RUNNING)) { | ||||
error = ENETDOWN; | error = ENETDOWN; | ||||
goto done; | goto done; | ||||
} | } | ||||
if (params == NULL) { | if (params == NULL) { | ||||
/* tx mgt packet */ | /* tx mgt packet */ | ||||
if ((error = run_tx_mgt(sc, m, ni)) != 0) { | if ((error = run_tx_mgt(sc, m, ni)) != 0) { | ||||
DPRINTF("mgt tx failed\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "mgt tx failed\n"); | ||||
goto done; | goto done; | ||||
} | } | ||||
} else { | } else { | ||||
/* tx raw packet with param */ | /* tx raw packet with param */ | ||||
if ((error = run_tx_param(sc, m, ni, params)) != 0) { | if ((error = run_tx_param(sc, m, ni, params)) != 0) { | ||||
DPRINTF("tx with param failed\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "tx with param failed\n"); | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
done: | done: | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (error != 0) { | if (error != 0) { | ||||
▲ Show 20 Lines • Show All 1,199 Lines • ▼ Show 20 Lines | run_update_beacon(struct ieee80211vap *vap, int item) | ||||
if (rvp->beacon_mbuf == NULL) { | if (rvp->beacon_mbuf == NULL) { | ||||
rvp->beacon_mbuf = ieee80211_beacon_alloc(ni); | rvp->beacon_mbuf = ieee80211_beacon_alloc(ni); | ||||
if (rvp->beacon_mbuf == NULL) | if (rvp->beacon_mbuf == NULL) | ||||
return; | return; | ||||
} | } | ||||
ieee80211_beacon_update(ni, rvp->beacon_mbuf, mcast); | ieee80211_beacon_update(ni, rvp->beacon_mbuf, mcast); | ||||
i = RUN_CMDQ_GET(&sc->cmdq_store); | i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_BEACON, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_update_beacon_cb; | sc->cmdq[i].func = run_update_beacon_cb; | ||||
sc->cmdq[i].arg0 = vap; | sc->cmdq[i].arg0 = vap; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
return; | return; | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
run_updateprot(struct ieee80211com *ic) | run_updateprot(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint32_t i; | uint32_t i; | ||||
i = RUN_CMDQ_GET(&sc->cmdq_store); | i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_BEACON, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_updateprot_cb; | sc->cmdq[i].func = run_updateprot_cb; | ||||
sc->cmdq[i].arg0 = ic; | sc->cmdq[i].arg0 = ic; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
} | } | ||||
static void | static void | ||||
run_updateprot_cb(void *arg) | run_updateprot_cb(void *arg) | ||||
{ | { | ||||
Show All 25 Lines | run_usb_timeout_cb(void *arg) | ||||
struct run_softc *sc = vap->iv_ic->ic_softc; | struct run_softc *sc = vap->iv_ic->ic_softc; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
if(vap->iv_state == IEEE80211_S_RUN && | if(vap->iv_state == IEEE80211_S_RUN && | ||||
vap->iv_opmode != IEEE80211_M_STA) | vap->iv_opmode != IEEE80211_M_STA) | ||||
run_reset_livelock(sc); | run_reset_livelock(sc); | ||||
else if (vap->iv_state == IEEE80211_S_SCAN) { | else if (vap->iv_state == IEEE80211_S_SCAN) { | ||||
DPRINTF("timeout caused by scan\n"); | RUN_DPRINTF(sc, RUN_DEBUG_USB | RUN_DEBUG_STATE, | ||||
"timeout caused by scan\n"); | |||||
/* cancel bgscan */ | /* cancel bgscan */ | ||||
ieee80211_cancel_scan(vap); | ieee80211_cancel_scan(vap); | ||||
} else | } else | ||||
DPRINTF("timeout by unknown cause\n"); | RUN_DPRINTF(sc, RUN_DEBUG_USB | RUN_DEBUG_STATE, | ||||
"timeout by unknown cause\n"); | |||||
} | } | ||||
static void | static void | ||||
run_reset_livelock(struct run_softc *sc) | run_reset_livelock(struct run_softc *sc) | ||||
{ | { | ||||
uint32_t tmp; | uint32_t tmp; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* | /* | ||||
* In IBSS or HostAP modes (when the hardware sends beacons), the MAC | * In IBSS or HostAP modes (when the hardware sends beacons), the MAC | ||||
* can run into a livelock and start sending CTS-to-self frames like | * can run into a livelock and start sending CTS-to-self frames like | ||||
* crazy if protection is enabled. Reset MAC/BBP for a while | * crazy if protection is enabled. Reset MAC/BBP for a while | ||||
*/ | */ | ||||
run_read(sc, RT2860_DEBUG, &tmp); | run_read(sc, RT2860_DEBUG, &tmp); | ||||
DPRINTFN(3, "debug reg %08x\n", tmp); | RUN_DPRINTF(sc, RUN_DEBUG_RESET, "debug reg %08x\n", tmp); | ||||
if ((tmp & (1 << 29)) && (tmp & (1 << 7 | 1 << 5))) { | if ((tmp & (1 << 29)) && (tmp & (1 << 7 | 1 << 5))) { | ||||
DPRINTF("CTS-to-self livelock detected\n"); | RUN_DPRINTF(sc, RUN_DEBUG_RESET, | ||||
"CTS-to-self livelock detected\n"); | |||||
run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_SRST); | run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_SRST); | ||||
run_delay(sc, 1); | run_delay(sc, 1); | ||||
run_write(sc, RT2860_MAC_SYS_CTRL, | run_write(sc, RT2860_MAC_SYS_CTRL, | ||||
RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); | RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
run_update_promisc_locked(struct run_softc *sc) | run_update_promisc_locked(struct run_softc *sc) | ||||
{ | { | ||||
uint32_t tmp; | uint32_t tmp; | ||||
run_read(sc, RT2860_RX_FILTR_CFG, &tmp); | run_read(sc, RT2860_RX_FILTR_CFG, &tmp); | ||||
tmp |= RT2860_DROP_UC_NOME; | tmp |= RT2860_DROP_UC_NOME; | ||||
if (sc->sc_ic.ic_promisc > 0) | if (sc->sc_ic.ic_promisc > 0) | ||||
tmp &= ~RT2860_DROP_UC_NOME; | tmp &= ~RT2860_DROP_UC_NOME; | ||||
run_write(sc, RT2860_RX_FILTR_CFG, tmp); | run_write(sc, RT2860_RX_FILTR_CFG, tmp); | ||||
DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ? | RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s promiscuous mode\n", | ||||
"entering" : "leaving"); | (sc->sc_ic.ic_promisc > 0) ? "entering" : "leaving"); | ||||
} | } | ||||
static void | static void | ||||
run_update_promisc(struct ieee80211com *ic) | run_update_promisc(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_softc; | struct run_softc *sc = ic->ic_softc; | ||||
if ((sc->sc_flags & RUN_RUNNING) == 0) | if ((sc->sc_flags & RUN_RUNNING) == 0) | ||||
return; | return; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
run_update_promisc_locked(sc); | run_update_promisc_locked(sc); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
run_enable_tsf_sync(struct run_softc *sc) | run_enable_tsf_sync(struct run_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id, | RUN_DPRINTF(sc, RUN_DEBUG_BEACON, "rvp_id=%d ic_opmode=%d\n", | ||||
ic->ic_opmode); | RUN_VAP(vap)->rvp_id, ic->ic_opmode); | ||||
run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | ||||
tmp &= ~0x1fffff; | tmp &= ~0x1fffff; | ||||
tmp |= vap->iv_bss->ni_intval * 16; | tmp |= vap->iv_bss->ni_intval * 16; | ||||
tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; | tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; | ||||
if (ic->ic_opmode == IEEE80211_M_STA) { | if (ic->ic_opmode == IEEE80211_M_STA) { | ||||
/* | /* | ||||
Show All 9 Lines | tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; | ||||
*/ | */ | ||||
tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; | tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; | ||||
} else if (ic->ic_opmode == IEEE80211_M_HOSTAP || | } else if (ic->ic_opmode == IEEE80211_M_HOSTAP || | ||||
ic->ic_opmode == IEEE80211_M_MBSS) { | ic->ic_opmode == IEEE80211_M_MBSS) { | ||||
tmp |= RT2860_BCN_TX_EN; | tmp |= RT2860_BCN_TX_EN; | ||||
/* SYNC with nobody */ | /* SYNC with nobody */ | ||||
tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; | tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; | ||||
} else { | } else { | ||||
DPRINTF("Enabling TSF failed. undefined opmode\n"); | RUN_DPRINTF(sc, RUN_DEBUG_BEACON, | ||||
"Enabling TSF failed. undefined opmode\n"); | |||||
return; | return; | ||||
} | } | ||||
run_write(sc, RT2860_BCN_TIME_CFG, tmp); | run_write(sc, RT2860_BCN_TIME_CFG, tmp); | ||||
} | } | ||||
static void | static void | ||||
run_enable_tsf(struct run_softc *sc) | run_enable_tsf(struct run_softc *sc) | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
run_updateslot(struct ieee80211com *ic) | run_updateslot(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint32_t i; | uint32_t i; | ||||
i = RUN_CMDQ_GET(&sc->cmdq_store); | i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | RUN_DPRINTF(sc, RUN_DEBUG_BEACON, "cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_updateslot_cb; | sc->cmdq[i].func = run_updateslot_cb; | ||||
sc->cmdq[i].arg0 = ic; | sc->cmdq[i].arg0 = ic; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
return; | return; | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
▲ Show 20 Lines • Show All 1,002 Lines • ▼ Show 20 Lines | run_stop(void *arg) | ||||
/* disable Tx/Rx */ | /* disable Tx/Rx */ | ||||
run_read(sc, RT2860_MAC_SYS_CTRL, &tmp); | run_read(sc, RT2860_MAC_SYS_CTRL, &tmp); | ||||
tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); | tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); | ||||
run_write(sc, RT2860_MAC_SYS_CTRL, tmp); | run_write(sc, RT2860_MAC_SYS_CTRL, tmp); | ||||
/* wait for pending Tx to complete */ | /* wait for pending Tx to complete */ | ||||
for (ntries = 0; ntries < 100; ntries++) { | for (ntries = 0; ntries < 100; ntries++) { | ||||
if (run_read(sc, RT2860_TXRXQ_PCNT, &tmp) != 0) { | if (run_read(sc, RT2860_TXRXQ_PCNT, &tmp) != 0) { | ||||
DPRINTF("Cannot read Tx queue count\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_RESET, | ||||
"Cannot read Tx queue count\n"); | |||||
break; | break; | ||||
} | } | ||||
if ((tmp & RT2860_TX2Q_PCNT_MASK) == 0) { | if ((tmp & RT2860_TX2Q_PCNT_MASK) == 0) { | ||||
DPRINTF("All Tx cleared\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_RESET, | ||||
"All Tx cleared\n"); | |||||
break; | break; | ||||
} | } | ||||
run_delay(sc, 10); | run_delay(sc, 10); | ||||
} | } | ||||
if (ntries >= 100) | if (ntries >= 100) | ||||
DPRINTF("There are still pending Tx\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT | RUN_DEBUG_RESET, | ||||
"There are still pending Tx\n"); | |||||
run_delay(sc, 10); | run_delay(sc, 10); | ||||
run_write(sc, RT2860_USB_DMA_CFG, 0); | run_write(sc, RT2860_USB_DMA_CFG, 0); | ||||
run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); | run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); | ||||
run_write(sc, RT2860_MAC_SYS_CTRL, 0); | run_write(sc, RT2860_MAC_SYS_CTRL, 0); | ||||
for (i = 0; i != RUN_EP_QUEUES; i++) | for (i = 0; i != RUN_EP_QUEUES; i++) | ||||
run_unsetup_tx_list(sc, &sc->sc_epq[i]); | run_unsetup_tx_list(sc, &sc->sc_epq[i]); | ||||
Show All 31 Lines |