Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_ural.c
Show First 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | static struct ieee80211vap *ural_vap_create(struct ieee80211com *, | ||||
const uint8_t [IEEE80211_ADDR_LEN]); | const uint8_t [IEEE80211_ADDR_LEN]); | ||||
static void ural_vap_delete(struct ieee80211vap *); | static void ural_vap_delete(struct ieee80211vap *); | ||||
static void ural_tx_free(struct ural_tx_data *, int); | static void ural_tx_free(struct ural_tx_data *, int); | ||||
static void ural_setup_tx_list(struct ural_softc *); | static void ural_setup_tx_list(struct ural_softc *); | ||||
static void ural_unsetup_tx_list(struct ural_softc *); | static void ural_unsetup_tx_list(struct ural_softc *); | ||||
static int ural_newstate(struct ieee80211vap *, | static int ural_newstate(struct ieee80211vap *, | ||||
enum ieee80211_state, int); | enum ieee80211_state, int); | ||||
static void ural_setup_tx_desc(struct ural_softc *, | static void ural_setup_tx_desc(struct ural_softc *, | ||||
struct ural_tx_desc *, uint32_t, int, int); | struct ural_tx_desc *, uint32_t, int, | ||||
const struct ieee80211_rate_t *); | |||||
static int ural_tx_bcn(struct ural_softc *, struct mbuf *, | static int ural_tx_bcn(struct ural_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int ural_tx_mgt(struct ural_softc *, struct mbuf *, | static int ural_tx_mgt(struct ural_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int ural_tx_data(struct ural_softc *, struct mbuf *, | static int ural_tx_data(struct ural_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int ural_transmit(struct ieee80211com *, struct mbuf *); | static int ural_transmit(struct ieee80211com *, struct mbuf *); | ||||
static void ural_start(struct ural_softc *); | static void ural_start(struct ural_softc *); | ||||
▲ Show 20 Lines • Show All 520 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
{ | { | ||||
struct ural_vap *uvp = URAL_VAP(vap); | struct ural_vap *uvp = URAL_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ural_softc *sc = ic->ic_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam_vht *tp; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
DPRINTF("%s -> %s\n", | DPRINTF("%s -> %s\n", | ||||
ieee80211_state_name[vap->iv_state], | ieee80211_state_name[vap->iv_state], | ||||
ieee80211_state_name[nstate]); | ieee80211_state_name[nstate]); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | case IEEE80211_S_RUN: | ||||
if (vap->iv_opmode != IEEE80211_M_MONITOR) | if (vap->iv_opmode != IEEE80211_M_MONITOR) | ||||
ural_enable_tsf_sync(sc); | ural_enable_tsf_sync(sc); | ||||
else | else | ||||
ural_enable_tsf(sc); | ural_enable_tsf(sc); | ||||
/* enable automatic rate adaptation */ | /* enable automatic rate adaptation */ | ||||
/* XXX should use ic_bsschan but not valid until after newstate call below */ | /* XXX should use ic_bsschan but not valid until after newstate call below */ | ||||
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) | ||||
ural_ratectl_start(sc, ni); | ural_ratectl_start(sc, ni); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | ural_plcp_signal(int rate) | ||||
case 11: return 0x2; | case 11: return 0x2; | ||||
case 22: return 0x3; | case 22: return 0x3; | ||||
} | } | ||||
return 0xff; /* XXX unsupported/unknown rate */ | return 0xff; /* XXX unsupported/unknown rate */ | ||||
} | } | ||||
static void | static void | ||||
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, | ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, | ||||
uint32_t flags, int len, int rate) | uint32_t flags, int len, const struct ieee80211_rate_t *rate) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
uint16_t plcp_length; | uint16_t plcp_length; | ||||
int remainder; | int remainder; | ||||
desc->flags = htole32(flags); | desc->flags = htole32(flags); | ||||
desc->flags |= htole32(RAL_TX_NEWSEQ); | desc->flags |= htole32(RAL_TX_NEWSEQ); | ||||
desc->flags |= htole32(len << 16); | desc->flags |= htole32(len << 16); | ||||
desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); | desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); | ||||
desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); | desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); | ||||
/* setup PLCP fields */ | /* setup PLCP fields */ | ||||
desc->plcp_signal = ural_plcp_signal(rate); | desc->plcp_signal = ural_plcp_signal(rate->value); | ||||
desc->plcp_service = 4; | desc->plcp_service = 4; | ||||
len += IEEE80211_CRC_LEN; | len += IEEE80211_CRC_LEN; | ||||
if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) { | if (rate->type == IEEE80211_T_OFDM) { | ||||
desc->flags |= htole32(RAL_TX_OFDM); | desc->flags |= htole32(RAL_TX_OFDM); | ||||
plcp_length = len & 0xfff; | plcp_length = len & 0xfff; | ||||
desc->plcp_length_hi = plcp_length >> 6; | desc->plcp_length_hi = plcp_length >> 6; | ||||
desc->plcp_length_lo = plcp_length & 0x3f; | desc->plcp_length_lo = plcp_length & 0x3f; | ||||
} else { | } else { | ||||
if (rate == 0) | KASSERT(rate->type == IEEE80211_T_CCK, | ||||
rate = 2; /* avoid division by zero */ | ("unknown rate type %u\n", rate->type)); | ||||
plcp_length = howmany(16 * len, rate); | |||||
if (rate == 22) { | plcp_length = howmany(16 * len, rate->value); | ||||
if (rate->value == 22) { | |||||
remainder = (16 * len) % 22; | remainder = (16 * len) % 22; | ||||
if (remainder != 0 && remainder < 7) | if (remainder != 0 && remainder < 7) | ||||
desc->plcp_service |= RAL_PLCP_LENGEXT; | desc->plcp_service |= RAL_PLCP_LENGEXT; | ||||
} | } | ||||
desc->plcp_length_hi = plcp_length >> 8; | desc->plcp_length_hi = plcp_length >> 8; | ||||
desc->plcp_length_lo = plcp_length & 0xff; | desc->plcp_length_lo = plcp_length & 0xff; | ||||
if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | if (rate->props.cck.short_preamble && | ||||
(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | |||||
desc->plcp_signal |= 0x08; | desc->plcp_signal |= 0x08; | ||||
} | } | ||||
desc->iv = 0; | desc->iv = 0; | ||||
desc->eiv = 0; | desc->eiv = 0; | ||||
} | } | ||||
#define RAL_TX_TIMEOUT 5000 | #define RAL_TX_TIMEOUT 5000 | ||||
static int | static int | ||||
ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam_vht *tp; | ||||
struct ural_tx_data *data; | struct ural_tx_data *data; | ||||
if (sc->tx_nfree == 0) { | if (sc->tx_nfree == 0) { | ||||
m_freem(m0); | m_freem(m0); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return (EIO); | return (EIO); | ||||
} | } | ||||
if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) { | if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) { | ||||
m_freem(m0); | m_freem(m0); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; | tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; | ||||
rate = ieee80211_get_rate(tp->mgmtrate); | |||||
data->m = m0; | data->m = m0; | ||||
data->ni = ni; | data->ni = ni; | ||||
data->rate = tp->mgmtrate; | data->rate = rate->value; | ||||
ural_setup_tx_desc(sc, &data->desc, | ural_setup_tx_desc(sc, &data->desc, | ||||
RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, m0->m_pkthdr.len, | RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, m0->m_pkthdr.len, rate); | ||||
tp->mgmtrate); | |||||
DPRINTFN(10, "sending beacon frame len=%u rate=%u\n", | DPRINTFN(10, "sending beacon frame len=%u rate=%u/%u\n", | ||||
m0->m_pkthdr.len, tp->mgmtrate); | m0->m_pkthdr.len, rate->type, rate->value); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
const struct ieee80211_rate_t *rate; | |||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ural_tx_data *data; | struct ural_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
uint32_t flags; | uint32_t flags; | ||||
uint16_t dur; | uint16_t dur; | ||||
RAL_LOCK_ASSERT(sc, MA_OWNED); | RAL_LOCK_ASSERT(sc, MA_OWNED); | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | ||||
k = ieee80211_crypto_encap(ni, m0); | k = ieee80211_crypto_encap(ni, m0); | ||||
if (k == NULL) { | if (k == NULL) { | ||||
m_freem(m0); | m_freem(m0); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
} | } | ||||
rate = ieee80211_get_rate(tp->mgmtrate); | |||||
data->m = m0; | data->m = m0; | ||||
data->ni = ni; | data->ni = ni; | ||||
data->rate = tp->mgmtrate; | data->rate = rate->value; | ||||
flags = 0; | flags = 0; | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | ||||
flags |= RAL_TX_ACK; | flags |= RAL_TX_ACK; | ||||
dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate, | 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); | ||||
/* tell hardware to add timestamp for probe responses */ | /* tell hardware to add timestamp for probe responses */ | ||||
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == | if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == | ||||
IEEE80211_FC0_TYPE_MGT && | IEEE80211_FC0_TYPE_MGT && | ||||
(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == | (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == | ||||
IEEE80211_FC0_SUBTYPE_PROBE_RESP) | IEEE80211_FC0_SUBTYPE_PROBE_RESP) | ||||
flags |= RAL_TX_TIMESTAMP; | flags |= RAL_TX_TIMESTAMP; | ||||
} | } | ||||
ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, tp->mgmtrate); | ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); | ||||
DPRINTFN(10, "sending mgt frame len=%u rate=%u\n", | DPRINTFN(10, "sending mgt frame len=%u rate=%u/%u\n", | ||||
m0->m_pkthdr.len, tp->mgmtrate); | m0->m_pkthdr.len, rate->type, rate->value); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
ural_sendprot(struct ural_softc *sc, | ural_sendprot(struct ural_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 ural_tx_data *data; | struct ural_tx_data *data; | ||||
struct mbuf *mprot; | struct mbuf *mprot; | ||||
int protrate, flags; | int flags; | ||||
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); | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"could not allocate mbuf for protection mode %d\n", prot); | "could not allocate mbuf for protection mode %d\n", prot); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
protrate = ieee80211_ctl_rate(ic->ic_rt, rate); | protrate = ieee80211_ctl_rate(ic->ic_rt->ctl_rates, rate_idx); | ||||
flags = RAL_TX_RETRY(7); | flags = RAL_TX_RETRY(7); | ||||
if (prot == IEEE80211_PROT_RTSCTS) | if (prot == IEEE80211_PROT_RTSCTS) | ||||
flags |= RAL_TX_ACK; | flags |= RAL_TX_ACK; | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
data->m = mprot; | data->m = mprot; | ||||
data->ni = ieee80211_ref_node(ni); | data->ni = ieee80211_ref_node(ni); | ||||
data->rate = protrate; | data->rate = protrate->value; | ||||
ural_setup_tx_desc(sc, &data->desc, flags, mprot->m_pkthdr.len, protrate); | ural_setup_tx_desc(sc, &data->desc, flags, mprot->m_pkthdr.len, protrate); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, | ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, 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 ural_tx_data *data; | struct ural_tx_data *data; | ||||
uint32_t flags; | uint32_t flags; | ||||
int error; | int error; | ||||
int rate; | |||||
RAL_LOCK_ASSERT(sc, MA_OWNED); | RAL_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)) { | ||||
m_freem(m0); | m_freem(m0); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
flags = 0; | flags = 0; | ||||
if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) | if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) | ||||
flags |= RAL_TX_ACK; | flags |= RAL_TX_ACK; | ||||
if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { | if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { | ||||
error = ural_sendprot(sc, m0, ni, | error = ural_sendprot(sc, m0, 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 || sc->tx_nfree == 0) { | if (error || sc->tx_nfree == 0) { | ||||
m_freem(m0); | m_freem(m0); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
flags |= RAL_TX_IFS_SIFS; | flags |= RAL_TX_IFS_SIFS; | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
data->m = m0; | data->m = m0; | ||||
data->ni = ni; | data->ni = ni; | ||||
data->rate = rate; | data->rate = rate->value; | ||||
/* XXX need to setup descriptor ourself */ | /* XXX need to setup descriptor ourself */ | ||||
ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); | ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); | ||||
DPRINTFN(10, "sending raw frame len=%u rate=%u\n", | DPRINTFN(10, "sending raw frame len=%u rate=%u/%u\n", | ||||
m0->m_pkthdr.len, rate); | m0->m_pkthdr.len, rate->type, rate->value); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ural_tx_data *data; | struct ural_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | |||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
uint32_t flags = 0; | uint32_t flags = 0; | ||||
uint16_t dur; | uint16_t dur, rate_idx; | ||||
int error, rate; | int ismcast, error; | ||||
RAL_LOCK_ASSERT(sc, MA_OWNED); | RAL_LOCK_ASSERT(sc, MA_OWNED); | ||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | |||||
if (m0->m_flags & M_EAPOL) | if (m0->m_flags & M_EAPOL) | ||||
rate = tp->mgmtrate; | rate_idx = tp->mgmtrate; | ||||
else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) | else if (ismcast) | ||||
rate = tp->mcastrate; | rate_idx = tp->mcastrate; | ||||
else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) | else if (tp->ucastrate != IEEE80211_RATE_NONEXISTENT) | ||||
rate = tp->ucastrate; | rate_idx = tp->ucastrate; | ||||
else { | else { | ||||
(void) ieee80211_ratectl_rate(ni, NULL, 0); | (void) ieee80211_ratectl_rate(ni, NULL, 0); | ||||
rate = ni->ni_txrate; | rate_idx = ni->ni_txrate; | ||||
} | } | ||||
rate = ieee80211_get_rate(rate_idx); | |||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | ||||
k = ieee80211_crypto_encap(ni, m0); | k = ieee80211_crypto_encap(ni, m0); | ||||
if (k == NULL) { | if (k == NULL) { | ||||
m_freem(m0); | m_freem(m0); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
/* packet header may have moved, reset our local pointer */ | /* packet header may have moved, reset our local pointer */ | ||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
} | } | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | if (!ismcast) { | ||||
int prot = IEEE80211_PROT_NONE; | int prot = IEEE80211_PROT_NONE; | ||||
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) | if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) | ||||
prot = IEEE80211_PROT_RTSCTS; | prot = IEEE80211_PROT_RTSCTS; | ||||
else if ((ic->ic_flags & IEEE80211_F_USEPROT) && | else if ((ic->ic_flags & IEEE80211_F_USEPROT) && | ||||
ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) | rate->type == IEEE80211_T_OFDM) | ||||
prot = ic->ic_protmode; | prot = ic->ic_protmode; | ||||
if (prot != IEEE80211_PROT_NONE) { | if (prot != IEEE80211_PROT_NONE) { | ||||
error = ural_sendprot(sc, m0, ni, prot, rate); | error = ural_sendprot(sc, m0, ni, prot, rate_idx); | ||||
if (error || sc->tx_nfree == 0) { | if (error || sc->tx_nfree == 0) { | ||||
m_freem(m0); | m_freem(m0); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
flags |= RAL_TX_IFS_SIFS; | flags |= RAL_TX_IFS_SIFS; | ||||
} | } | ||||
} | } | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
data->m = m0; | data->m = m0; | ||||
data->ni = ni; | data->ni = ni; | ||||
data->rate = rate; | data->rate = rate->value; | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { | if (!ismcast) { | ||||
flags |= RAL_TX_ACK; | flags |= RAL_TX_ACK; | ||||
flags |= RAL_TX_RETRY(7); | flags |= RAL_TX_RETRY(7); | ||||
dur = ieee80211_ack_duration(ic->ic_rt, rate, | dur = ieee80211_ack_duration(ic->ic_rt->ctl_rates, | ||||
ic->ic_flags & IEEE80211_F_SHPREAMBLE); | rate_idx, ic->ic_flags & IEEE80211_F_SHPREAMBLE); | ||||
USETW(wh->i_dur, dur); | USETW(wh->i_dur, dur); | ||||
} | } | ||||
ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); | ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); | ||||
DPRINTFN(10, "sending data frame len=%u rate=%u\n", | DPRINTFN(10, "sending data frame len=%u rate=%u/%u\n", | ||||
m0->m_pkthdr.len, rate); | m0->m_pkthdr.len, rate->type, rate->value); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 927 Lines • Show Last 20 Lines |