Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_run.c
Show First 20 Lines • Show All 404 Lines • ▼ Show 20 Lines | static int run_tx_mgt(struct run_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int run_sendprot(struct run_softc *, const struct mbuf *, | static int run_sendprot(struct run_softc *, const struct mbuf *, | ||||
struct ieee80211_node *, int, int); | struct ieee80211_node *, int, int); | ||||
static int run_tx_param(struct run_softc *, struct mbuf *, | static int run_tx_param(struct run_softc *, struct mbuf *, | ||||
struct ieee80211_node *, | struct ieee80211_node *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
static int run_raw_xmit(struct ieee80211_node *, struct mbuf *, | static int run_raw_xmit(struct ieee80211_node *, struct mbuf *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
static void run_start(struct ifnet *); | static int run_transmit(struct ieee80211com *, struct mbuf *); | ||||
static int run_ioctl(struct ifnet *, u_long, caddr_t); | static void run_start(struct run_softc *); | ||||
static void run_parent(struct ieee80211com *); | |||||
static void run_iq_calib(struct run_softc *, u_int); | static void run_iq_calib(struct run_softc *, u_int); | ||||
static void run_set_agc(struct run_softc *, uint8_t); | static void run_set_agc(struct run_softc *, uint8_t); | ||||
static void run_select_chan_group(struct run_softc *, int); | static void run_select_chan_group(struct run_softc *, int); | ||||
static void run_set_rx_antenna(struct run_softc *, int); | static void run_set_rx_antenna(struct run_softc *, int); | ||||
static void run_rt2870_set_chan(struct run_softc *, u_int); | static void run_rt2870_set_chan(struct run_softc *, u_int); | ||||
static void run_rt3070_set_chan(struct run_softc *, u_int); | static void run_rt3070_set_chan(struct run_softc *, u_int); | ||||
static void run_rt3572_set_chan(struct run_softc *, u_int); | static void run_rt3572_set_chan(struct run_softc *, u_int); | ||||
static void run_rt3593_set_chan(struct run_softc *, u_int); | static void run_rt3593_set_chan(struct run_softc *, u_int); | ||||
Show All 29 Lines | |||||
static void run_rt5390_rf_init(struct run_softc *); | static void run_rt5390_rf_init(struct run_softc *); | ||||
static int run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t, | static int run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t, | ||||
uint8_t *); | uint8_t *); | ||||
static void run_rt3070_rf_setup(struct run_softc *); | static void run_rt3070_rf_setup(struct run_softc *); | ||||
static void run_rt3593_rf_setup(struct run_softc *); | static void run_rt3593_rf_setup(struct run_softc *); | ||||
static void run_rt5390_rf_setup(struct run_softc *); | static void run_rt5390_rf_setup(struct run_softc *); | ||||
static int run_txrx_enable(struct run_softc *); | static int run_txrx_enable(struct run_softc *); | ||||
static void run_adjust_freq_offset(struct run_softc *); | static void run_adjust_freq_offset(struct run_softc *); | ||||
static void run_init(void *); | |||||
static void run_init_locked(struct run_softc *); | static void run_init_locked(struct run_softc *); | ||||
static void run_stop(void *); | static void run_stop(void *); | ||||
static void run_delay(struct run_softc *, u_int); | static void run_delay(struct run_softc *, u_int); | ||||
static eventhandler_tag run_etag; | static eventhandler_tag run_etag; | ||||
static const struct rt2860_rate { | static const struct rt2860_rate { | ||||
uint8_t rate; | uint8_t rate; | ||||
▲ Show 20 Lines • Show All 228 Lines • ▼ Show 20 Lines | run_match(device_t self) | ||||
return (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa)); | return (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa)); | ||||
} | } | ||||
static int | static int | ||||
run_attach(device_t self) | run_attach(device_t self) | ||||
{ | { | ||||
struct run_softc *sc = device_get_softc(self); | struct run_softc *sc = device_get_softc(self); | ||||
struct usb_attach_arg *uaa = device_get_ivars(self); | struct usb_attach_arg *uaa = device_get_ivars(self); | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ifnet *ifp; | |||||
uint32_t ver; | uint32_t ver; | ||||
int ntries, error; | int ntries, error; | ||||
uint8_t iface_index, bands; | uint8_t iface_index, bands; | ||||
device_set_usb_desc(self); | device_set_usb_desc(self); | ||||
sc->sc_udev = uaa->device; | sc->sc_udev = uaa->device; | ||||
sc->sc_dev = self; | sc->sc_dev = self; | ||||
if (USB_GET_DRIVER_INFO(uaa) != RUN_EJECT) | if (USB_GET_DRIVER_INFO(uaa) != RUN_EJECT) | ||||
sc->sc_flags |= RUN_FLAG_FWLOAD_NEEDED; | sc->sc_flags |= RUN_FLAG_FWLOAD_NEEDED; | ||||
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), | mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), | ||||
MTX_NETWORK_LOCK, MTX_DEF); | MTX_NETWORK_LOCK, MTX_DEF); | ||||
mbufq_init(&sc->sc_snd, ifqmaxlen); | |||||
iface_index = RT2860_IFACE_INDEX; | iface_index = RT2860_IFACE_INDEX; | ||||
error = usbd_transfer_setup(uaa->device, &iface_index, | error = usbd_transfer_setup(uaa->device, &iface_index, | ||||
sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_mtx); | sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_mtx); | ||||
if (error) { | if (error) { | ||||
device_printf(self, "could not allocate USB transfers, " | device_printf(self, "could not allocate USB transfers, " | ||||
"err=%s\n", usbd_errstr(error)); | "err=%s\n", usbd_errstr(error)); | ||||
Show All 22 Lines | run_attach(device_t self) | ||||
sc->mac_rev = ver & 0xffff; | sc->mac_rev = ver & 0xffff; | ||||
/* retrieve RF rev. no and various other things from EEPROM */ | /* retrieve RF rev. no and various other things from EEPROM */ | ||||
run_read_eeprom(sc); | run_read_eeprom(sc); | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n", | "MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n", | ||||
sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev), | sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev), | ||||
sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid)); | sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr)); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); | |||||
if (ifp == NULL) { | |||||
device_printf(sc->sc_dev, "can not if_alloc()\n"); | |||||
goto detach; | |||||
} | |||||
ic = ifp->if_l2com; | |||||
ifp->if_softc = sc; | |||||
if_initname(ifp, "run", device_get_unit(sc->sc_dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = run_init; | |||||
ifp->if_ioctl = run_ioctl; | |||||
ifp->if_start = run_start; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); | |||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ic->ic_ifp = ifp; | |||||
ic->ic_softc = sc; | ic->ic_softc = sc; | ||||
ic->ic_name = device_get_nameunit(self); | ic->ic_name = device_get_nameunit(self); | ||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ | ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ | ||||
ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ | ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ | ||||
/* set device capabilities */ | /* set device capabilities */ | ||||
ic->ic_caps = | ic->ic_caps = | ||||
IEEE80211_C_STA | /* station mode supported */ | IEEE80211_C_STA | /* station mode supported */ | ||||
Show All 20 Lines | run_attach(device_t self) | ||||
setbit(&bands, IEEE80211_MODE_11B); | setbit(&bands, IEEE80211_MODE_11B); | ||||
setbit(&bands, IEEE80211_MODE_11G); | setbit(&bands, IEEE80211_MODE_11G); | ||||
if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || | if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || | ||||
sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || | sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || | ||||
sc->rf_rev == RT5592_RF_5592) | sc->rf_rev == RT5592_RF_5592) | ||||
setbit(&bands, IEEE80211_MODE_11A); | setbit(&bands, IEEE80211_MODE_11A); | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
ieee80211_ifattach(ic, sc->sc_bssid); | ieee80211_ifattach(ic); | ||||
ic->ic_scan_start = run_scan_start; | ic->ic_scan_start = run_scan_start; | ||||
ic->ic_scan_end = run_scan_end; | ic->ic_scan_end = run_scan_end; | ||||
ic->ic_set_channel = run_set_channel; | ic->ic_set_channel = run_set_channel; | ||||
ic->ic_node_alloc = run_node_alloc; | ic->ic_node_alloc = run_node_alloc; | ||||
ic->ic_newassoc = run_newassoc; | ic->ic_newassoc = run_newassoc; | ||||
ic->ic_updateslot = run_updateslot; | ic->ic_updateslot = run_updateslot; | ||||
ic->ic_update_mcast = run_update_mcast; | ic->ic_update_mcast = run_update_mcast; | ||||
ic->ic_wme.wme_update = run_wme_update; | ic->ic_wme.wme_update = run_wme_update; | ||||
ic->ic_raw_xmit = run_raw_xmit; | ic->ic_raw_xmit = run_raw_xmit; | ||||
ic->ic_update_promisc = run_update_promisc; | ic->ic_update_promisc = run_update_promisc; | ||||
ic->ic_vap_create = run_vap_create; | ic->ic_vap_create = run_vap_create; | ||||
ic->ic_vap_delete = run_vap_delete; | ic->ic_vap_delete = run_vap_delete; | ||||
ic->ic_transmit = run_transmit; | |||||
ic->ic_parent = run_parent; | |||||
ieee80211_radiotap_attach(ic, | ieee80211_radiotap_attach(ic, | ||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), | &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), | ||||
RUN_TX_RADIOTAP_PRESENT, | RUN_TX_RADIOTAP_PRESENT, | ||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | ||||
RUN_RX_RADIOTAP_PRESENT); | RUN_RX_RADIOTAP_PRESENT); | ||||
TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc); | TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc); | ||||
Show All 9 Lines | detach: | ||||
run_detach(self); | run_detach(self); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | static int | ||||
run_detach(device_t self) | run_detach(device_t self) | ||||
{ | { | ||||
struct run_softc *sc = device_get_softc(self); | struct run_softc *sc = device_get_softc(self); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic; | |||||
int i; | int i; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
sc->sc_detached = 1; | sc->sc_detached = 1; | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
/* stop all USB transfers */ | /* stop all USB transfers */ | ||||
usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER); | usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER); | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
sc->ratectl_run = RUN_RATECTL_OFF; | sc->ratectl_run = RUN_RATECTL_OFF; | ||||
sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT; | sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT; | ||||
/* free TX list, if any */ | /* free TX list, if any */ | ||||
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]); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (ifp) { | if (sc->sc_ic.ic_softc == sc) { | ||||
ic = ifp->if_l2com; | |||||
/* drain tasks */ | /* drain tasks */ | ||||
usb_callout_drain(&sc->ratectl_ch); | usb_callout_drain(&sc->ratectl_ch); | ||||
ieee80211_draintask(ic, &sc->cmdq_task); | ieee80211_draintask(ic, &sc->cmdq_task); | ||||
ieee80211_draintask(ic, &sc->ratectl_task); | ieee80211_draintask(ic, &sc->ratectl_task); | ||||
ieee80211_ifdetach(ic); | ieee80211_ifdetach(ic); | ||||
if_free(ifp); | |||||
} | } | ||||
mbufq_drain(&sc->sc_snd); | |||||
mtx_destroy(&sc->sc_mtx); | mtx_destroy(&sc->sc_mtx); | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct ieee80211vap * | static struct ieee80211vap * | ||||
run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | ||||
enum ieee80211_opmode opmode, int flags, | enum ieee80211_opmode opmode, int flags, | ||||
const uint8_t bssid[IEEE80211_ADDR_LEN], | const uint8_t bssid[IEEE80211_ADDR_LEN], | ||||
const uint8_t mac[IEEE80211_ADDR_LEN]) | const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct run_softc *sc = ic->ic_softc; | ||||
struct run_softc *sc = ifp->if_softc; | |||||
struct run_vap *rvp; | struct run_vap *rvp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
int i; | int i; | ||||
if (sc->rvp_cnt >= RUN_VAP_MAX) { | if (sc->rvp_cnt >= RUN_VAP_MAX) { | ||||
if_printf(ifp, "number of VAPs maxed out\n"); | device_printf(sc->sc_dev, "number of VAPs maxed out\n"); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
switch (opmode) { | switch (opmode) { | ||||
case IEEE80211_M_STA: | case IEEE80211_M_STA: | ||||
/* enable s/w bmiss handling for sta mode */ | /* enable s/w bmiss handling for sta mode */ | ||||
flags |= IEEE80211_CLONE_NOBEACONS; | flags |= IEEE80211_CLONE_NOBEACONS; | ||||
/* fall though */ | /* fall though */ | ||||
Show All 9 Lines | case IEEE80211_M_WDS: | ||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next){ | TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next){ | ||||
if(vap->iv_opmode != IEEE80211_M_HOSTAP) | if(vap->iv_opmode != IEEE80211_M_HOSTAP) | ||||
continue; | continue; | ||||
/* WDS vap's always share the local mac address. */ | /* WDS vap's always share the local mac address. */ | ||||
flags &= ~IEEE80211_CLONE_BSSID; | flags &= ~IEEE80211_CLONE_BSSID; | ||||
break; | break; | ||||
} | } | ||||
if (vap == NULL) { | if (vap == NULL) { | ||||
if_printf(ifp, "wds only supported in ap mode\n"); | device_printf(sc->sc_dev, | ||||
"wds only supported in ap mode\n"); | |||||
return (NULL); | return (NULL); | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
if_printf(ifp, "unknown opmode %d\n", opmode); | device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
rvp = (struct run_vap *) malloc(sizeof(struct run_vap), | rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_NOWAIT | M_ZERO); | |||||
if (rvp == NULL) | |||||
return (NULL); | |||||
vap = &rvp->vap; | vap = &rvp->vap; | ||||
if (ieee80211_vap_setup(ic, vap, name, unit, | if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, | ||||
opmode, flags, bssid, mac) != 0) { | bssid) != 0) { | ||||
/* out of memory */ | /* out of memory */ | ||||
free(rvp, M_80211_VAP); | free(rvp, M_80211_VAP); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
vap->iv_key_update_begin = run_key_update_begin; | vap->iv_key_update_begin = run_key_update_begin; | ||||
vap->iv_key_update_end = run_key_update_end; | vap->iv_key_update_end = run_key_update_end; | ||||
vap->iv_update_beacon = run_update_beacon; | vap->iv_update_beacon = run_update_beacon; | ||||
Show All 10 Lines | run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | ||||
/* override state transition machine */ | /* override state transition machine */ | ||||
rvp->newstate = vap->iv_newstate; | rvp->newstate = vap->iv_newstate; | ||||
vap->iv_newstate = run_newstate; | vap->iv_newstate = run_newstate; | ||||
ieee80211_ratectl_init(vap); | ieee80211_ratectl_init(vap); | ||||
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); | ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); | ||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status); | ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status, | ||||
mac); | |||||
/* make sure id is always unique */ | /* make sure id is always unique */ | ||||
for (i = 0; i < RUN_VAP_MAX; i++) { | for (i = 0; i < RUN_VAP_MAX; i++) { | ||||
if((sc->rvp_bmap & 1 << i) == 0){ | if((sc->rvp_bmap & 1 << i) == 0){ | ||||
sc->rvp_bmap |= 1 << i; | sc->rvp_bmap |= 1 << i; | ||||
rvp->rvp_id = i; | rvp->rvp_id = i; | ||||
break; | break; | ||||
} | } | ||||
Show All 9 Lines | run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | ||||
return (vap); | return (vap); | ||||
} | } | ||||
static void | static void | ||||
run_vap_delete(struct ieee80211vap *vap) | run_vap_delete(struct ieee80211vap *vap) | ||||
{ | { | ||||
struct run_vap *rvp = RUN_VAP(vap); | struct run_vap *rvp = RUN_VAP(vap); | ||||
struct ifnet *ifp; | |||||
struct ieee80211com *ic; | struct ieee80211com *ic; | ||||
struct run_softc *sc; | struct run_softc *sc; | ||||
uint8_t rvp_id; | uint8_t rvp_id; | ||||
if (vap == NULL) | if (vap == NULL) | ||||
return; | return; | ||||
ic = vap->iv_ic; | ic = vap->iv_ic; | ||||
ifp = ic->ic_ifp; | sc = ic->ic_softc; | ||||
sc = ifp->if_softc; | |||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
m_freem(rvp->beacon_mbuf); | m_freem(rvp->beacon_mbuf); | ||||
rvp->beacon_mbuf = NULL; | rvp->beacon_mbuf = NULL; | ||||
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); | ||||
▲ Show 20 Lines • Show All 716 Lines • ▼ Show 20 Lines | DPRINTF("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; | |||||
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); | DPRINTF("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 & 0xff, val >> 8); | DPRINTF("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8); | ||||
/* read MAC address */ | /* read MAC address */ | ||||
run_srom_read(sc, RT2860_EEPROM_MAC01, &val); | run_srom_read(sc, RT2860_EEPROM_MAC01, &val); | ||||
sc->sc_bssid[0] = val & 0xff; | ic->ic_macaddr[0] = val & 0xff; | ||||
sc->sc_bssid[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); | ||||
sc->sc_bssid[2] = val & 0xff; | ic->ic_macaddr[2] = val & 0xff; | ||||
sc->sc_bssid[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); | ||||
sc->sc_bssid[4] = val & 0xff; | ic->ic_macaddr[4] = val & 0xff; | ||||
sc->sc_bssid[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, | DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, | ||||
▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
run_media_change(struct ifnet *ifp) | run_media_change(struct ifnet *ifp) | ||||
{ | { | ||||
struct ieee80211vap *vap = ifp->if_softc; | struct ieee80211vap *vap = ifp->if_softc; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint8_t rate, ridx; | uint8_t rate, ridx; | ||||
int error; | int error; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
error = ieee80211_media_change(ifp); | error = ieee80211_media_change(ifp); | ||||
if (error != ENETRESET) { | if (error != ENETRESET) { | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
Show All 14 Lines | if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { | ||||
rn = (struct run_node *)ni; | rn = (struct run_node *)ni; | ||||
rn->fix_ridx = ridx; | rn->fix_ridx = ridx; | ||||
DPRINTF("rate=%d, fix_ridx=%d\n", rate, rn->fix_ridx); | DPRINTF("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 & IFF_DRV_RUNNING)){ | (ifp->if_drv_flags & RUN_RUNNING)){ | ||||
run_init_locked(sc); | run_init_locked(sc); | ||||
} | } | ||||
#endif | #endif | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
{ | { | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct run_vap *rvp = RUN_VAP(vap); | struct run_vap *rvp = RUN_VAP(vap); | ||||
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; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | if (vap->iv_opmode != IEEE80211_M_MONITOR) { | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
run_updateslot(ic); | run_updateslot(ic); | ||||
run_enable_mrr(sc); | run_enable_mrr(sc); | ||||
run_set_txpreamble(sc); | run_set_txpreamble(sc); | ||||
run_set_basicrates(sc); | run_set_basicrates(sc); | ||||
ni = ieee80211_ref_node(vap->iv_bss); | ni = ieee80211_ref_node(vap->iv_bss); | ||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); | IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); | ||||
run_set_bssid(sc, ni->ni_bssid); | run_set_bssid(sc, ni->ni_bssid); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
run_enable_tsf_sync(sc); | run_enable_tsf_sync(sc); | ||||
/* enable automatic rate adaptation */ | /* enable automatic rate adaptation */ | ||||
tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; | tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; | ||||
if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) | if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) | ||||
ratectl |= bid; | ratectl |= bid; | ||||
Show All 20 Lines | run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
return(rvp->newstate(vap, nstate, arg)); | return(rvp->newstate(vap, nstate, arg)); | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void | static void | ||||
run_wme_update_cb(void *arg) | run_wme_update_cb(void *arg) | ||||
{ | { | ||||
struct ieee80211com *ic = arg; | struct ieee80211com *ic = arg; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct ieee80211_wme_state *wmesp = &ic->ic_wme; | struct ieee80211_wme_state *wmesp = &ic->ic_wme; | ||||
int aci, error = 0; | int aci, error = 0; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* update MAC TX configuration registers */ | /* update MAC TX configuration registers */ | ||||
for (aci = 0; aci < WME_NUM_AC; aci++) { | for (aci = 0; aci < WME_NUM_AC; aci++) { | ||||
error = run_write(sc, RT2860_EDCA_AC_CFG(aci), | error = run_write(sc, RT2860_EDCA_AC_CFG(aci), | ||||
Show All 36 Lines | if (error) | ||||
DPRINTF("WME update failed\n"); | DPRINTF("WME update failed\n"); | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
run_wme_update(struct ieee80211com *ic) | run_wme_update(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
/* sometime called wothout lock */ | /* sometime called wothout lock */ | ||||
if (mtx_owned(&ic->ic_comlock.mtx)) { | if (mtx_owned(&ic->ic_comlock.mtx)) { | ||||
uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); | ||||
DPRINTF("cmdq_store=%d\n", i); | DPRINTF("cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_wme_update_cb; | sc->cmdq[i].func = run_wme_update_cb; | ||||
sc->cmdq[i].arg0 = ic; | sc->cmdq[i].arg0 = ic; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
Show All 26 Lines | |||||
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; | ||||
struct ieee80211vap *vap = cmdq->arg1; | struct ieee80211vap *vap = cmdq->arg1; | ||||
struct ieee80211_key *k = cmdq->k; | struct ieee80211_key *k = cmdq->k; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
uint32_t attr; | uint32_t attr; | ||||
uint16_t base, associd; | uint16_t base, associd; | ||||
uint8_t mode, wcid, iv[8]; | uint8_t mode, wcid, iv[8]; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP) | if (vap->iv_opmode == IEEE80211_M_HOSTAP) | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* return 0 on error | * return 0 on error | ||||
*/ | */ | ||||
static int | static int | ||||
run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k, | run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k, | ||||
const uint8_t mac[IEEE80211_ADDR_LEN]) | const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_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); | DPRINTF("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; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* return 0 on error | * return 0 on error | ||||
*/ | */ | ||||
static int | static int | ||||
run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k) | run_key_delete(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_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct ieee80211_key *k0; | struct ieee80211_key *k0; | ||||
uint32_t i; | uint32_t i; | ||||
/* | /* | ||||
* 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. | ||||
Show All 14 Lines | |||||
} | } | ||||
static void | static void | ||||
run_ratectl_to(void *arg) | run_ratectl_to(void *arg) | ||||
{ | { | ||||
struct run_softc *sc = arg; | struct run_softc *sc = arg; | ||||
/* do it in a process context, so it can go sleep */ | /* do it in a process context, so it can go sleep */ | ||||
ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task); | ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task); | ||||
/* next timeout will be rescheduled in the callback task */ | /* next timeout will be rescheduled in the callback task */ | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void | static void | ||||
run_ratectl_cb(void *arg, int pending) | run_ratectl_cb(void *arg, int pending) | ||||
{ | { | ||||
struct run_softc *sc = arg; | struct run_softc *sc = arg; | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
if (vap == NULL) | if (vap == NULL) | ||||
return; | return; | ||||
if (sc->rvp_cnt > 1 || vap->iv_opmode != IEEE80211_M_STA) { | if (sc->rvp_cnt > 1 || vap->iv_opmode != IEEE80211_M_STA) { | ||||
/* | /* | ||||
* run_reset_livelock() doesn't do anything with AMRR, | * run_reset_livelock() doesn't do anything with AMRR, | ||||
Show All 16 Lines | 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); | ||||
} | } | ||||
static void | static void | ||||
run_drain_fifo(void *arg) | run_drain_fifo(void *arg) | ||||
{ | { | ||||
struct run_softc *sc = arg; | struct run_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t stat; | uint32_t stat; | ||||
uint16_t (*wstat)[3]; | uint16_t (*wstat)[3]; | ||||
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 (;;) { | ||||
Show All 20 Lines | for (;;) { | ||||
* To eliminate such page faults, we poll stats in softc. | * To eliminate such page faults, we poll stats in softc. | ||||
* Then, update the rates later with ieee80211_ratectl_tx_update(). | * Then, update the rates later with ieee80211_ratectl_tx_update(). | ||||
*/ | */ | ||||
wstat = &(sc->wcid_stats[wcid]); | wstat = &(sc->wcid_stats[wcid]); | ||||
(*wstat)[RUN_TXCNT]++; | (*wstat)[RUN_TXCNT]++; | ||||
if (stat & RT2860_TXQ_OK) | if (stat & RT2860_TXQ_OK) | ||||
(*wstat)[RUN_SUCCESS]++; | (*wstat)[RUN_SUCCESS]++; | ||||
else | else | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(sc->sc_ic.ic_oerrors, 1); | ||||
/* | /* | ||||
* Check if there were retries, ie if the Tx success rate is | * Check if there were retries, ie if the Tx success rate is | ||||
* different from the requested rate. Note that it works only | * different from the requested rate. Note that it works only | ||||
* because we do not allow rate fallback from OFDM to CCK. | * because we do not allow rate fallback from OFDM to CCK. | ||||
*/ | */ | ||||
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); | DPRINTFN(3, "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; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | |||||
struct ifnet *ifp = ic->ic_ifp; | |||||
struct run_node *rn = (void *)ni; | struct run_node *rn = (void *)ni; | ||||
union run_stats sta[2]; | union run_stats sta[2]; | ||||
uint16_t (*wstat)[3]; | uint16_t (*wstat)[3]; | ||||
int txcnt, success, retrycnt, error; | int txcnt, success, retrycnt, error; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
/* Check for special case */ | /* Check for special case */ | ||||
if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA && | if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA && | ||||
ni != vap->iv_bss) | ni != vap->iv_bss) | ||||
goto fail; | goto fail; | ||||
if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS || | if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS || | ||||
vap->iv_opmode == IEEE80211_M_STA)) { | vap->iv_opmode == IEEE80211_M_STA)) { | ||||
/* read statistic counters (clear on read) and update AMRR state */ | /* read statistic counters (clear on read) and update AMRR state */ | ||||
error = run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta, | error = run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta, | ||||
sizeof sta); | sizeof sta); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
/* count failed TX as errors */ | /* count failed TX as errors */ | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail)); | if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, | ||||
le16toh(sta[0].error.fail)); | |||||
retrycnt = le16toh(sta[1].tx.retry); | retrycnt = le16toh(sta[1].tx.retry); | ||||
success = le16toh(sta[1].tx.success); | success = le16toh(sta[1].tx.success); | ||||
txcnt = retrycnt + success + le16toh(sta[0].error.fail); | txcnt = retrycnt + success + le16toh(sta[0].error.fail); | ||||
DPRINTFN(3, "retrycnt=%d success=%d failcnt=%d\n", | DPRINTFN(3, "retrycnt=%d success=%d failcnt=%d\n", | ||||
retrycnt, success, le16toh(sta[0].error.fail)); | retrycnt, success, le16toh(sta[0].error.fail)); | ||||
} else { | } else { | ||||
Show All 21 Lines | fail: | ||||
DPRINTFN(3, "ridx=%d\n", rn->amrr_ridx); | DPRINTFN(3, "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_ifp->if_softc; | struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc; | ||||
uint8_t wcid = cmdq->wcid; | uint8_t wcid = cmdq->wcid; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
run_write_region_1(sc, RT2860_WCID_ENTRY(wcid), | run_write_region_1(sc, RT2860_WCID_ENTRY(wcid), | ||||
ni->ni_macaddr, IEEE80211_ADDR_LEN); | ni->ni_macaddr, IEEE80211_ADDR_LEN); | ||||
memset(&(sc->wcid_stats[wcid]), 0, sizeof(sc->wcid_stats[wcid])); | memset(&(sc->wcid_stats[wcid]), 0, sizeof(sc->wcid_stats[wcid])); | ||||
} | } | ||||
static void | static void | ||||
run_newassoc(struct ieee80211_node *ni, int isnew) | run_newassoc(struct ieee80211_node *ni, int isnew) | ||||
{ | { | ||||
struct run_node *rn = (void *)ni; | struct run_node *rn = (void *)ni; | ||||
struct ieee80211_rateset *rs = &ni->ni_rates; | struct ieee80211_rateset *rs = &ni->ni_rates; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint8_t rate; | uint8_t rate; | ||||
uint8_t ridx; | uint8_t ridx; | ||||
uint8_t wcid; | uint8_t wcid; | ||||
int i, j; | int i, j; | ||||
wcid = (vap->iv_opmode == IEEE80211_M_STA) ? | wcid = (vap->iv_opmode == IEEE80211_M_STA) ? | ||||
1 : RUN_AID2WCID(ni->ni_associd); | 1 : RUN_AID2WCID(ni->ni_associd); | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (sc->nrxchains > 2) | ||||
rxchain = 2; | rxchain = 2; | ||||
} | } | ||||
return (rxchain); | return (rxchain); | ||||
} | } | ||||
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) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct rt2870_rxd *rxd; | struct rt2870_rxd *rxd; | ||||
struct rt2860_rxwi *rxwi; | struct rt2860_rxwi *rxwi; | ||||
uint32_t flags; | uint32_t flags; | ||||
uint16_t len, rxwisize; | uint16_t len, rxwisize; | ||||
uint8_t ant, rssi; | uint8_t ant, rssi; | ||||
int8_t nf; | int8_t nf; | ||||
rxwi = mtod(m, struct rt2860_rxwi *); | rxwi = mtod(m, struct rt2860_rxwi *); | ||||
len = le16toh(rxwi->len) & 0xfff; | len = le16toh(rxwi->len) & 0xfff; | ||||
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); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("bad RXWI length %u > %u\n", len, dmalen); | DPRINTF("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); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV"); | DPRINTF("%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 *); | ||||
Show All 12 Lines | 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); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
DPRINTF("MIC error. Someone is lying.\n"); | DPRINTF("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.rcvif = ifp; | |||||
m->m_pkthdr.len = m->m_len = len; | m->m_pkthdr.len = m->m_len = len; | ||||
if (ni != NULL) { | if (ni != NULL) { | ||||
(void)ieee80211_input(ni, m, rssi, nf); | (void)ieee80211_input(ni, m, rssi, nf); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
} else { | } else { | ||||
(void)ieee80211_input_all(ic, m, rssi, nf); | (void)ieee80211_input_all(ic, m, rssi, nf); | ||||
} | } | ||||
Show All 36 Lines | if (__predict_false(ieee80211_radiotap_active(ic))) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct run_softc *sc = usbd_xfer_softc(xfer); | struct run_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct mbuf *m = NULL; | struct mbuf *m = NULL; | ||||
struct mbuf *m0; | struct mbuf *m0; | ||||
uint32_t dmalen; | uint32_t dmalen; | ||||
uint16_t rxwisize; | uint16_t rxwisize; | ||||
int xferlen; | int xferlen; | ||||
rxwisize = sizeof(struct rt2860_rxwi); | rxwisize = sizeof(struct rt2860_rxwi); | ||||
if (sc->mac_ver == 0x5592) | if (sc->mac_ver == 0x5592) | ||||
Show All 21 Lines | run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
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"); | DPRINTF("could not allocate mbuf - idle with stall\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_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. | ||||
*/ | */ | ||||
usbd_xfer_set_frame_data(xfer, 0, | usbd_xfer_set_frame_data(xfer, 0, | ||||
mtod(sc->rx_m, caddr_t), RUN_MAX_RXSZ); | mtod(sc->rx_m, caddr_t), RUN_MAX_RXSZ); | ||||
usbd_xfer_set_frames(xfer, 1); | usbd_xfer_set_frames(xfer, 1); | ||||
} | } | ||||
usbd_transfer_submit(xfer); | usbd_transfer_submit(xfer); | ||||
break; | break; | ||||
default: /* Error */ | default: /* Error */ | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
/* try to clear stall first */ | /* try to clear stall first */ | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
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"); | ||||
counter_u64_add(ic->ic_ierrors, 1); | |||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | |||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
if (sc->rx_m != NULL) { | if (sc->rx_m != NULL) { | ||||
m_freem(sc->rx_m); | m_freem(sc->rx_m); | ||||
sc->rx_m = NULL; | sc->rx_m = NULL; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
Show All 31 Lines | if ((xferlen -= dmalen + 8) <= 8) { | ||||
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"); | DPRINTF("could not allocate mbuf\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_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); | ||||
/* update data ptr */ | /* update data ptr */ | ||||
m->m_data += dmalen + 8; | m->m_data += dmalen + 8; | ||||
m->m_pkthdr.len = m->m_len -= dmalen + 8; | m->m_pkthdr.len = m->m_len -= dmalen + 8; | ||||
} | } | ||||
/* make sure we free the source buffer, if any */ | /* make sure we free the source buffer, if any */ | ||||
m_freem(m); | m_freem(m); | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
run_tx_free(struct run_endpoint_queue *pq, | run_tx_free(struct run_endpoint_queue *pq, struct run_tx_data *data, int txerr) | ||||
struct run_tx_data *data, int txerr) | |||||
{ | { | ||||
if (data->m != NULL) { | if (data->m != NULL) { | ||||
if (data->m->m_flags & M_TXCB) | ieee80211_tx_complete(data->ni, data->m, txerr); | ||||
ieee80211_process_callback(data->ni, data->m, | |||||
txerr ? ETIMEDOUT : 0); | |||||
m_freem(data->m); | |||||
data->m = NULL; | data->m = NULL; | ||||
if (data->ni == NULL) { | |||||
DPRINTF("no node\n"); | |||||
} else { | |||||
ieee80211_free_node(data->ni); | |||||
data->ni = NULL; | data->ni = NULL; | ||||
} | } | ||||
} | |||||
STAILQ_INSERT_TAIL(&pq->tx_fh, data, next); | STAILQ_INSERT_TAIL(&pq->tx_fh, data, next); | ||||
pq->tx_nfree++; | pq->tx_nfree++; | ||||
} | } | ||||
static void | static void | ||||
run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) | run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) | ||||
{ | { | ||||
struct run_softc *sc = usbd_xfer_softc(xfer); | struct run_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct run_tx_data *data; | struct run_tx_data *data; | ||||
struct ieee80211vap *vap = NULL; | struct ieee80211vap *vap = NULL; | ||||
struct usb_page_cache *pc; | struct usb_page_cache *pc; | ||||
struct run_endpoint_queue *pq = &sc->sc_epq[index]; | struct run_endpoint_queue *pq = &sc->sc_epq[index]; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
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 " | DPRINTFN(11, "transfer complete: %d " | ||||
"bytes @ index %d\n", actlen, index); | "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); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
usbd_xfer_set_priv(xfer, NULL); | usbd_xfer_set_priv(xfer, NULL); | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
/* 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", | DPRINTF("data overflow, %u bytes\n", | ||||
m->m_pkthdr.len); | m->m_pkthdr.len); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
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 20 Lines | if (ieee80211_radiotap_active_vap(vap)) { | ||||
ieee80211_radiotap_tx(vap, m); | ieee80211_radiotap_tx(vap, m); | ||||
} | } | ||||
DPRINTFN(11, "sending frame len=%u/%u @ index %d\n", | DPRINTFN(11, "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_UNLOCK(sc); | |||||
run_start(ifp); | |||||
RUN_LOCK(sc); | |||||
break; | break; | ||||
default: | default: | ||||
DPRINTF("USB transfer error, %s\n", | DPRINTF("USB transfer error, %s\n", | ||||
usbd_errstr(error)); | usbd_errstr(error)); | ||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
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); | DPRINTF("cmdq_store=%d\n", i); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
run_bulk_tx_callbackN(xfer, error, 5); | run_bulk_tx_callbackN(xfer, error, 5); | ||||
} | } | ||||
static void | static void | ||||
run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data) | run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data) | ||||
{ | { | ||||
struct mbuf *m = data->m; | struct mbuf *m = data->m; | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = data->ni->ni_vap; | struct ieee80211vap *vap = data->ni->ni_vap; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct rt2870_txd *txd; | struct rt2870_txd *txd; | ||||
struct rt2860_txwi *txwi; | struct rt2860_txwi *txwi; | ||||
uint16_t xferlen, txwisize; | uint16_t xferlen, txwisize; | ||||
uint16_t mcs; | uint16_t mcs; | ||||
uint8_t ridx = data->ridx; | uint8_t ridx = data->ridx; | ||||
uint8_t pad; | uint8_t pad; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data) | ||||
if (vap->iv_opmode != IEEE80211_M_STA && !IEEE80211_QOS_HAS_SEQ(wh)) | if (vap->iv_opmode != IEEE80211_M_STA && !IEEE80211_QOS_HAS_SEQ(wh)) | ||||
txwi->xflags |= RT2860_TX_NSEQ; | txwi->xflags |= RT2860_TX_NSEQ; | ||||
} | } | ||||
/* This function must be called locked */ | /* This function must be called locked */ | ||||
static int | static int | ||||
run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_channel *chan; | struct ieee80211_channel *chan; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct run_node *rn = (void *)ni; | struct run_node *rn = (void *)ni; | ||||
struct run_tx_data *data; | struct run_tx_data *data; | ||||
struct rt2870_txd *txd; | struct rt2870_txd *txd; | ||||
struct rt2860_txwi *txwi; | struct rt2860_txwi *txwi; | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", | ||||
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) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct run_node *rn = (void *)ni; | struct run_node *rn = (void *)ni; | ||||
struct run_tx_data *data; | struct run_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct rt2870_txd *txd; | struct rt2870_txd *txd; | ||||
struct rt2860_txwi *txwi; | struct rt2860_txwi *txwi; | ||||
uint16_t dur; | uint16_t dur; | ||||
uint8_t ridx = rn->mgt_ridx; | uint8_t ridx = rn->mgt_ridx; | ||||
uint8_t type; | uint8_t type; | ||||
Show All 14 Lines | run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
else if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | else if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | ||||
xflags |= RT2860_TX_ACK; | xflags |= RT2860_TX_ACK; | ||||
dur = ieee80211_ack_duration(ic->ic_rt, rt2860_rates[ridx].rate, | dur = ieee80211_ack_duration(ic->ic_rt, rt2860_rates[ridx].rate, | ||||
ic->ic_flags & IEEE80211_F_SHPREAMBLE); | ic->ic_flags & IEEE80211_F_SHPREAMBLE); | ||||
USETW(wh->i_dur, dur); | USETW(wh->i_dur, dur); | ||||
} | } | ||||
if (sc->sc_epq[0].tx_nfree == 0) { | if (sc->sc_epq[0].tx_nfree == 0) | ||||
/* let caller free mbuf */ | /* let caller free mbuf */ | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
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; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | run_sendprot(struct run_softc *sc, | ||||
ackrate = ieee80211_ack_rate(ic->ic_rt, rate); | ackrate = ieee80211_ack_rate(ic->ic_rt, rate); | ||||
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; | isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; | ||||
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) | dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) | ||||
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort); | + ieee80211_ack_duration(ic->ic_rt, rate, isshort); | ||||
wflags = RT2860_TX_FRAG; | wflags = RT2860_TX_FRAG; | ||||
/* check that there are free slots before allocating the mbuf */ | /* check that there are free slots before allocating the mbuf */ | ||||
if (sc->sc_epq[0].tx_nfree == 0) { | if (sc->sc_epq[0].tx_nfree == 0) | ||||
/* let caller free mbuf */ | /* let caller free mbuf */ | ||||
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | |||||
if (prot == IEEE80211_PROT_RTSCTS) { | if (prot == IEEE80211_PROT_RTSCTS) { | ||||
/* NB: CTS is the same size as an ACK */ | /* NB: CTS is the same size as an ACK */ | ||||
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(sc->sc_ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); | ||||
DPRINTF("could not allocate mbuf\n"); | DPRINTF("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--; | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 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 */ | ||||
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
DPRINTF("sending raw frame, but tx ring is full\n"); | DPRINTF("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; | ||||
Show All 22 Lines | usbd_transfer_start(sc->sc_xfer[0]); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | ||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ifnet *ifp = ni->ni_ic->ic_ifp; | struct run_softc *sc = ni->ni_ic->ic_softc; | ||||
struct run_softc *sc = ifp->if_softc; | |||||
int error = 0; | int error = 0; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
/* prevent management frames from being sent if we're not ready */ | /* prevent management frames from being sent if we're not ready */ | ||||
if (!(ifp->if_drv_flags & IFF_DRV_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) { | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
DPRINTF("mgt tx failed\n"); | DPRINTF("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) { | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
DPRINTF("tx with param failed\n"); | DPRINTF("tx with param failed\n"); | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
done: | done: | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (error != 0) { | if (error != 0) { | ||||
if(m != NULL) | if(m != NULL) | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
run_transmit(struct ieee80211com *ic, struct mbuf *m) | |||||
{ | |||||
struct run_softc *sc = ic->ic_softc; | |||||
int error; | |||||
RUN_LOCK(sc); | |||||
if ((sc->sc_flags & RUN_RUNNING) == 0) { | |||||
RUN_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | |||||
error = mbufq_enqueue(&sc->sc_snd, m); | |||||
if (error) { | |||||
RUN_UNLOCK(sc); | |||||
return (error); | |||||
} | |||||
run_start(sc); | |||||
RUN_UNLOCK(sc); | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
run_start(struct ifnet *ifp) | run_start(struct run_softc *sc) | ||||
{ | { | ||||
struct run_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
RUN_LOCK(sc); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | if ((sc->sc_flags & RUN_RUNNING) == 0) | ||||
RUN_UNLOCK(sc); | |||||
return; | return; | ||||
} | |||||
for (;;) { | while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | ||||
/* send data frames */ | |||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | |||||
if (m == NULL) | |||||
break; | |||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; | ||||
if (run_tx(sc, m, ni) != 0) { | if (run_tx(sc, m, ni) != 0) { | ||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | mbufq_prepend(&sc->sc_snd, m); | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
RUN_UNLOCK(sc); | |||||
} | } | ||||
static int | static void | ||||
run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | run_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | |||||
struct ifreq *ifr = (struct ifreq *) data; | |||||
int startall = 0; | int startall = 0; | ||||
int error; | |||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
error = sc->sc_detached ? ENXIO : 0; | if (sc->sc_detached) { | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (error) | return; | ||||
return (error); | } | ||||
switch (cmd) { | if (ic->ic_nrunning > 0) { | ||||
case SIOCSIFFLAGS: | if (!(sc->sc_flags & RUN_RUNNING)) { | ||||
RUN_LOCK(sc); | |||||
if (ifp->if_flags & IFF_UP) { | |||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){ | |||||
startall = 1; | startall = 1; | ||||
run_init_locked(sc); | run_init_locked(sc); | ||||
} else | } else | ||||
run_update_promisc_locked(sc); | run_update_promisc_locked(sc); | ||||
} else { | } else if ((sc->sc_flags & RUN_RUNNING) && sc->rvp_cnt <= 1) | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING && | |||||
(ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) { | |||||
run_stop(sc); | run_stop(sc); | ||||
} | |||||
} | |||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
if (startall) | if (startall) | ||||
ieee80211_start_all(ic); | 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); | |||||
} | |||||
static void | static void | ||||
run_iq_calib(struct run_softc *sc, u_int chan) | run_iq_calib(struct run_softc *sc, u_int chan) | ||||
{ | { | ||||
uint16_t val; | uint16_t val; | ||||
/* Tx0 IQ gain. */ | /* Tx0 IQ gain. */ | ||||
run_bbp_write(sc, 158, 0x2c); | run_bbp_write(sc, 158, 0x2c); | ||||
if (chan <= 14) | if (chan <= 14) | ||||
▲ Show 20 Lines • Show All 968 Lines • ▼ Show 20 Lines | if (sc->rf_rev == RT5390_RF_5370) { | ||||
run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808); | run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) | run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
u_int chan, group; | u_int chan, group; | ||||
chan = ieee80211_chan2ieee(ic, c); | chan = ieee80211_chan2ieee(ic, c); | ||||
if (chan == 0 || chan == IEEE80211_CHAN_ANY) | if (chan == 0 || chan == IEEE80211_CHAN_ANY) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (sc->mac_ver == 0x5592) | if (sc->mac_ver == 0x5592) | ||||
run_rt5592_set_chan(sc, chan); | run_rt5592_set_chan(sc, chan); | ||||
Show All 28 Lines | if (sc->mac_ver >= 0x5392) | ||||
run_iq_calib(sc, chan); | run_iq_calib(sc, chan); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
run_set_channel(struct ieee80211com *ic) | run_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
run_set_chan(sc, ic->ic_curchan); | run_set_chan(sc, ic->ic_curchan); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
static void | static void | ||||
run_scan_start(struct ieee80211com *ic) | run_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
/* abort TSF synchronization */ | /* abort TSF synchronization */ | ||||
run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | ||||
run_write(sc, RT2860_BCN_TIME_CFG, | run_write(sc, RT2860_BCN_TIME_CFG, | ||||
tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | | tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | | ||||
RT2860_TBTT_TIMER_EN)); | RT2860_TBTT_TIMER_EN)); | ||||
run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr); | run_set_bssid(sc, ieee80211broadcastaddr); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
static void | static void | ||||
run_scan_end(struct ieee80211com *ic) | run_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
RUN_LOCK(sc); | RUN_LOCK(sc); | ||||
run_enable_tsf_sync(sc); | run_enable_tsf_sync(sc); | ||||
/* XXX keep local copy */ | /* XXX keep local copy */ | ||||
run_set_bssid(sc, sc->sc_bssid); | run_set_bssid(sc, ic->ic_macaddr); | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Could be called from ieee80211_node_timeout() | * Could be called from ieee80211_node_timeout() | ||||
* (non-sleepable thread) | * (non-sleepable thread) | ||||
*/ | */ | ||||
static void | static void | ||||
run_update_beacon(struct ieee80211vap *vap, int item) | run_update_beacon(struct ieee80211vap *vap, int item) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct run_vap *rvp = RUN_VAP(vap); | struct run_vap *rvp = RUN_VAP(vap); | ||||
int mcast = 0; | int mcast = 0; | ||||
uint32_t i; | uint32_t i; | ||||
KASSERT(vap != NULL, ("no beacon")); | KASSERT(vap != NULL, ("no beacon")); | ||||
switch (item) { | switch (item) { | ||||
case IEEE80211_BEACON_ERP: | case IEEE80211_BEACON_ERP: | ||||
Show All 28 Lines | |||||
} | } | ||||
static void | static void | ||||
run_update_beacon_cb(void *arg) | run_update_beacon_cb(void *arg) | ||||
{ | { | ||||
struct ieee80211vap *vap = arg; | struct ieee80211vap *vap = arg; | ||||
struct run_vap *rvp = RUN_VAP(vap); | struct run_vap *rvp = RUN_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct rt2860_txwi txwi; | struct rt2860_txwi txwi; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
uint16_t txwisize; | uint16_t txwisize; | ||||
uint8_t ridx; | uint8_t ridx; | ||||
if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) | if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) | ||||
return; | return; | ||||
if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) | if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) | ||||
Show All 31 Lines | run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id), (uint8_t *)&txwi, | ||||
txwisize); | txwisize); | ||||
run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + txwisize, | run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + txwisize, | ||||
mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1); | mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1); | ||||
} | } | ||||
static void | static void | ||||
run_updateprot(struct ieee80211com *ic) | run_updateprot(struct ieee80211com *ic) | ||||
{ | { | ||||
struct run_softc *sc = ic->ic_ifp->if_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); | DPRINTF("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) | ||||
{ | { | ||||
struct ieee80211com *ic = arg; | struct ieee80211com *ic = arg; | ||||
struct run_softc *sc = ic->ic_ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; | tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; | ||||
/* setup protection frame rate (MCS code) */ | /* setup protection frame rate (MCS code) */ | ||||
tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ? | tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ? | ||||
rt2860_rates[RT2860_RIDX_OFDM6].mcs | RT2860_PHY_OFDM : | rt2860_rates[RT2860_RIDX_OFDM6].mcs | RT2860_PHY_OFDM : | ||||
rt2860_rates[RT2860_RIDX_CCK11].mcs; | rt2860_rates[RT2860_RIDX_CCK11].mcs; | ||||
/* CCK frames don't require protection */ | /* CCK frames don't require protection */ | ||||
run_write(sc, RT2860_CCK_PROT_CFG, tmp); | run_write(sc, RT2860_CCK_PROT_CFG, tmp); | ||||
if (ic->ic_flags & IEEE80211_F_USEPROT) { | if (ic->ic_flags & IEEE80211_F_USEPROT) { | ||||
if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) | if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) | ||||
tmp |= RT2860_PROT_CTRL_RTS_CTS; | tmp |= RT2860_PROT_CTRL_RTS_CTS; | ||||
else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) | else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) | ||||
tmp |= RT2860_PROT_CTRL_CTS; | tmp |= RT2860_PROT_CTRL_CTS; | ||||
} | } | ||||
run_write(sc, RT2860_OFDM_PROT_CFG, tmp); | run_write(sc, RT2860_OFDM_PROT_CFG, tmp); | ||||
} | } | ||||
static void | static void | ||||
run_usb_timeout_cb(void *arg) | run_usb_timeout_cb(void *arg) | ||||
{ | { | ||||
struct ieee80211vap *vap = arg; | struct ieee80211vap *vap = arg; | ||||
struct run_softc *sc = vap->iv_ic->ic_ifp->if_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"); | DPRINTF("timeout caused by scan\n"); | ||||
Show All 29 Lines | |||||
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_ifp->if_flags & IFF_PROMISC) | 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_ifp->if_flags & IFF_PROMISC) ? | DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ? | ||||
"entering" : "leaving"); | "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 ((ic->ic_ifp->if_drv_flags & IFF_DRV_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_ifp->if_l2com; | 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, | DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id, | ||||
ic->ic_opmode); | ic->ic_opmode); | ||||
run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | run_read(sc, RT2860_BCN_TIME_CFG, &tmp); | ||||
tmp &= ~0x1fffff; | tmp &= ~0x1fffff; | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | run_write(sc, RT2860_LG_FBK_CFG1, | ||||
CCK(0)); /* 1-> 1 */ | CCK(0)); /* 1-> 1 */ | ||||
#undef OFDM | #undef OFDM | ||||
#undef CCK | #undef CCK | ||||
} | } | ||||
static void | static void | ||||
run_set_txpreamble(struct run_softc *sc) | run_set_txpreamble(struct run_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
run_read(sc, RT2860_AUTO_RSP_CFG, &tmp); | run_read(sc, RT2860_AUTO_RSP_CFG, &tmp); | ||||
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | ||||
tmp |= RT2860_CCK_SHORT_EN; | tmp |= RT2860_CCK_SHORT_EN; | ||||
else | else | ||||
tmp &= ~RT2860_CCK_SHORT_EN; | tmp &= ~RT2860_CCK_SHORT_EN; | ||||
run_write(sc, RT2860_AUTO_RSP_CFG, tmp); | run_write(sc, RT2860_AUTO_RSP_CFG, tmp); | ||||
} | } | ||||
static void | static void | ||||
run_set_basicrates(struct run_softc *sc) | run_set_basicrates(struct run_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
/* set basic rates mask */ | /* set basic rates mask */ | ||||
if (ic->ic_curmode == IEEE80211_MODE_11B) | if (ic->ic_curmode == IEEE80211_MODE_11B) | ||||
run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x003); | run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x003); | ||||
else if (ic->ic_curmode == IEEE80211_MODE_11A) | else if (ic->ic_curmode == IEEE80211_MODE_11A) | ||||
run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x150); | run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x150); | ||||
else /* 11g */ | else /* 11g */ | ||||
run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x15f); | run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x15f); | ||||
Show All 28 Lines | |||||
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); | DPRINTF("cmdq_store=%d\n", i); | ||||
sc->cmdq[i].func = run_updateslot_cb; | sc->cmdq[i].func = run_updateslot_cb; | ||||
sc->cmdq[i].arg0 = ic->ic_ifp; | sc->cmdq[i].arg0 = ic; | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
return; | return; | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void | static void | ||||
run_updateslot_cb(void *arg) | run_updateslot_cb(void *arg) | ||||
{ | { | ||||
struct ifnet *ifp = arg; | struct ieee80211com *ic = arg; | ||||
struct run_softc *sc = ifp->if_softc; | struct run_softc *sc = ic->ic_softc; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp); | run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp); | ||||
tmp &= ~0xff; | tmp &= ~0xff; | ||||
tmp |= (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | tmp |= (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | ||||
run_write(sc, RT2860_BKOFF_SLOT_CFG, tmp); | run_write(sc, RT2860_BKOFF_SLOT_CFG, tmp); | ||||
} | } | ||||
static void | static void | ||||
run_update_mcast(struct ieee80211com *ic) | run_update_mcast(struct ieee80211com *ic) | ||||
{ | { | ||||
/* h/w filter supports getting everything or nothing */ | |||||
ic->ic_ifp->if_flags |= IFF_ALLMULTI; | |||||
} | } | ||||
static int8_t | static int8_t | ||||
run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain) | run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211_channel *c = ic->ic_curchan; | struct ieee80211_channel *c = ic->ic_curchan; | ||||
int delta; | int delta; | ||||
if (IEEE80211_IS_CHAN_5GHZ(c)) { | if (IEEE80211_IS_CHAN_5GHZ(c)) { | ||||
u_int chan = ieee80211_chan2ieee(ic, c); | u_int chan = ieee80211_chan2ieee(ic, c); | ||||
delta = sc->rssi_5ghz[rxchain]; | delta = sc->rssi_5ghz[rxchain]; | ||||
/* determine channel group */ | /* determine channel group */ | ||||
▲ Show 20 Lines • Show All 633 Lines • ▼ Show 20 Lines | if (sc->mac_ver != 0x5592) { | ||||
} else | } else | ||||
run_write(sc, RT2860_TX_SW_CFG2, 0); | run_write(sc, RT2860_TX_SW_CFG2, 0); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
run_txrx_enable(struct run_softc *sc) | run_txrx_enable(struct run_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
int error, ntries; | int error, ntries; | ||||
run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); | run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); | ||||
for (ntries = 0; ntries < 200; ntries++) { | for (ntries = 0; ntries < 200; ntries++) { | ||||
if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0) | if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0) | ||||
return (error); | return (error); | ||||
if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) | if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | run_adjust_freq_offset(struct run_softc *sc) | ||||
if (tmp != rf) | if (tmp != rf) | ||||
run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf); | run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf); | ||||
} | } | ||||
static void | static void | ||||
run_init_locked(struct run_softc *sc) | run_init_locked(struct run_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
uint8_t bbp1, bbp3; | uint8_t bbp1, bbp3; | ||||
int i; | int i; | ||||
int ridx; | int ridx; | ||||
int ntries; | int ntries; | ||||
if (ic->ic_nrunning > 1) | if (ic->ic_nrunning > 1) | ||||
return; | return; | ||||
Show All 13 Lines | for (ntries = 0; ntries < 100; ntries++) { | ||||
run_delay(sc, 10); | run_delay(sc, 10); | ||||
} | } | ||||
if (ntries == 100) | if (ntries == 100) | ||||
goto fail; | goto fail; | ||||
for (i = 0; i != RUN_EP_QUEUES; i++) | for (i = 0; i != RUN_EP_QUEUES; i++) | ||||
run_setup_tx_list(sc, &sc->sc_epq[i]); | run_setup_tx_list(sc, &sc->sc_epq[i]); | ||||
run_set_macaddr(sc, IF_LLADDR(ifp)); | run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); | ||||
for (ntries = 0; ntries < 100; ntries++) { | for (ntries = 0; ntries < 100; ntries++) { | ||||
if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0) | if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0) | ||||
goto fail; | goto fail; | ||||
if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) | if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) | ||||
break; | break; | ||||
run_delay(sc, 10); | run_delay(sc, 10); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | run_init_locked(struct run_softc *sc) | ||||
run_set_chan(sc, ic->ic_curchan); | run_set_chan(sc, ic->ic_curchan); | ||||
/* setup initial protection mode */ | /* setup initial protection mode */ | ||||
run_updateprot_cb(ic); | run_updateprot_cb(ic); | ||||
/* turn radio LED on */ | /* turn radio LED on */ | ||||
run_set_leds(sc, RT2860_LED_RADIO); | run_set_leds(sc, RT2860_LED_RADIO); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | sc->sc_flags |= RUN_RUNNING; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
sc->cmdq_run = RUN_CMDQ_GO; | sc->cmdq_run = RUN_CMDQ_GO; | ||||
for (i = 0; i != RUN_N_XFER; i++) | for (i = 0; i != RUN_N_XFER; i++) | ||||
usbd_xfer_set_stall(sc->sc_xfer[i]); | usbd_xfer_set_stall(sc->sc_xfer[i]); | ||||
usbd_transfer_start(sc->sc_xfer[RUN_BULK_RX]); | usbd_transfer_start(sc->sc_xfer[RUN_BULK_RX]); | ||||
if (run_txrx_enable(sc) != 0) | if (run_txrx_enable(sc) != 0) | ||||
goto fail; | goto fail; | ||||
return; | return; | ||||
fail: | fail: | ||||
run_stop(sc); | run_stop(sc); | ||||
} | } | ||||
static void | static void | ||||
run_init(void *arg) | |||||
{ | |||||
struct run_softc *sc = arg; | |||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
RUN_LOCK(sc); | |||||
run_init_locked(sc); | |||||
RUN_UNLOCK(sc); | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
ieee80211_start_all(ic); | |||||
} | |||||
static void | |||||
run_stop(void *arg) | run_stop(void *arg) | ||||
{ | { | ||||
struct run_softc *sc = (struct run_softc *)arg; | struct run_softc *sc = (struct run_softc *)arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
int i; | int i; | ||||
int ntries; | int ntries; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->sc_flags & RUN_RUNNING) | ||||
run_set_leds(sc, 0); /* turn all LEDs off */ | run_set_leds(sc, 0); /* turn all LEDs off */ | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | sc->sc_flags &= ~RUN_RUNNING; | ||||
sc->ratectl_run = RUN_RATECTL_OFF; | sc->ratectl_run = RUN_RATECTL_OFF; | ||||
sc->cmdq_run = sc->cmdq_key_set; | sc->cmdq_run = sc->cmdq_key_set; | ||||
RUN_UNLOCK(sc); | RUN_UNLOCK(sc); | ||||
for(i = 0; i < RUN_N_XFER; i++) | for(i = 0; i < RUN_N_XFER; i++) | ||||
usbd_transfer_drain(sc->sc_xfer[i]); | usbd_transfer_drain(sc->sc_xfer[i]); | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |