Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_run.c
Show First 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | |||||
static void run_tx_free(struct run_endpoint_queue *pq, | static void run_tx_free(struct run_endpoint_queue *pq, | ||||
struct run_tx_data *, int); | struct run_tx_data *, int); | ||||
static void run_set_tx_desc(struct run_softc *, struct run_tx_data *); | static void run_set_tx_desc(struct run_softc *, struct run_tx_data *); | ||||
static int run_tx(struct run_softc *, struct mbuf *, | static int run_tx(struct run_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int run_tx_mgt(struct run_softc *, struct mbuf *, | 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, uint16_t); | ||||
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 int run_transmit(struct ieee80211com *, struct mbuf *); | static int run_transmit(struct ieee80211com *, struct mbuf *); | ||||
static void run_start(struct run_softc *); | static void run_start(struct run_softc *); | ||||
static void run_parent(struct ieee80211com *); | static void run_parent(struct ieee80211com *); | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
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; | ||||
uint8_t mcs; | uint8_t mcs; | ||||
enum ieee80211_phytype phy; | enum ieee80211_phytype phy; | ||||
uint8_t ctl_ridx; | |||||
uint16_t sp_ack_dur; | |||||
uint16_t lp_ack_dur; | |||||
} rt2860_rates[] = { | } rt2860_rates[] = { | ||||
{ 2, 0, IEEE80211_T_DS, 0, 314, 314 }, | { 2, 0, IEEE80211_T_DS }, | ||||
{ 4, 1, IEEE80211_T_DS, 1, 258, 162 }, | { 4, 1, IEEE80211_T_DS }, | ||||
{ 11, 2, IEEE80211_T_DS, 2, 223, 127 }, | { 11, 2, IEEE80211_T_DS }, | ||||
{ 22, 3, IEEE80211_T_DS, 3, 213, 117 }, | { 22, 3, IEEE80211_T_DS }, | ||||
{ 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, | { 12, 0, IEEE80211_T_OFDM }, | ||||
{ 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, | { 18, 1, IEEE80211_T_OFDM }, | ||||
{ 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, | { 24, 2, IEEE80211_T_OFDM }, | ||||
{ 36, 3, IEEE80211_T_OFDM, 6, 44, 44 }, | { 36, 3, IEEE80211_T_OFDM }, | ||||
{ 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, | { 48, 4, IEEE80211_T_OFDM }, | ||||
{ 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, | { 72, 5, IEEE80211_T_OFDM }, | ||||
{ 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, | { 96, 6, IEEE80211_T_OFDM }, | ||||
{ 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } | { 108, 7, IEEE80211_T_OFDM } | ||||
}; | }; | ||||
static const struct { | static const struct { | ||||
uint16_t reg; | uint16_t reg; | ||||
uint32_t val; | uint32_t val; | ||||
} rt2870_def_mac[] = { | } rt2870_def_mac[] = { | ||||
RT2870_DEF_MAC | RT2870_DEF_MAC | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 1,501 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static struct ieee80211_node * | static struct ieee80211_node * | ||||
run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) | run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
{ | { | ||||
return malloc(sizeof (struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO); | return malloc(sizeof (struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
} | } | ||||
static uint8_t | |||||
rate2ridx(struct run_softc *sc, const struct ieee80211_rate_t *rate) | |||||
{ | |||||
switch (rate->type) { | |||||
case IEEE80211_T_HT: | |||||
/* TODO? */ | |||||
break; | |||||
case IEEE80211_T_OFDM: | |||||
switch (rate->value) { | |||||
case 12: return 4; | |||||
case 18: return 5; | |||||
case 24: return 6; | |||||
case 36: return 7; | |||||
case 48: return 8; | |||||
case 72: return 9; | |||||
case 96: return 10; | |||||
case 108: return 11; | |||||
default: | |||||
break; | |||||
} | |||||
case IEEE80211_T_CCK: | |||||
switch (rate->value) { | |||||
case 2: return 0; | |||||
case 4: return 1; | |||||
case 11: return 2; | |||||
case 22: return 3; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
device_printf(sc->sc_dev, "unknown rate %u/%u\n", | |||||
rate->type, rate->value); | |||||
return (0); | |||||
} | |||||
static int | static int | ||||
run_media_change(struct ifnet *ifp) | run_media_change(struct ifnet *ifp) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
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_vht *tp; | ||||
struct run_softc *sc = ic->ic_softc; | struct run_softc *sc = ic->ic_softc; | ||||
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); | ||||
return (error); | return (error); | ||||
} | } | ||||
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_RATE_NONEXISTENT) { | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct run_node *rn; | struct run_node *rn; | ||||
rate = ic->ic_sup_rates[ic->ic_curmode]. | rate = ieee80211_get_rate(tp->ucastrate); | ||||
rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL; | |||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | |||||
if (rt2860_rates[ridx].rate == rate) | |||||
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 = rate2ridx(sc, rate); | ||||
RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, fix_ridx=%d\n", | RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%u/%u, fix_ridx=%d\n", | ||||
rate, rn->fix_ridx); | rate->type, rate->value, 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); | ||||
} | } | ||||
#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_vht *tp; | ||||
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; | ||||
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; | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | if (vap->iv_opmode != IEEE80211_M_MONITOR) { | ||||
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(sc->sc_bssid, ni->ni_bssid); | ||||
run_set_bssid(sc, sc->sc_bssid); | run_set_bssid(sc, sc->sc_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_RATE_NONEXISTENT) | ||||
ratectl |= bid; | ratectl |= bid; | ||||
} else | } else | ||||
run_enable_tsf(sc); | run_enable_tsf(sc); | ||||
/* 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)); | ||||
▲ Show 20 Lines • Show All 479 Lines • ▼ Show 20 Lines | 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) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
struct run_node *rn = RUN_NODE(ni); | struct run_node *rn = RUN_NODE(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_softc; | struct run_softc *sc = ic->ic_softc; | ||||
uint8_t rate; | enum ieee80211_phymode mode; | ||||
uint8_t ridx; | |||||
uint8_t wcid; | uint8_t wcid; | ||||
int i, j; | int i; | ||||
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); | ||||
if (wcid > RT2870_WCID_MAX) { | if (wcid > RT2870_WCID_MAX) { | ||||
device_printf(sc->sc_dev, "wcid=%d out of range\n", wcid); | device_printf(sc->sc_dev, "wcid=%d out of range\n", wcid); | ||||
return; | return; | ||||
} | } | ||||
Show All 14 Lines | if (isnew && ni->ni_associd != 0) { | ||||
ieee80211_runtask(ic, &sc->cmdq_task); | ieee80211_runtask(ic, &sc->cmdq_task); | ||||
} | } | ||||
RUN_DPRINTF(sc, RUN_DEBUG_STATE, | RUN_DPRINTF(sc, RUN_DEBUG_STATE, | ||||
"new assoc isnew=%d associd=%x addr=%s\n", | "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 = ieee80211_get_rate(rs->rates[i].rs_index); | ||||
/* convert 802.11 rate to hardware rate index */ | /* convert 802.11 rate to hardware rate index */ | ||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | rn->ridx[i] = rate2ridx(sc, rate); | ||||
if (rt2860_rates[ridx].rate == rate) | |||||
break; | |||||
rn->ridx[i] = ridx; | |||||
/* determine rate of control response frames */ | |||||
for (j = i; j >= 0; j--) { | |||||
if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && | |||||
rt2860_rates[rn->ridx[i]].phy == | |||||
rt2860_rates[rn->ridx[j]].phy) | |||||
break; | |||||
} | |||||
if (j >= 0) { | |||||
rn->ctl_ridx[i] = rn->ridx[j]; | |||||
} else { | |||||
/* no basic rate found, use mandatory one */ | |||||
rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; | |||||
} | |||||
RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | ||||
"rate=0x%02x ridx=%d ctl_ridx=%d\n", | "rate=%u/0x%02x ridx=%d\n", | ||||
rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]); | rate->type, rate->value, rn->ridx[i]); | ||||
} | } | ||||
rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; | |||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | mode = ieee80211_chan2mode(ic->ic_curchan); | ||||
if (rt2860_rates[ridx].rate == rate) | rate = ieee80211_get_rate(vap->iv_txparms[mode].mgmtrate); | ||||
break; | rn->mgt_ridx = rate2ridx(sc, rate); | ||||
rn->mgt_ridx = ridx; | |||||
RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | ||||
"rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx); | "rate=%u/%u, mgmt_ridx=%d\n", rate->type, rate->value, | ||||
rn->mgt_ridx); | |||||
rate = ieee80211_get_rate(vap->iv_txparms[mode].mcastrate); | |||||
rn->mcast_ridx = rate2ridx(sc, rate); | |||||
RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, | |||||
"rate=%u/%u, mcast_ridx=%d\n", rate->type, rate->value, | |||||
rn->mcast_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); | ||||
} | } | ||||
/* | /* | ||||
* Return the Rx chain with the highest RSSI for a given frame. | * Return the Rx chain with the highest RSSI for a given frame. | ||||
▲ Show 20 Lines • Show All 543 Lines • ▼ Show 20 Lines | |||||
/* 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_ic; | 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; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
struct run_node *rn = RUN_NODE(ni); | struct run_node *rn = RUN_NODE(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; | ||||
uint16_t rate_idx; | |||||
uint16_t qos; | uint16_t qos; | ||||
uint16_t dur; | uint16_t dur; | ||||
uint16_t qid; | uint16_t qid; | ||||
uint8_t type; | uint8_t type; | ||||
uint8_t tid; | uint8_t tid; | ||||
uint8_t ridx; | uint8_t ridx; | ||||
uint8_t ctl_ridx; | |||||
uint8_t qflags; | uint8_t qflags; | ||||
uint8_t xflags = 0; | uint8_t xflags = 0; | ||||
int hasqos; | int hasqos; | ||||
int ismcast; | |||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | |||||
/* | /* | ||||
* There are 7 bulk endpoints: 1 for RX | * There are 7 bulk endpoints: 1 for RX | ||||
* and 6 for TX (4 EDCAs + HCCA + Prio). | * and 6 for TX (4 EDCAs + HCCA + Prio). | ||||
* Update 03-14-2009: some devices like the Planex GW-US300MiniS | * Update 03-14-2009: some devices like the Planex GW-US300MiniS | ||||
* seem to have only 4 TX bulk endpoints (Fukaumi Naoki). | * seem to have only 4 TX bulk endpoints (Fukaumi Naoki). | ||||
*/ | */ | ||||
if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) { | if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) { | ||||
Show All 13 Lines | if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) { | ||||
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; | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "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); | ||||
/* pickup a rate index */ | /* pickup a rate index */ | ||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1) || | if (type != IEEE80211_FC0_TYPE_DATA || | ||||
type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) { | (m->m_flags & M_EAPOL) != 0) { | ||||
ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? | rate_idx = tp->mgmtrate; | ||||
RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; | ridx = rn->mgt_ridx; | ||||
ctl_ridx = rt2860_rates[ridx].ctl_ridx; | } else if (ismcast) { | ||||
} else { | rate_idx = tp->mcastrate; | ||||
if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) | ridx = rn->mcast_ridx; | ||||
} else if (tp->ucastrate != IEEE80211_RATE_NONEXISTENT) { | |||||
rate_idx = tp->ucastrate; | |||||
ridx = rn->fix_ridx; | ridx = rn->fix_ridx; | ||||
else | } else { | ||||
rate_idx = ni->ni_txrate; | |||||
ridx = rn->amrr_ridx; | ridx = rn->amrr_ridx; | ||||
ctl_ridx = rt2860_rates[ridx].ctl_ridx; | |||||
} | } | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | if (!ismcast && | ||||
(!hasqos || (qos & IEEE80211_QOS_ACKPOLICY) != | (!hasqos || (qos & IEEE80211_QOS_ACKPOLICY) != | ||||
IEEE80211_QOS_ACKPOLICY_NOACK)) { | IEEE80211_QOS_ACKPOLICY_NOACK)) { | ||||
xflags |= RT2860_TX_ACK; | xflags |= RT2860_TX_ACK; | ||||
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | dur = ieee80211_ack_duration(ic->ic_rt->ctl_rates, | ||||
dur = rt2860_rates[ctl_ridx].sp_ack_dur; | rate_idx, ic->ic_flags & IEEE80211_F_SHPREAMBLE); | ||||
else | |||||
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) { | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "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; | ||||
txd->flags = qflags; | txd->flags = qflags; | ||||
txwi = (struct rt2860_txwi *)(txd + 1); | txwi = (struct rt2860_txwi *)(txd + 1); | ||||
txwi->xflags = xflags; | txwi->xflags = xflags; | ||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1)) | if (ismcast) | ||||
txwi->wcid = 0; | txwi->wcid = 0; | ||||
else | else | ||||
txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ? | txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ? | ||||
1 : RUN_AID2WCID(ni->ni_associd); | 1 : RUN_AID2WCID(ni->ni_associd); | ||||
/* clear leftover garbage bits */ | /* clear leftover garbage bits */ | ||||
txwi->flags = 0; | txwi->flags = 0; | ||||
txwi->txop = 0; | txwi->txop = 0; | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | ||||
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) | ||||
{ | { | ||||
const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | |||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct run_node *rn = RUN_NODE(ni); | struct run_node *rn = RUN_NODE(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 xflags = 0; | uint8_t xflags = 0; | ||||
uint8_t wflags = 0; | uint8_t wflags = 0; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
/* tell hardware to add timestamp for probe responses */ | /* tell hardware to add timestamp for probe responses */ | ||||
if ((wh->i_fc[0] & | if ((wh->i_fc[0] & | ||||
(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == | (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == | ||||
(IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | ||||
wflags |= RT2860_TX_TS; | wflags |= RT2860_TX_TS; | ||||
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->ctl_rates, | ||||
ic->ic_flags & IEEE80211_F_SHPREAMBLE); | tp->mgmtrate, 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 */ | ||||
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); | ||||
Show All 20 Lines | run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
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); | ||||
} | } | ||||
static int | static int | ||||
run_sendprot(struct run_softc *sc, | run_sendprot(struct run_softc *sc, const struct mbuf *m, | ||||
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) | struct ieee80211_node *ni, int prot, uint16_t rate_idx) | ||||
{ | { | ||||
const struct ieee80211_rate_t *protrate; | |||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
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; | ||||
struct mbuf *mprot; | struct mbuf *mprot; | ||||
int ridx; | uint8_t wflags, xflags; | ||||
int protrate; | |||||
uint8_t wflags = 0; | |||||
uint8_t xflags = 0; | |||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* 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 */ | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
mprot = ieee80211_alloc_prot(ni, m, rate, prot); | mprot = ieee80211_alloc_prot(ni, m, rate_idx, prot); | ||||
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); | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "could not allocate mbuf\n"); | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "could not allocate mbuf\n"); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
protrate = ieee80211_ctl_rate(ic->ic_rt, rate); | protrate = ieee80211_ctl_rate(ic->ic_rt->ctl_rates, rate_idx); | ||||
wflags = RT2860_TX_FRAG; | wflags = RT2860_TX_FRAG; | ||||
xflags = 0; | xflags = 0; | ||||
if (prot == IEEE80211_PROT_RTSCTS) | if (prot == IEEE80211_PROT_RTSCTS) | ||||
xflags |= RT2860_TX_ACK; | xflags |= RT2860_TX_ACK; | ||||
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->flags = wflags; | txwi->flags = wflags; | ||||
txwi->xflags = xflags; | txwi->xflags = xflags; | ||||
txwi->txop = 0; /* clear leftover garbage bits */ | txwi->txop = 0; /* clear leftover garbage bits */ | ||||
data->m = mprot; | data->m = mprot; | ||||
data->ni = ieee80211_ref_node(ni); | data->ni = ieee80211_ref_node(ni); | ||||
data->ridx = rate2ridx(sc, protrate); | |||||
for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) | |||||
if (rt2860_rates[ridx].rate == protrate) | |||||
break; | |||||
data->ridx = ridx; | |||||
run_set_tx_desc(sc, data); | run_set_tx_desc(sc, data); | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending prot len=%u rate=%u\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending prot len=%u rate=%u/%u\n", | ||||
m->m_pkthdr.len, rate); | m->m_pkthdr.len, protrate->type, protrate->value); | ||||
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); | ||||
} | } | ||||
static int | static int | ||||
run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni, | run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni, | ||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
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; | ||||
uint8_t ridx; | |||||
uint8_t rate; | |||||
uint8_t opflags = 0; | uint8_t opflags = 0; | ||||
uint8_t xflags = 0; | uint8_t xflags = 0; | ||||
int error; | int error; | ||||
RUN_LOCK_ASSERT(sc, MA_OWNED); | RUN_LOCK_ASSERT(sc, MA_OWNED); | ||||
KASSERT(params != NULL, ("no raw xmit params")); | KASSERT(params != NULL, ("no raw xmit params")); | ||||
rate = params->ibp_rate0; | rate = ieee80211_get_rate_safe(params->ibp_rate0); | ||||
if (!ieee80211_isratevalid(ic->ic_rt, rate)) { | if (!rate || !ieee80211_isratevalid(ic->ic_rt, rate)) { | ||||
/* let caller free mbuf */ | /* let caller free mbuf */ | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) | if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) | ||||
xflags |= RT2860_TX_ACK; | xflags |= RT2860_TX_ACK; | ||||
if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { | if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { | ||||
error = run_sendprot(sc, m, ni, | error = run_sendprot(sc, m, ni, | ||||
params->ibp_flags & IEEE80211_BPF_RTS ? | params->ibp_flags & IEEE80211_BPF_RTS ? | ||||
IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, | IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, | ||||
rate); | params->ibp_rate0); | ||||
if (error) { | 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 */ | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | ||||
"sending raw frame, but tx ring is full\n"); | "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++) | data->ridx = rate2ridx(sc, rate); | ||||
if (rt2860_rates[ridx].rate == rate) | |||||
break; | |||||
data->ridx = ridx; | |||||
run_set_tx_desc(sc, data); | run_set_tx_desc(sc, data); | ||||
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "sending raw frame len=%u rate=%u\n", | RUN_DPRINTF(sc, RUN_DEBUG_XMIT, | ||||
m->m_pkthdr.len, rate); | "sending raw frame len=%u rate=%u/%u\n", | ||||
m->m_pkthdr.len, rate->type, rate->value); | |||||
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); | ||||
} | } | ||||
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 run_softc *sc = ni->ni_ic->ic_softc; | struct run_softc *sc = ni->ni_ic->ic_softc; | ||||
int error = 0; | int error = 0; | ||||
▲ Show 20 Lines • Show All 2,622 Lines • Show Last 20 Lines |