mirror of https://github.com/proski/madwifi
Audit of node referencing:
* Enhance readability of some functions WRT node referencing by putting blocks around areas where node references are held * Various bits of consistency of the usage of node references; always unreference them at the point at which they are no longer used. Don't reuse variables implicitly. * Significant overhaul of the usage of bf_node and ieee80211_cb.ni. Always hold a reference with aforementioned variable and always unreference it properly. git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@2839 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
parent
be343965ed
commit
c6eac77db1
247
ath/if_ath.c
247
ath/if_ath.c
|
@ -2413,8 +2413,8 @@ ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb)
|
||||||
HAL_PKT_TYPE atype;
|
HAL_PKT_TYPE atype;
|
||||||
u_int flags;
|
u_int flags;
|
||||||
u_int8_t antenna, txrate;
|
u_int8_t antenna, txrate;
|
||||||
struct ath_txq *txq=NULL;
|
struct ath_txq *txq = NULL;
|
||||||
struct ath_desc *ds=NULL;
|
struct ath_desc *ds = NULL;
|
||||||
struct ieee80211_frame *wh;
|
struct ieee80211_frame *wh;
|
||||||
|
|
||||||
wh = (struct ieee80211_frame *) skb->data;
|
wh = (struct ieee80211_frame *) skb->data;
|
||||||
|
@ -2432,9 +2432,8 @@ ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb)
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: skb %p [data %p len %u] skbaddr %llx\n",
|
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: skb %p [data %p len %u] skbaddr %llx\n",
|
||||||
__func__, skb, skb->data, skb->len, ito64(bf->bf_skbaddr));
|
__func__, skb, skb->data, skb->len, ito64(bf->bf_skbaddr));
|
||||||
|
|
||||||
|
|
||||||
bf->bf_skb = skb;
|
bf->bf_skb = skb;
|
||||||
bf->bf_node = NULL;
|
KASSERT((bf->bf_node == NULL), ("Detected node reference leak"));
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
bf->bf_numdescff = 0;
|
bf->bf_numdescff = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2444,7 +2443,6 @@ ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb)
|
||||||
rt = sc->sc_currates;
|
rt = sc->sc_currates;
|
||||||
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
|
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
|
||||||
|
|
||||||
|
|
||||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
|
if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
|
||||||
flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
|
flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
|
||||||
sc->sc_stats.ast_tx_noack++;
|
sc->sc_stats.ast_tx_noack++;
|
||||||
|
@ -2532,7 +2530,6 @@ ath_ffstageq_flush(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
int (*ath_ff_flushdonetest)(struct ath_txq *txq, struct ath_buf *bf))
|
int (*ath_ff_flushdonetest)(struct ath_txq *txq, struct ath_buf *bf))
|
||||||
{
|
{
|
||||||
struct ath_buf *bf_ff = NULL;
|
struct ath_buf *bf_ff = NULL;
|
||||||
struct ieee80211_node *ni = NULL;
|
|
||||||
unsigned int pktlen;
|
unsigned int pktlen;
|
||||||
int framecnt;
|
int framecnt;
|
||||||
|
|
||||||
|
@ -2545,16 +2542,15 @@ ath_ffstageq_flush(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = bf_ff->bf_node;
|
KASSERT(ATH_NODE(bf_ff->bf_node)->an_tx_ffbuf[bf_ff->bf_skb->priority],
|
||||||
KASSERT(ATH_NODE(ni)->an_tx_ffbuf[bf_ff->bf_skb->priority],
|
|
||||||
("no bf_ff on staging queue %p", bf_ff));
|
("no bf_ff on staging queue %p", bf_ff));
|
||||||
ATH_NODE(ni)->an_tx_ffbuf[bf_ff->bf_skb->priority] = NULL;
|
ATH_NODE(bf_ff->bf_node)->an_tx_ffbuf[bf_ff->bf_skb->priority] = NULL;
|
||||||
TAILQ_REMOVE(&txq->axq_stageq, bf_ff, bf_stagelist);
|
TAILQ_REMOVE(&txq->axq_stageq, bf_ff, bf_stagelist);
|
||||||
|
|
||||||
ATH_TXQ_UNLOCK_IRQ(txq);
|
ATH_TXQ_UNLOCK_IRQ(txq);
|
||||||
|
|
||||||
/* encap and xmit */
|
/* encap and xmit */
|
||||||
bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
|
bf_ff->bf_skb = ieee80211_encap(bf_ff->bf_node, bf_ff->bf_skb, &framecnt);
|
||||||
if (bf_ff->bf_skb == NULL) {
|
if (bf_ff->bf_skb == NULL) {
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
|
DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
|
||||||
"%s: discard, encapsulation failure\n", __func__);
|
"%s: discard, encapsulation failure\n", __func__);
|
||||||
|
@ -2562,15 +2558,17 @@ ath_ffstageq_flush(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
pktlen = bf_ff->bf_skb->len; /* NB: don't reference skb below */
|
pktlen = bf_ff->bf_skb->len; /* NB: don't reference skb below */
|
||||||
if (ath_tx_start(sc->sc_dev, ni, bf_ff, bf_ff->bf_skb, 0) == 0)
|
if (ath_tx_start(sc->sc_dev, bf_ff->bf_node, bf_ff, bf_ff->bf_skb, 0) == 0)
|
||||||
continue;
|
continue;
|
||||||
bad:
|
bad:
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
if (bf_ff->bf_skb != NULL) {
|
if (bf_ff->bf_skb != NULL) {
|
||||||
|
struct ieee80211_cb *cb = (struct ieee80211_cb *)bf_ff->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf_ff->bf_skb);
|
dev_kfree_skb(bf_ff->bf_skb);
|
||||||
bf_ff->bf_skb = NULL;
|
bf_ff->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
bf_ff->bf_node = NULL;
|
ieee80211_unref_node(&bf_ff->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
|
||||||
|
@ -2615,7 +2613,7 @@ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
|
||||||
struct ath_softc *sc = dev->priv;
|
struct ath_softc *sc = dev->priv;
|
||||||
struct ieee80211_node *ni = NULL;
|
struct ieee80211_node *ni = NULL;
|
||||||
struct ath_buf *bf = NULL;
|
struct ath_buf *bf = NULL;
|
||||||
struct ieee80211_cb *cb = (struct ieee80211_cb *) skb->cb;
|
struct ieee80211_cb *cb = (struct ieee80211_cb *)skb->cb;
|
||||||
struct ether_header *eh;
|
struct ether_header *eh;
|
||||||
STAILQ_HEAD(tmp_bf_head, ath_buf) bf_head;
|
STAILQ_HEAD(tmp_bf_head, ath_buf) bf_head;
|
||||||
struct ath_buf *tbf, *tempbf;
|
struct ath_buf *tbf, *tempbf;
|
||||||
|
@ -2684,8 +2682,7 @@ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: use this lock to protect an->an_tx_ffbuf (and txq->axq_stageq)
|
/* NB: use this lock to protect an->an_tx_ffbuf (and txq->axq_stageq)
|
||||||
* in athff_can_aggregate() call too.
|
* in athff_can_aggregate() call too. */
|
||||||
*/
|
|
||||||
ATH_TXQ_LOCK_IRQ(txq);
|
ATH_TXQ_LOCK_IRQ(txq);
|
||||||
if (athff_can_aggregate(sc, eh, an, skb, vap->iv_fragthreshold, &ff_flush)) {
|
if (athff_can_aggregate(sc, eh, an, skb, vap->iv_fragthreshold, &ff_flush)) {
|
||||||
if (an->an_tx_ffbuf[skb->priority]) { /* i.e., frame on the staging queue */
|
if (an->an_tx_ffbuf[skb->priority]) { /* i.e., frame on the staging queue */
|
||||||
|
@ -2723,7 +2720,7 @@ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
|
||||||
"%s: adding to fast-frame stage Q\n", __func__);
|
"%s: adding to fast-frame stage Q\n", __func__);
|
||||||
|
|
||||||
bf->bf_skb = skb;
|
bf->bf_skb = skb;
|
||||||
bf->bf_node = ni;
|
bf->bf_node = ieee80211_ref_node(ni);
|
||||||
bf->bf_queueage = txq->axq_totalqueued;
|
bf->bf_queueage = txq->axq_totalqueued;
|
||||||
an->an_tx_ffbuf[skb->priority] = bf;
|
an->an_tx_ffbuf[skb->priority] = bf;
|
||||||
|
|
||||||
|
@ -2744,12 +2741,11 @@ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
|
||||||
/* NB: ath_tx_start -> ath_tx_txqaddbuf uses ATH_TXQ_LOCK too */
|
/* NB: ath_tx_start -> ath_tx_txqaddbuf uses ATH_TXQ_LOCK too */
|
||||||
ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
|
ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
|
||||||
|
|
||||||
/* encap and xmit */
|
/* Encap. and transmit */
|
||||||
bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
|
bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
|
||||||
|
|
||||||
if (bf_ff->bf_skb == NULL) {
|
if (bf_ff->bf_skb == NULL) {
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT,
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
||||||
"%s: discard, ff flush encap failure\n",
|
"%s: discard, fast-frame flush encap. failure\n",
|
||||||
__func__);
|
__func__);
|
||||||
sc->sc_stats.ast_tx_encap++;
|
sc->sc_stats.ast_tx_encap++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2760,13 +2756,15 @@ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
|
DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
|
||||||
"%s: ff stageq flush failure\n", __func__);
|
"%s: fast-frame stageq flush failure\n", __func__);
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
if (bf_ff->bf_skb) {
|
if (bf_ff->bf_skb) {
|
||||||
|
cb = (struct ieee80211_cb *)bf_ff->bf_skb->cb;
|
||||||
|
if (&cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf_ff->bf_skb);
|
dev_kfree_skb(bf_ff->bf_skb);
|
||||||
bf_ff->bf_skb = NULL;
|
bf_ff->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
bf_ff->bf_node = NULL;
|
ieee80211_unref_node(&bf_ff->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
|
||||||
|
@ -2832,20 +2830,18 @@ ff_bypass:
|
||||||
for (bfcnt = 1; bfcnt < framecnt; ++bfcnt) {
|
for (bfcnt = 1; bfcnt < framecnt; ++bfcnt) {
|
||||||
if ((tbf = STAILQ_FIRST(&sc->sc_txbuf)) != NULL) {
|
if ((tbf = STAILQ_FIRST(&sc->sc_txbuf)) != NULL) {
|
||||||
STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
|
STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
|
||||||
|
tbf->bf_node = ieee80211_ref_node(ni);
|
||||||
STAILQ_INSERT_TAIL(&bf_head, tbf, bf_list);
|
STAILQ_INSERT_TAIL(&bf_head, tbf, bf_list);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ieee80211_ref_node(ni);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfcnt != framecnt) {
|
if (bfcnt != framecnt) {
|
||||||
if (!STAILQ_EMPTY(&bf_head)) {
|
if (!STAILQ_EMPTY(&bf_head)) {
|
||||||
/*
|
/* Failed to alloc enough ath_bufs;
|
||||||
* Failed to alloc enough ath_bufs;
|
* return to sc_txbuf list */
|
||||||
* return to sc_txbuf list
|
|
||||||
*/
|
|
||||||
STAILQ_FOREACH_SAFE(tbf, &bf_head, bf_list, tempbf) {
|
STAILQ_FOREACH_SAFE(tbf, &bf_head, bf_list, tempbf) {
|
||||||
|
ieee80211_unref_node(&tbf->bf_node);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2855,7 +2851,7 @@ ff_bypass:
|
||||||
}
|
}
|
||||||
ATH_TXBUF_UNLOCK_IRQ(sc);
|
ATH_TXBUF_UNLOCK_IRQ(sc);
|
||||||
|
|
||||||
while ((bf = STAILQ_FIRST(&bf_head)) != NULL && skb != NULL) {
|
while (((bf = STAILQ_FIRST(&bf_head)) != NULL) && (skb != NULL)) {
|
||||||
unsigned int nextfraglen = 0;
|
unsigned int nextfraglen = 0;
|
||||||
|
|
||||||
STAILQ_REMOVE_HEAD(&bf_head, bf_list);
|
STAILQ_REMOVE_HEAD(&bf_head, bf_list);
|
||||||
|
@ -2878,6 +2874,8 @@ ff_bypass:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ni = NULL;
|
||||||
|
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
/* flush out stale FF from staging Q for applicable operational modes. */
|
/* flush out stale FF from staging Q for applicable operational modes. */
|
||||||
/* XXX: ADHOC mode too? */
|
/* XXX: ADHOC mode too? */
|
||||||
|
@ -2892,24 +2890,26 @@ hardstart_fail:
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_FOREACH_SAFE(tbf, &bf_head, bf_list, tempbf) {
|
STAILQ_FOREACH_SAFE(tbf, &bf_head, bf_list, tempbf) {
|
||||||
tbf->bf_skb = NULL;
|
tbf->bf_skb = NULL;
|
||||||
tbf->bf_node = NULL;
|
if (tbf->bf_node != NULL)
|
||||||
|
ieee80211_unref_node(&tbf->bf_node);
|
||||||
if (ni != NULL)
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
|
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
|
||||||
}
|
}
|
||||||
ATH_TXBUF_UNLOCK_IRQ(sc);
|
ATH_TXBUF_UNLOCK_IRQ(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* let the kernel requeue the skb (dont free it!) */
|
/* Pass control of the skb to the caller (i.e., resources are their
|
||||||
|
* problem). */
|
||||||
if (requeue)
|
if (requeue)
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
|
|
||||||
/* free sk_buffs */
|
/* Otherwise, we have to deal with them. */
|
||||||
while (skb) {
|
while (skb) {
|
||||||
tskb = skb->next;
|
tskb = skb->next;
|
||||||
skb->next = NULL;
|
skb->next = NULL;
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
skb = tskb;
|
skb = tskb;
|
||||||
}
|
}
|
||||||
|
@ -2930,9 +2930,8 @@ ath_mgtstart(struct ieee80211com *ic, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct net_device *dev = ic->ic_dev;
|
struct net_device *dev = ic->ic_dev;
|
||||||
struct ath_softc *sc = dev->priv;
|
struct ath_softc *sc = dev->priv;
|
||||||
struct ieee80211_node *ni = NULL;
|
|
||||||
struct ath_buf *bf = NULL;
|
struct ath_buf *bf = NULL;
|
||||||
struct ieee80211_cb *cb;
|
struct ieee80211_cb *cb = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if ((dev->flags & IFF_RUNNING) == 0 || sc->sc_invalid) {
|
if ((dev->flags & IFF_RUNNING) == 0 || sc->sc_invalid) {
|
||||||
|
@ -2973,26 +2972,33 @@ ath_mgtstart(struct ieee80211com *ic, struct sk_buff *skb)
|
||||||
* we need to hold the reference with the frame.
|
* we need to hold the reference with the frame.
|
||||||
*/
|
*/
|
||||||
cb = (struct ieee80211_cb *)skb->cb;
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
ni = cb->ni;
|
error = ath_tx_start(dev, cb->ni, bf, skb, 0);
|
||||||
error = ath_tx_start(dev, ni, bf, skb, 0);
|
if (error)
|
||||||
if (error == 0) {
|
goto bad;
|
||||||
sc->sc_stats.ast_tx_mgmt++;
|
|
||||||
return 0;
|
sc->sc_stats.ast_tx_mgmt++;
|
||||||
}
|
return 0;
|
||||||
/* fall thru... */
|
|
||||||
bad:
|
bad:
|
||||||
if (ni != NULL)
|
/* XXX: ath_tx_start does not appear to clean up after itself if it
|
||||||
ieee80211_unref_node(&ni);
|
* fails in the middle of setting up a buffer. We do that here.
|
||||||
|
* This is evil. */
|
||||||
|
if (cb != NULL)
|
||||||
|
if (&cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
|
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
|
skb = NULL;
|
||||||
|
|
||||||
if (bf != NULL) {
|
if (bf != NULL) {
|
||||||
|
if (bf->bf_node != NULL)
|
||||||
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
/* NB: bf->bf_skb == skb, so the resources are freed above */
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
bf->bf_node = NULL;
|
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
||||||
ATH_TXBUF_UNLOCK_IRQ(sc);
|
ATH_TXBUF_UNLOCK_IRQ(sc);
|
||||||
}
|
}
|
||||||
dev_kfree_skb_any(skb);
|
|
||||||
skb = NULL;
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3953,6 +3959,7 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
|
||||||
{
|
{
|
||||||
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
||||||
struct ieee80211_frame *wh;
|
struct ieee80211_frame *wh;
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
@ -3963,6 +3970,9 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
|
||||||
if (bf->bf_skb != NULL) {
|
if (bf->bf_skb != NULL) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf->bf_skb);
|
dev_kfree_skb(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4031,8 +4041,7 @@ ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
#define USE_SHPREAMBLE(_ic) \
|
#define USE_SHPREAMBLE(_ic) \
|
||||||
(((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
|
(((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
|
||||||
== IEEE80211_F_SHPREAMBLE)
|
== IEEE80211_F_SHPREAMBLE)
|
||||||
struct ieee80211_node *ni = bf->bf_node;
|
struct ieee80211com *ic = bf->bf_node->ni_ic;
|
||||||
struct ieee80211com *ic = ni->ni_ic;
|
|
||||||
struct sk_buff *skb = bf->bf_skb;
|
struct sk_buff *skb = bf->bf_skb;
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_desc *ds;
|
struct ath_desc *ds;
|
||||||
|
@ -4107,7 +4116,7 @@ ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
skb->len + IEEE80211_CRC_LEN, /* frame length */
|
skb->len + IEEE80211_CRC_LEN, /* frame length */
|
||||||
sizeof(struct ieee80211_frame), /* header length */
|
sizeof(struct ieee80211_frame), /* header length */
|
||||||
HAL_PKT_TYPE_BEACON, /* Atheros packet type */
|
HAL_PKT_TYPE_BEACON, /* Atheros packet type */
|
||||||
ni->ni_txpower, /* txpower XXX */
|
bf->bf_node->ni_txpower, /* txpower XXX */
|
||||||
rate, 1, /* series 0 rate/tries */
|
rate, 1, /* series 0 rate/tries */
|
||||||
HAL_TXKEYIX_INVALID, /* no encryption */
|
HAL_TXKEYIX_INVALID, /* no encryption */
|
||||||
antenna, /* antenna mode */
|
antenna, /* antenna mode */
|
||||||
|
@ -4142,7 +4151,6 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
||||||
{
|
{
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct ieee80211_node *ni;
|
|
||||||
struct ath_vap *avp;
|
struct ath_vap *avp;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned int curlen, ncabq;
|
unsigned int curlen, ncabq;
|
||||||
|
@ -4168,7 +4176,6 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
bf = avp->av_bcbuf;
|
bf = avp->av_bcbuf;
|
||||||
ni = bf->bf_node;
|
|
||||||
|
|
||||||
#ifdef ATH_SUPERG_DYNTURBO
|
#ifdef ATH_SUPERG_DYNTURBO
|
||||||
/*
|
/*
|
||||||
|
@ -4192,7 +4199,7 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
||||||
skb = bf->bf_skb;
|
skb = bf->bf_skb;
|
||||||
curlen = skb->len;
|
curlen = skb->len;
|
||||||
ncabq = avp->av_mcastq.axq_depth;
|
ncabq = avp->av_mcastq.axq_depth;
|
||||||
if (ieee80211_beacon_update(ni, &avp->av_boff, skb, ncabq)) {
|
if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, skb, ncabq)) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, curlen, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, curlen, BUS_DMA_TODEVICE);
|
||||||
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
|
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
|
||||||
|
@ -4379,7 +4386,7 @@ ath_beacon_send(struct ath_softc *sc, int *needmark)
|
||||||
if (sc->sc_updateslot == UPDATE) {
|
if (sc->sc_updateslot == UPDATE) {
|
||||||
sc->sc_updateslot = COMMIT; /* commit next beacon */
|
sc->sc_updateslot = COMMIT; /* commit next beacon */
|
||||||
sc->sc_slotupdate = slot;
|
sc->sc_slotupdate = slot;
|
||||||
} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
|
} else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot))
|
||||||
ath_setslottime(sc); /* commit change to hardware */
|
ath_setslottime(sc); /* commit change to hardware */
|
||||||
|
|
||||||
if ((!sc->sc_stagbeacons || slot == 0) && (!sc->sc_diversity)) {
|
if ((!sc->sc_stagbeacons || slot == 0) && (!sc->sc_diversity)) {
|
||||||
|
@ -4454,7 +4461,6 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct ieee80211_node *ni;
|
|
||||||
struct ath_vap *avp;
|
struct ath_vap *avp;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
@ -4465,7 +4471,6 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bf = avp->av_bcbuf;
|
bf = avp->av_bcbuf;
|
||||||
ni = bf->bf_node;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update dynamic beacon contents. If this returns
|
* Update dynamic beacon contents. If this returns
|
||||||
|
@ -4474,7 +4479,7 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||||
* of the TIM bitmap).
|
* of the TIM bitmap).
|
||||||
*/
|
*/
|
||||||
skb = bf->bf_skb;
|
skb = bf->bf_skb;
|
||||||
if (ieee80211_beacon_update(ni, &avp->av_boff, skb, 0)) {
|
if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, skb, 0)) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
|
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
|
||||||
|
@ -4502,9 +4507,13 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||||
static void
|
static void
|
||||||
ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf)
|
ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
if (bf->bf_skb != NULL) {
|
if (bf->bf_skb != NULL) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf->bf_skb);
|
dev_kfree_skb(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4520,11 +4529,15 @@ static void
|
||||||
ath_beacon_free(struct ath_softc *sc)
|
ath_beacon_free(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
|
|
||||||
STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
|
STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
|
||||||
if (bf->bf_skb != NULL) {
|
if (bf->bf_skb != NULL) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf->bf_skb);
|
dev_kfree_skb(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4771,7 +4784,7 @@ ath_descdma_setup(struct ath_softc *sc,
|
||||||
bsize = sizeof(struct ath_buf) * nbuf;
|
bsize = sizeof(struct ath_buf) * nbuf;
|
||||||
bf = kmalloc(bsize, GFP_KERNEL);
|
bf = kmalloc(bsize, GFP_KERNEL);
|
||||||
if (bf == NULL) {
|
if (bf == NULL) {
|
||||||
error = -ENOMEM; /* XXX different code */
|
error = -ENOMEM;
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
memset(bf, 0, bsize);
|
memset(bf, 0, bsize);
|
||||||
|
@ -4798,7 +4811,7 @@ ath_descdma_cleanup(struct ath_softc *sc,
|
||||||
struct ath_descdma *dd, ath_bufhead *head, int dir)
|
struct ath_descdma *dd, ath_bufhead *head, int dir)
|
||||||
{
|
{
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct ieee80211_node *ni;
|
struct ieee80211_cb *cb = NULL;
|
||||||
|
|
||||||
STAILQ_FOREACH(bf, head, bf_list) {
|
STAILQ_FOREACH(bf, head, bf_list) {
|
||||||
if (bf->bf_skb != NULL) {
|
if (bf->bf_skb != NULL) {
|
||||||
|
@ -4809,17 +4822,14 @@ ath_descdma_cleanup(struct ath_softc *sc,
|
||||||
else
|
else
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, dir);
|
bf->bf_skbaddr, bf->bf_skb->len, dir);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf->bf_skb);
|
dev_kfree_skb(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
}
|
}
|
||||||
ni = bf->bf_node;
|
if (bf->bf_node != NULL)
|
||||||
bf->bf_node = NULL;
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
if (ni != NULL) {
|
|
||||||
/*
|
|
||||||
* Reclaim node reference.
|
|
||||||
*/
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free memory associated with descriptors */
|
/* Free memory associated with descriptors */
|
||||||
|
@ -4936,13 +4946,15 @@ ath_node_cleanup(struct ieee80211_node *ni)
|
||||||
bf = STAILQ_FIRST(&an->an_uapsd_q);
|
bf = STAILQ_FIRST(&an->an_uapsd_q);
|
||||||
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
||||||
|
|
||||||
cb = (struct ieee80211_cb *) bf->bf_skb->cb;
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
ieee80211_unref_node(&cb->ni);
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb_any(bf->bf_skb);
|
dev_kfree_skb_any(bf->bf_skb);
|
||||||
|
bf->bf_skb = NULL;
|
||||||
|
|
||||||
bf->bf_desc->ds_link = 0;
|
bf->bf_desc->ds_link = 0;
|
||||||
bf->bf_skb = NULL;
|
if (bf->bf_node != NULL)
|
||||||
bf->bf_node = NULL;
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
||||||
|
@ -4955,13 +4967,15 @@ ath_node_cleanup(struct ieee80211_node *ni)
|
||||||
bf = STAILQ_FIRST(&an->an_uapsd_overflowq);
|
bf = STAILQ_FIRST(&an->an_uapsd_overflowq);
|
||||||
STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list);
|
STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list);
|
||||||
|
|
||||||
cb = (struct ieee80211_cb *) bf->bf_skb->cb;
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
ieee80211_unref_node(&cb->ni);
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb_any(bf->bf_skb);
|
dev_kfree_skb_any(bf->bf_skb);
|
||||||
|
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
bf->bf_node = NULL;
|
|
||||||
bf->bf_desc->ds_link = 0;
|
bf->bf_desc->ds_link = 0;
|
||||||
|
if (bf->bf_node != NULL)
|
||||||
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
||||||
|
@ -5157,7 +5171,8 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
||||||
while (bf) {
|
while (bf) {
|
||||||
skb = bf->bf_skb;
|
skb = bf->bf_skb;
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
bf->bf_node = NULL;
|
if (bf->bf_node != NULL)
|
||||||
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
||||||
|
@ -5498,21 +5513,26 @@ ath_tx_capture(struct net_device *dev, const struct ath_buf *bf, struct sk_buff
|
||||||
const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
|
const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
|
||||||
struct ieee80211com *ic = &sc->sc_ic;
|
struct ieee80211com *ic = &sc->sc_ic;
|
||||||
struct ieee80211_frame *wh;
|
struct ieee80211_frame *wh;
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
unsigned int extra = A_MAX(sizeof(struct ath_tx_radiotap_header),
|
unsigned int extra = A_MAX(sizeof(struct ath_tx_radiotap_header),
|
||||||
A_MAX(sizeof(struct wlan_ng_prism2_header),
|
A_MAX(sizeof(struct wlan_ng_prism2_header),
|
||||||
ATHDESC_HEADER_SIZE));
|
ATHDESC_HEADER_SIZE));
|
||||||
u_int32_t tstamp;
|
u_int32_t tstamp;
|
||||||
unsigned int headersize;
|
unsigned int headersize;
|
||||||
int padbytes;
|
int padbytes;
|
||||||
/*
|
|
||||||
* release the owner of this skb since we're basically
|
/* Release the owner of this skb since we're basically recycling it. */
|
||||||
* recycling it
|
|
||||||
*/
|
|
||||||
if (atomic_read(&skb->users) != 1) {
|
if (atomic_read(&skb->users) != 1) {
|
||||||
struct sk_buff *skb2 = skb;
|
struct sk_buff *skb2 = skb;
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (skb == NULL) {
|
if (skb == NULL) {
|
||||||
printk("%s:%d %s\n", __FILE__, __LINE__, __func__);
|
printk("%s:%d %s\n", __FILE__, __LINE__, __func__);
|
||||||
|
|
||||||
|
/* Another copy of the skb has not been made so we
|
||||||
|
* must release the reference. */
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(skb2);
|
dev_kfree_skb(skb2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5550,6 +5570,9 @@ ath_tx_capture(struct net_device *dev, const struct ath_buf *bf, struct sk_buff
|
||||||
ieee80211_input_monitor(ic, skb, bf, 1, tsf, sc);
|
ieee80211_input_monitor(ic, skb, bf, 1, tsf, sc);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5851,13 +5874,10 @@ rx_accept:
|
||||||
*/
|
*/
|
||||||
if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
|
if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
|
||||||
(ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
|
(ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
|
||||||
struct ath_node *an;
|
/* Fast path: node is present in the key map;
|
||||||
/*
|
* grab a reference for processing the frame. */
|
||||||
* Fast path: node is present in the key map;
|
ni = ieee80211_ref_node(ni);
|
||||||
* grab a reference for processing the frame.
|
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
|
||||||
*/
|
|
||||||
an = ATH_NODE(ieee80211_ref_node(ni));
|
|
||||||
ATH_RSSI_LPF(an->an_avgrssi, rs->rs_rssi);
|
|
||||||
type = ieee80211_input(ni, skb, rs->rs_rssi, rs_tsf);
|
type = ieee80211_input(ni, skb, rs->rs_rssi, rs_tsf);
|
||||||
ieee80211_unref_node(&ni);
|
ieee80211_unref_node(&ni);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5881,6 +5901,7 @@ rx_accept:
|
||||||
if (keyix != IEEE80211_KEYIX_NONE &&
|
if (keyix != IEEE80211_KEYIX_NONE &&
|
||||||
sc->sc_keyixmap[keyix] == NULL)
|
sc->sc_keyixmap[keyix] == NULL)
|
||||||
sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
|
sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
|
||||||
|
an = NULL;
|
||||||
ieee80211_unref_node(&ni);
|
ieee80211_unref_node(&ni);
|
||||||
} else
|
} else
|
||||||
type = ieee80211_input_all(ic, skb, rs->rs_rssi, rs_tsf);
|
type = ieee80211_input_all(ic, skb, rs->rs_rssi, rs_tsf);
|
||||||
|
@ -6285,6 +6306,7 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
||||||
static void ath_grppoll_stop(struct ieee80211vap *vap)
|
static void ath_grppoll_stop(struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
struct ath_softc *sc = ic->ic_dev->priv;
|
struct ath_softc *sc = ic->ic_dev->priv;
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_txq *txq = &sc->sc_grpplq;
|
struct ath_txq *txq = &sc->sc_grpplq;
|
||||||
|
@ -6309,9 +6331,13 @@ static void ath_grppoll_stop(struct ieee80211vap *vap)
|
||||||
|
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(bf->bf_skb);
|
dev_kfree_skb(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
bf->bf_node = NULL;
|
if (bf->bf_node != NULL)
|
||||||
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_grppollbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_grppollbuf, bf, bf_list);
|
||||||
|
@ -6633,11 +6659,12 @@ ath_tx_findindex(const HAL_RATE_TABLE *rt, int rate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needs external locking!
|
* XXX: Needs external locking!
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
struct ath_buf *lastbuf;
|
struct ath_buf *lastbuf;
|
||||||
|
|
||||||
/* case the delivery queue just sent and can move overflow q over */
|
/* case the delivery queue just sent and can move overflow q over */
|
||||||
|
@ -6675,6 +6702,9 @@ ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
||||||
*/
|
*/
|
||||||
lastbuf = STAILQ_FIRST(&an->an_uapsd_q);
|
lastbuf = STAILQ_FIRST(&an->an_uapsd_q);
|
||||||
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
||||||
|
cb = (struct ieee80211_cb *)lastbuf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb(lastbuf->bf_skb);
|
dev_kfree_skb(lastbuf->bf_skb);
|
||||||
lastbuf->bf_skb = NULL;
|
lastbuf->bf_skb = NULL;
|
||||||
ieee80211_unref_node(&lastbuf->bf_node);
|
ieee80211_unref_node(&lastbuf->bf_node);
|
||||||
|
@ -6805,7 +6835,7 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni, struct ath_buf *
|
||||||
ivlen = ath_get_ivlen(k) / 4;
|
ivlen = ath_get_ivlen(k) / 4;
|
||||||
#endif
|
#endif
|
||||||
/* packet header may have moved, reset our local pointer */
|
/* packet header may have moved, reset our local pointer */
|
||||||
wh = (struct ieee80211_frame *) skb->data;
|
wh = (struct ieee80211_frame *)skb->data;
|
||||||
} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
|
} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
|
||||||
/*
|
/*
|
||||||
* Use station key cache slot, if assigned.
|
* Use station key cache slot, if assigned.
|
||||||
|
@ -6847,7 +6877,7 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni, struct ath_buf *
|
||||||
}
|
}
|
||||||
#endif /* ATH_SUPERG_FF */
|
#endif /* ATH_SUPERG_FF */
|
||||||
bf->bf_skb = skb;
|
bf->bf_skb = skb;
|
||||||
bf->bf_node = ni;
|
bf->bf_node = ieee80211_ref_node(ni);
|
||||||
|
|
||||||
/* setup descriptors */
|
/* setup descriptors */
|
||||||
ds = bf->bf_desc;
|
ds = bf->bf_desc;
|
||||||
|
@ -7299,7 +7329,7 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni, struct ath_buf *
|
||||||
ieee80211_node_refcnt(vap->iv_bss));
|
ieee80211_node_refcnt(vap->iv_bss));
|
||||||
|
|
||||||
|
|
||||||
ath_tx_txqaddbuf(sc, ni, txq, bf, ds, pktlen);
|
ath_tx_txqaddbuf(sc, PASS_NODE(ni), txq, bf, ds, pktlen);
|
||||||
return 0;
|
return 0;
|
||||||
#undef MIN
|
#undef MIN
|
||||||
}
|
}
|
||||||
|
@ -7418,14 +7448,6 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
|
if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
|
||||||
(bf->bf_flags & HAL_TXDESC_NOACK) == 0)
|
(bf->bf_flags & HAL_TXDESC_NOACK) == 0)
|
||||||
sc->sc_rc->ops->tx_complete(sc, an, bf);
|
sc->sc_rc->ops->tx_complete(sc, an, bf);
|
||||||
/*
|
|
||||||
* Reclaim reference to node.
|
|
||||||
*
|
|
||||||
* NB: the node may be reclaimed here if, for example
|
|
||||||
* this is a DEAUTH message that was sent and the
|
|
||||||
* node was timed out due to inactivity.
|
|
||||||
*/
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
||||||
|
@ -7493,7 +7515,13 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
}
|
}
|
||||||
|
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
bf->bf_node = NULL;
|
/* Reclaim reference to node.
|
||||||
|
*
|
||||||
|
* NB: the node may be reclaimed here if, for example
|
||||||
|
* this is a DEAUTH message that was sent and the
|
||||||
|
* node was timed out due to inactivity. */
|
||||||
|
ieee80211_unref_node(&bf->bf_node);
|
||||||
|
ni = NULL;
|
||||||
|
|
||||||
ATH_TXBUF_LOCK_IRQ(sc);
|
ATH_TXBUF_LOCK_IRQ(sc);
|
||||||
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
||||||
|
@ -7638,6 +7666,7 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
struct ieee80211_cb* cb = NULL;
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
struct sk_buff *tskb;
|
struct sk_buff *tskb;
|
||||||
#endif
|
#endif
|
||||||
|
@ -7664,6 +7693,9 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
skb = bf->bf_skb->next;
|
skb = bf->bf_skb->next;
|
||||||
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
|
||||||
bf->bf_skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)bf->bf_skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb_any(bf->bf_skb);
|
dev_kfree_skb_any(bf->bf_skb);
|
||||||
bf->bf_skb = NULL;
|
bf->bf_skb = NULL;
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
|
@ -7673,6 +7705,9 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
tskb = skb->next;
|
tskb = skb->next;
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddrff[i++], skb->len, BUS_DMA_TODEVICE);
|
bf->bf_skbaddrff[i++], skb->len, BUS_DMA_TODEVICE);
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
if (cb->ni != NULL)
|
||||||
|
ieee80211_unref_node(&cb->ni);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
skb = tskb;
|
skb = tskb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
||||||
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 ieee80211_frame *wh;
|
struct ieee80211_frame *wh;
|
||||||
|
struct ieee80211_cb *cb = NULL;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int pktlen;
|
int pktlen;
|
||||||
u_int8_t *frm;
|
u_int8_t *frm;
|
||||||
|
@ -255,6 +256,9 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
cb->ni = ieee80211_ref_node(ni);
|
||||||
|
|
||||||
frm = ieee80211_beacon_init(ni, bo, frm);
|
frm = ieee80211_beacon_init(ni, bo, frm);
|
||||||
|
|
||||||
skb_trim(skb, frm - skb->data);
|
skb_trim(skb, frm - skb->data);
|
||||||
|
|
|
@ -467,7 +467,7 @@ ieee80211_input(struct ieee80211_node *ni,
|
||||||
nt = &ic->ic_sta;
|
nt = &ic->ic_sta;
|
||||||
ni_wds = ieee80211_find_wds_node(nt, wh->i_addr3);
|
ni_wds = ieee80211_find_wds_node(nt, wh->i_addr3);
|
||||||
if (ni_wds) {
|
if (ni_wds) {
|
||||||
ieee80211_unref_node(&ni_wds); /* Decr ref count */
|
ieee80211_unref_node(&ni_wds);
|
||||||
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
|
IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
|
||||||
wh, NULL, "%s",
|
wh, NULL, "%s",
|
||||||
"multicast echo originated from node behind me");
|
"multicast echo originated from node behind me");
|
||||||
|
@ -914,6 +914,9 @@ ieee80211_input_all(struct ieee80211com *ic,
|
||||||
skb1 = skb;
|
skb1 = skb;
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
}
|
}
|
||||||
|
/* This function does not 'own' vap->iv_bss, so we cannot
|
||||||
|
* guarantee its existence during the following call, hence
|
||||||
|
* briefly grab our own reference. */
|
||||||
ni = ieee80211_ref_node(vap->iv_bss);
|
ni = ieee80211_ref_node(vap->iv_bss);
|
||||||
type = ieee80211_input(ni, skb1, rssi, rtsf);
|
type = ieee80211_input(ni, skb1, rssi, rtsf);
|
||||||
ieee80211_unref_node(&ni);
|
ieee80211_unref_node(&ni);
|
||||||
|
|
|
@ -431,13 +431,11 @@ ieee80211_mgmt_output(struct ieee80211_node *ni, struct sk_buff *skb, int type)
|
||||||
(void) ic->ic_mgtstart(ic, skb);
|
(void) ic->ic_mgtstart(ic, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Send a null data frame to the specified node.
|
||||||
* Send a null data frame to the specified node.
|
|
||||||
*
|
*
|
||||||
* NB: the caller is assumed to have setup a node reference
|
* NB: the caller provides us with our own node reference this must not be
|
||||||
* for use; this is necessary to deal with a race condition
|
* leaked; this is necessary to deal with a race condition when
|
||||||
* when probing for inactive stations.
|
* probing for inactive stations. */
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
ieee80211_send_nulldata(struct ieee80211_node *ni)
|
ieee80211_send_nulldata(struct ieee80211_node *ni)
|
||||||
{
|
{
|
||||||
|
@ -455,8 +453,6 @@ ieee80211_send_nulldata(struct ieee80211_node *ni)
|
||||||
ieee80211_unref_node(&ni);
|
ieee80211_unref_node(&ni);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
cb = (struct ieee80211_cb *)skb->cb;
|
|
||||||
cb->ni = ni;
|
|
||||||
|
|
||||||
wh = (struct ieee80211_frame *)
|
wh = (struct ieee80211_frame *)
|
||||||
skb_push(skb, sizeof(struct ieee80211_frame));
|
skb_push(skb, sizeof(struct ieee80211_frame));
|
||||||
|
@ -485,6 +481,8 @@ ieee80211_send_nulldata(struct ieee80211_node *ni)
|
||||||
|
|
||||||
/* XXX assign some priority; this probably is wrong */
|
/* XXX assign some priority; this probably is wrong */
|
||||||
skb->priority = WME_AC_BE;
|
skb->priority = WME_AC_BE;
|
||||||
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
|
cb->ni = PASS_NODE(ni);
|
||||||
|
|
||||||
(void) ic->ic_mgtstart(ic, skb); /* cheat */
|
(void) ic->ic_mgtstart(ic, skb); /* cheat */
|
||||||
|
|
||||||
|
@ -853,13 +851,13 @@ ieee80211_encap(struct ieee80211_node *ni, struct sk_buff *skb, int *framecnt)
|
||||||
!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
|
!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
|
||||||
use4addr = 1;
|
use4addr = 1;
|
||||||
ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);
|
ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);
|
||||||
/* Add a wds entry to the station VAP */
|
/* Add a WDS entry to the station VAP */
|
||||||
if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
|
if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
|
||||||
struct ieee80211_node_table *nt = &ic->ic_sta;
|
struct ieee80211_node_table *nt = &ic->ic_sta;
|
||||||
struct ieee80211_node *ni_wds
|
struct ieee80211_node *ni_wds
|
||||||
= ieee80211_find_wds_node(nt, eh.ether_shost);
|
= ieee80211_find_wds_node(nt, eh.ether_shost);
|
||||||
if (ni_wds)
|
if (ni_wds)
|
||||||
ieee80211_unref_node(&ni_wds); /* Decr. ref. count */
|
ieee80211_unref_node(&ni_wds);
|
||||||
else
|
else
|
||||||
ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0);
|
ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0);
|
||||||
}
|
}
|
||||||
|
@ -1699,17 +1697,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u_int8_t *frm;
|
u_int8_t *frm;
|
||||||
|
|
||||||
/*
|
|
||||||
* Hold a reference on the node so it doesn't go away until after
|
|
||||||
* the xmit is complete all the way in the driver. On error we
|
|
||||||
* will remove our reference.
|
|
||||||
*/
|
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
|
|
||||||
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
|
|
||||||
__func__, __LINE__,
|
|
||||||
ni, ether_sprintf(ni->ni_macaddr),
|
|
||||||
ieee80211_node_refcnt(ni) + 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prreq frame format
|
* prreq frame format
|
||||||
* [tlv] ssid
|
* [tlv] ssid
|
||||||
|
@ -1786,18 +1773,6 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
|
||||||
|
|
||||||
KASSERT(ni != NULL, ("null node"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
|
|
||||||
/*
|
|
||||||
* Hold a reference on the node so it doesn't go away until after
|
|
||||||
* the xmit is complete all the way in the driver. On error we
|
|
||||||
* will remove our reference.
|
|
||||||
*/
|
|
||||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
|
|
||||||
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
|
|
||||||
__func__, __LINE__,
|
|
||||||
ni, ether_sprintf(ni->ni_macaddr),
|
|
||||||
ieee80211_node_refcnt(ni) + 1);
|
|
||||||
ieee80211_ref_node(ni);
|
|
||||||
|
|
||||||
timer = 0;
|
timer = 0;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
||||||
|
@ -2217,12 +2192,11 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
ieee80211_mgmt_output(ni, skb, type);
|
ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type);
|
||||||
if (timer)
|
if (timer)
|
||||||
mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
|
mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
|
||||||
return 0;
|
return 0;
|
||||||
bad:
|
bad:
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
return ret;
|
return ret;
|
||||||
#undef senderr
|
#undef senderr
|
||||||
}
|
}
|
||||||
|
@ -2241,9 +2215,8 @@ ieee80211_send_pspoll(struct ieee80211_node *ni)
|
||||||
|
|
||||||
skb = dev_alloc_skb(sizeof(struct ieee80211_ctlframe_addr2));
|
skb = dev_alloc_skb(sizeof(struct ieee80211_ctlframe_addr2));
|
||||||
if (skb == NULL) return;
|
if (skb == NULL) return;
|
||||||
ieee80211_ref_node(ni);
|
|
||||||
cb = (struct ieee80211_cb *)skb->cb;
|
cb = (struct ieee80211_cb *)skb->cb;
|
||||||
cb->ni = ni;
|
cb->ni = ieee80211_ref_node(ni);
|
||||||
skb->priority = WME_AC_VO;
|
skb->priority = WME_AC_VO;
|
||||||
|
|
||||||
wh = (struct ieee80211_ctlframe_addr2 *) skb_put(skb, sizeof(struct ieee80211_ctlframe_addr2));
|
wh = (struct ieee80211_ctlframe_addr2 *) skb_put(skb, sizeof(struct ieee80211_ctlframe_addr2));
|
||||||
|
|
|
@ -3434,11 +3434,12 @@ ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
|
||||||
if (!IEEE80211_ADDR_EQ(mlme->im_macaddr, vap->iv_dev->broadcast)) {
|
if (!IEEE80211_ADDR_EQ(mlme->im_macaddr, vap->iv_dev->broadcast)) {
|
||||||
ni = ieee80211_find_node(&ic->ic_sta,
|
ni = ieee80211_find_node(&ic->ic_sta,
|
||||||
mlme->im_macaddr);
|
mlme->im_macaddr);
|
||||||
if (ni == NULL)
|
if (ni != NULL) {
|
||||||
|
if (dev == ni->ni_vap->iv_dev)
|
||||||
|
domlme(mlme, ni);
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (dev == ni->ni_vap->iv_dev)
|
|
||||||
domlme(mlme, ni);
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
} else
|
} else
|
||||||
ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme);
|
ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme);
|
||||||
break;
|
break;
|
||||||
|
@ -3451,24 +3452,26 @@ ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
|
||||||
if (vap->iv_opmode != IEEE80211_M_HOSTAP)
|
if (vap->iv_opmode != IEEE80211_M_HOSTAP)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
|
ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
|
||||||
if (ni == NULL)
|
if (ni != NULL) {
|
||||||
|
if (mlme->im_op == IEEE80211_MLME_AUTHORIZE)
|
||||||
|
ieee80211_node_authorize(ni);
|
||||||
|
else
|
||||||
|
ieee80211_node_unauthorize(ni);
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (mlme->im_op == IEEE80211_MLME_AUTHORIZE)
|
|
||||||
ieee80211_node_authorize(ni);
|
|
||||||
else
|
|
||||||
ieee80211_node_unauthorize(ni);
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
break;
|
break;
|
||||||
case IEEE80211_MLME_CLEAR_STATS:
|
case IEEE80211_MLME_CLEAR_STATS:
|
||||||
if (vap->iv_opmode != IEEE80211_M_HOSTAP)
|
if (vap->iv_opmode != IEEE80211_M_HOSTAP)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
|
ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
|
||||||
if (ni == NULL)
|
if (ni != NULL) {
|
||||||
|
/* clear statistics */
|
||||||
|
memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats));
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* clear statistics */
|
|
||||||
memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats));
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -3824,25 +3827,25 @@ ieee80211_ioctl_getwpaie(struct net_device *dev, struct iwreq *iwr)
|
||||||
if (copy_from_user(&wpaie, iwr->u.data.pointer, IEEE80211_ADDR_LEN))
|
if (copy_from_user(&wpaie, iwr->u.data.pointer, IEEE80211_ADDR_LEN))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
|
ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
|
||||||
if (ni == NULL)
|
if (ni != NULL) {
|
||||||
|
memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
|
||||||
|
if (ni->ni_wpa_ie != NULL) {
|
||||||
|
int ielen = ni->ni_wpa_ie[1] + 2;
|
||||||
|
if (ielen > sizeof(wpaie.wpa_ie))
|
||||||
|
ielen = sizeof(wpaie.wpa_ie);
|
||||||
|
memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
|
||||||
|
}
|
||||||
|
if (ni->ni_rsn_ie != NULL) {
|
||||||
|
int ielen = ni->ni_rsn_ie[1] + 2;
|
||||||
|
if (ielen > sizeof(wpaie.rsn_ie))
|
||||||
|
ielen = sizeof(wpaie.rsn_ie);
|
||||||
|
memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
|
||||||
|
}
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
return (copy_to_user(iwr->u.data.pointer, &wpaie, sizeof(wpaie)) ?
|
||||||
|
-EFAULT : 0);
|
||||||
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
|
|
||||||
if (ni->ni_wpa_ie != NULL) {
|
|
||||||
int ielen = ni->ni_wpa_ie[1] + 2;
|
|
||||||
if (ielen > sizeof(wpaie.wpa_ie))
|
|
||||||
ielen = sizeof(wpaie.wpa_ie);
|
|
||||||
memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen);
|
|
||||||
}
|
|
||||||
if (ni->ni_rsn_ie != NULL) {
|
|
||||||
int ielen = ni->ni_rsn_ie[1] + 2;
|
|
||||||
if (ielen > sizeof(wpaie.rsn_ie))
|
|
||||||
ielen = sizeof(wpaie.rsn_ie);
|
|
||||||
memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
|
|
||||||
}
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
return (copy_to_user(iwr->u.data.pointer, &wpaie, sizeof(wpaie)) ?
|
|
||||||
-EFAULT : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3860,16 +3863,16 @@ ieee80211_ioctl_getstastats(struct net_device *dev, struct iwreq *iwr)
|
||||||
if (copy_from_user(macaddr, iwr->u.data.pointer, IEEE80211_ADDR_LEN))
|
if (copy_from_user(macaddr, iwr->u.data.pointer, IEEE80211_ADDR_LEN))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ni = ieee80211_find_node(&ic->ic_sta, macaddr);
|
ni = ieee80211_find_node(&ic->ic_sta, macaddr);
|
||||||
if (ni == NULL)
|
if (ni != NULL) {
|
||||||
|
if (iwr->u.data.length > sizeof(struct ieee80211req_sta_stats))
|
||||||
|
iwr->u.data.length = sizeof(struct ieee80211req_sta_stats);
|
||||||
|
/* NB: copy out only the statistics */
|
||||||
|
error = copy_to_user(iwr->u.data.pointer + off, &ni->ni_stats,
|
||||||
|
iwr->u.data.length - off);
|
||||||
|
ieee80211_unref_node(&ni);
|
||||||
|
return (error ? -EFAULT : 0);
|
||||||
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
if (iwr->u.data.length > sizeof(struct ieee80211req_sta_stats))
|
|
||||||
iwr->u.data.length = sizeof(struct ieee80211req_sta_stats);
|
|
||||||
/* NB: copy out only the statistics */
|
|
||||||
error = copy_to_user(iwr->u.data.pointer + off, &ni->ni_stats,
|
|
||||||
iwr->u.data.length - off);
|
|
||||||
ieee80211_unref_node(&ni);
|
|
||||||
return (error ? -EFAULT : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct scanreq { /* XXX: right place for declaration? */
|
struct scanreq { /* XXX: right place for declaration? */
|
||||||
|
|
Loading…
Reference in New Issue