Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iwn/if_iwn.c
Show First 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | |||||
static void iwn5000_rx_calib_results(struct iwn_softc *, | static void iwn5000_rx_calib_results(struct iwn_softc *, | ||||
struct iwn_rx_desc *, struct iwn_rx_data *); | struct iwn_rx_desc *, struct iwn_rx_data *); | ||||
static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *, | static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *, | ||||
struct iwn_rx_data *); | struct iwn_rx_data *); | ||||
static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *, | static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *, | ||||
struct iwn_rx_data *); | struct iwn_rx_data *); | ||||
static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, | static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, | ||||
struct iwn_rx_data *); | struct iwn_rx_data *); | ||||
static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, | static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, int, | ||||
uint8_t); | uint8_t); | ||||
static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *); | static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, int, | ||||
void *); | |||||
static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); | static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); | ||||
static void iwn_notif_intr(struct iwn_softc *); | static void iwn_notif_intr(struct iwn_softc *); | ||||
static void iwn_wakeup_intr(struct iwn_softc *); | static void iwn_wakeup_intr(struct iwn_softc *); | ||||
static void iwn_rftoggle_intr(struct iwn_softc *); | static void iwn_rftoggle_intr(struct iwn_softc *); | ||||
static void iwn_fatal_intr(struct iwn_softc *); | static void iwn_fatal_intr(struct iwn_softc *); | ||||
static void iwn_intr(void *); | static void iwn_intr(void *); | ||||
static void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t, | static void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t, | ||||
uint16_t); | uint16_t); | ||||
▲ Show 20 Lines • Show All 2,918 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* Process an incoming Compressed BlockAck. */ | /* Process an incoming Compressed BlockAck. */ | ||||
static void | static void | ||||
iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, | iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, | ||||
struct iwn_rx_data *data) | struct iwn_rx_data *data) | ||||
{ | { | ||||
struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; | |||||
struct iwn_ops *ops = &sc->ops; | struct iwn_ops *ops = &sc->ops; | ||||
struct iwn_node *wn; | struct iwn_node *wn; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1); | struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1); | ||||
struct iwn_tx_ring *txq; | struct iwn_tx_ring *txq; | ||||
struct iwn_tx_data *txdata; | struct iwn_tx_data *txdata; | ||||
struct ieee80211_tx_ampdu *tap; | struct ieee80211_tx_ampdu *tap; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
uint64_t bitmap; | uint64_t bitmap; | ||||
uint16_t ssn; | uint16_t ssn; | ||||
uint8_t tid; | uint8_t tid; | ||||
int ackfailcnt = 0, i, lastidx, qid, *res, shift; | int i, lastidx, qid, *res, shift; | ||||
int tx_ok = 0, tx_err = 0; | int tx_ok = 0, tx_err = 0; | ||||
DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); | DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); | ||||
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); | bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); | ||||
qid = le16toh(ba->qid); | qid = le16toh(ba->qid); | ||||
txq = &sc->txq[ba->qid]; | txq = &sc->txq[ba->qid]; | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, | ||||
* attempts are made. | * attempts are made. | ||||
* | * | ||||
* Yes, the rate control code doesn't know these are A-MPDU | * Yes, the rate control code doesn't know these are A-MPDU | ||||
* subframes and that it's okay to fail some of these. | * subframes and that it's okay to fail some of these. | ||||
*/ | */ | ||||
ni = tap->txa_ni; | ni = tap->txa_ni; | ||||
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap; | bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap; | ||||
for (i = 0; bitmap; i++) { | for (i = 0; bitmap; i++) { | ||||
txs->flags = 0; /* XXX TODO */ | |||||
if ((bitmap & 1) == 0) { | if ((bitmap & 1) == 0) { | ||||
tx_err ++; | tx_err ++; | ||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni, | txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; | ||||
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); | |||||
} else { | } else { | ||||
tx_ok ++; | tx_ok ++; | ||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni, | txs->status = IEEE80211_RATECTL_TX_SUCCESS; | ||||
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); | |||||
} | } | ||||
ieee80211_ratectl_tx_complete(ni, txs); | |||||
bitmap >>= 1; | bitmap >>= 1; | ||||
} | } | ||||
DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, | DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, | ||||
"->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err); | "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | DPRINTF(sc, IWN_DEBUG_XMIT, "%s: " | ||||
stat->ackfailcnt, | stat->ackfailcnt, | ||||
stat->btkillcnt, | stat->btkillcnt, | ||||
stat->rate, le16toh(stat->duration), | stat->rate, le16toh(stat->duration), | ||||
le32toh(stat->status)); | le32toh(stat->status)); | ||||
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); | bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); | ||||
if (qid >= sc->firstaggqueue) { | if (qid >= sc->firstaggqueue) { | ||||
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, | iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, | ||||
stat->ackfailcnt, &stat->status); | stat->rtsfailcnt, stat->ackfailcnt, &stat->status); | ||||
} else { | } else { | ||||
iwn_tx_done(sc, desc, stat->ackfailcnt, | iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, | ||||
le32toh(stat->status) & 0xff); | le32toh(stat->status) & 0xff); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, | iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, | ||||
struct iwn_rx_data *data) | struct iwn_rx_data *data) | ||||
{ | { | ||||
Show All 16 Lines | |||||
#ifdef notyet | #ifdef notyet | ||||
/* Reset TX scheduler slot. */ | /* Reset TX scheduler slot. */ | ||||
iwn5000_reset_sched(sc, desc->qid & 0xf, desc->idx); | iwn5000_reset_sched(sc, desc->qid & 0xf, desc->idx); | ||||
#endif | #endif | ||||
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); | bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); | ||||
if (qid >= sc->firstaggqueue) { | if (qid >= sc->firstaggqueue) { | ||||
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, | iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, | ||||
stat->ackfailcnt, &stat->status); | stat->rtsfailcnt, stat->ackfailcnt, &stat->status); | ||||
} else { | } else { | ||||
iwn_tx_done(sc, desc, stat->ackfailcnt, | iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, | ||||
le16toh(stat->status) & 0xff); | le16toh(stat->status) & 0xff); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Adapter-independent backend for TX_DONE firmware notifications. | * Adapter-independent backend for TX_DONE firmware notifications. | ||||
*/ | */ | ||||
static void | static void | ||||
iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, | iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, | ||||
uint8_t status) | int ackfailcnt, uint8_t status) | ||||
{ | { | ||||
struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; | |||||
struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; | struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; | ||||
struct iwn_tx_data *data = &ring->data[desc->idx]; | struct iwn_tx_data *data = &ring->data[desc->idx]; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct ieee80211vap *vap; | |||||
KASSERT(data->ni != NULL, ("no node")); | KASSERT(data->ni != NULL, ("no node")); | ||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); | DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); | ||||
/* Unmap and free mbuf. */ | /* Unmap and free mbuf. */ | ||||
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); | bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); | ||||
bus_dmamap_unload(ring->data_dmat, data->map); | bus_dmamap_unload(ring->data_dmat, data->map); | ||||
m = data->m, data->m = NULL; | m = data->m, data->m = NULL; | ||||
ni = data->ni, data->ni = NULL; | ni = data->ni, data->ni = NULL; | ||||
vap = ni->ni_vap; | |||||
/* | /* | ||||
* Update rate control statistics for the node. | * Update rate control statistics for the node. | ||||
*/ | */ | ||||
if (status & IWN_TX_FAIL) | txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | | ||||
ieee80211_ratectl_tx_complete(vap, ni, | IEEE80211_RATECTL_STATUS_LONG_RETRY; | ||||
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); | txs->short_retries = rtsfailcnt; | ||||
else | txs->long_retries = ackfailcnt; | ||||
ieee80211_ratectl_tx_complete(vap, ni, | if (!(status & IWN_TX_FAIL)) | ||||
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); | txs->status = IEEE80211_RATECTL_TX_SUCCESS; | ||||
else { | |||||
switch (status) { | |||||
case IWN_TX_FAIL_SHORT_LIMIT: | |||||
txs->status = IEEE80211_RATECTL_TX_FAIL_SHORT; | |||||
break; | |||||
case IWN_TX_FAIL_LONG_LIMIT: | |||||
txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; | |||||
break; | |||||
case IWN_TX_STATUS_FAIL_LIFE_EXPIRE: | |||||
txs->status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; | |||||
break; | |||||
default: | |||||
txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; | |||||
break; | |||||
} | |||||
} | |||||
ieee80211_ratectl_tx_complete(ni, txs); | |||||
/* | /* | ||||
* Channels marked for "radar" require traffic to be received | * Channels marked for "radar" require traffic to be received | ||||
* to unlock before we can transmit. Until traffic is seen | * to unlock before we can transmit. Until traffic is seen | ||||
* any attempt to transmit is returned immediately with status | * any attempt to transmit is returned immediately with status | ||||
* set to IWN_TX_FAIL_TX_LOCKED. Unfortunately this can easily | * set to IWN_TX_FAIL_TX_LOCKED. Unfortunately this can easily | ||||
* happen on first authenticate after scanning. To workaround | * happen on first authenticate after scanning. To workaround | ||||
* this we ignore a failure of this sort in AUTH state so the | * this we ignore a failure of this sort in AUTH state so the | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (data->m != NULL) { | ||||
m_freem(data->m); | m_freem(data->m); | ||||
data->m = NULL; | data->m = NULL; | ||||
} | } | ||||
wakeup(&ring->desc[desc->idx]); | wakeup(&ring->desc[desc->idx]); | ||||
} | } | ||||
static void | static void | ||||
iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, | iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, | ||||
int ackfailcnt, void *stat) | int rtsfailcnt, int ackfailcnt, void *stat) | ||||
{ | { | ||||
struct iwn_ops *ops = &sc->ops; | struct iwn_ops *ops = &sc->ops; | ||||
struct iwn_tx_ring *ring = &sc->txq[qid]; | struct iwn_tx_ring *ring = &sc->txq[qid]; | ||||
struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; | |||||
struct iwn_tx_data *data; | struct iwn_tx_data *data; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct iwn_node *wn; | struct iwn_node *wn; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct ieee80211_tx_ampdu *tap; | struct ieee80211_tx_ampdu *tap; | ||||
uint64_t bitmap; | uint64_t bitmap; | ||||
uint32_t *status = stat; | uint32_t *status = stat; | ||||
uint16_t *aggstatus = stat; | uint16_t *aggstatus = stat; | ||||
Show All 22 Lines | iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, | ||||
* A-MPDU single frame status - if we failed to transmit it | * A-MPDU single frame status - if we failed to transmit it | ||||
* in A-MPDU, then it may be a permanent failure. | * in A-MPDU, then it may be a permanent failure. | ||||
* | * | ||||
* XXX TODO: check what the Linux iwlwifi driver does here; | * XXX TODO: check what the Linux iwlwifi driver does here; | ||||
* there's some permanent and temporary failures that may be | * there's some permanent and temporary failures that may be | ||||
* handled differently. | * handled differently. | ||||
*/ | */ | ||||
if (nframes == 1) { | if (nframes == 1) { | ||||
txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | | |||||
IEEE80211_RATECTL_STATUS_LONG_RETRY; | |||||
txs->short_retries = rtsfailcnt; | |||||
txs->long_retries = ackfailcnt; | |||||
if ((*status & 0xff) != 1 && (*status & 0xff) != 2) { | if ((*status & 0xff) != 1 && (*status & 0xff) != 2) { | ||||
#ifdef NOT_YET | #ifdef NOT_YET | ||||
printf("ieee80211_send_bar()\n"); | printf("ieee80211_send_bar()\n"); | ||||
#endif | #endif | ||||
/* | /* | ||||
* If we completely fail a transmit, make sure a | * If we completely fail a transmit, make sure a | ||||
* notification is pushed up to the rate control | * notification is pushed up to the rate control | ||||
* layer. | * layer. | ||||
*/ | */ | ||||
ieee80211_ratectl_tx_complete(ni->ni_vap, | /* XXX */ | ||||
ni, | txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; | ||||
IEEE80211_RATECTL_TX_FAILURE, | |||||
&ackfailcnt, | |||||
NULL); | |||||
} else { | } else { | ||||
/* | /* | ||||
* If nframes=1, then we won't be getting a BA for | * If nframes=1, then we won't be getting a BA for | ||||
* this frame. Ensure that we correctly update the | * this frame. Ensure that we correctly update the | ||||
* rate control code with how many retries were | * rate control code with how many retries were | ||||
* needed to send it. | * needed to send it. | ||||
*/ | */ | ||||
ieee80211_ratectl_tx_complete(ni->ni_vap, | txs->status = IEEE80211_RATECTL_TX_SUCCESS; | ||||
ni, | |||||
IEEE80211_RATECTL_TX_SUCCESS, | |||||
&ackfailcnt, | |||||
NULL); | |||||
} | } | ||||
ieee80211_ratectl_tx_complete(ni, txs); | |||||
} | } | ||||
bitmap = 0; | bitmap = 0; | ||||
start = idx; | start = idx; | ||||
for (i = 0; i < nframes; i++) { | for (i = 0; i < nframes; i++) { | ||||
if (le16toh(aggstatus[i * 2]) & 0xc) | if (le16toh(aggstatus[i * 2]) & 0xc) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 5,286 Lines • Show Last 20 Lines |