forked from Minki/linux
ath9k: Node cleanup
Start removing the internal node list in ath9k, in preparation for using mac80211's STA list. Remove lists, locks, routines, flags, functions managing nodes in ath9k. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
17683c65c8
commit
b5aa9bf946
@ -47,6 +47,41 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
|
|||||||
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
|
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 parse_mpdudensity(u8 mpdudensity)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
|
||||||
|
* 0 for no restriction
|
||||||
|
* 1 for 1/4 us
|
||||||
|
* 2 for 1/2 us
|
||||||
|
* 3 for 1 us
|
||||||
|
* 4 for 2 us
|
||||||
|
* 5 for 4 us
|
||||||
|
* 6 for 8 us
|
||||||
|
* 7 for 16 us
|
||||||
|
*/
|
||||||
|
switch (mpdudensity) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
/* Our lower layer calculations limit our precision to
|
||||||
|
1 microsecond */
|
||||||
|
return 1;
|
||||||
|
case 4:
|
||||||
|
return 2;
|
||||||
|
case 5:
|
||||||
|
return 4;
|
||||||
|
case 6:
|
||||||
|
return 8;
|
||||||
|
case 7:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set current operating mode
|
* Set current operating mode
|
||||||
*
|
*
|
||||||
@ -1321,7 +1356,7 @@ void ath_deinit(struct ath_softc *sc)
|
|||||||
/* Node Management */
|
/* Node Management */
|
||||||
/*******************/
|
/*******************/
|
||||||
|
|
||||||
struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
|
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, int if_id)
|
||||||
{
|
{
|
||||||
struct ath_vap *avp;
|
struct ath_vap *avp;
|
||||||
struct ath_node *an;
|
struct ath_node *an;
|
||||||
@ -1329,90 +1364,30 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
|
|||||||
avp = sc->sc_vaps[if_id];
|
avp = sc->sc_vaps[if_id];
|
||||||
ASSERT(avp != NULL);
|
ASSERT(avp != NULL);
|
||||||
|
|
||||||
/* mac80211 sta_notify callback is from an IRQ context, so no sleep */
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
|
|
||||||
if (an == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(an, 0, sizeof(*an));
|
|
||||||
|
|
||||||
an->an_sc = sc;
|
|
||||||
memcpy(an->an_addr, addr, ETH_ALEN);
|
|
||||||
atomic_set(&an->an_refcnt, 1);
|
|
||||||
|
|
||||||
/* set up per-node tx/rx state */
|
/* set up per-node tx/rx state */
|
||||||
ath_tx_node_init(sc, an);
|
ath_tx_node_init(sc, an);
|
||||||
ath_rx_node_init(sc, an);
|
ath_rx_node_init(sc, an);
|
||||||
|
|
||||||
|
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
|
||||||
|
sta->ht_cap.ampdu_factor);
|
||||||
|
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||||
|
|
||||||
ath_chainmask_sel_init(sc, an);
|
ath_chainmask_sel_init(sc, an);
|
||||||
ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
|
ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
|
||||||
list_add(&an->list, &sc->node_list);
|
|
||||||
|
|
||||||
return an;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
|
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||||
|
|
||||||
ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
|
ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
|
||||||
an->an_flags |= ATH_NODE_CLEAN;
|
|
||||||
ath_tx_node_cleanup(sc, an, bh_flag);
|
ath_tx_node_cleanup(sc, an);
|
||||||
ath_rx_node_cleanup(sc, an);
|
|
||||||
|
|
||||||
ath_tx_node_free(sc, an);
|
ath_tx_node_free(sc, an);
|
||||||
ath_rx_node_free(sc, an);
|
ath_rx_node_free(sc, an);
|
||||||
|
|
||||||
spin_lock_irqsave(&sc->node_lock, flags);
|
|
||||||
|
|
||||||
list_del(&an->list);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sc->node_lock, flags);
|
|
||||||
|
|
||||||
kfree(an);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finds a node and increases the refcnt if found */
|
|
||||||
|
|
||||||
struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr)
|
|
||||||
{
|
|
||||||
struct ath_node *an = NULL, *an_found = NULL;
|
|
||||||
|
|
||||||
if (list_empty(&sc->node_list)) /* FIXME */
|
|
||||||
goto out;
|
|
||||||
list_for_each_entry(an, &sc->node_list, list) {
|
|
||||||
if (!compare_ether_addr(an->an_addr, addr)) {
|
|
||||||
atomic_inc(&an->an_refcnt);
|
|
||||||
an_found = an;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
return an_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrements the refcnt and if it drops to zero, detach the node */
|
|
||||||
|
|
||||||
void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&an->an_refcnt))
|
|
||||||
ath_node_detach(sc, an, bh_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */
|
|
||||||
struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr)
|
|
||||||
{
|
|
||||||
struct ath_node *an = NULL, *an_found = NULL;
|
|
||||||
|
|
||||||
if (list_empty(&sc->node_list))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
list_for_each_entry(an, &sc->node_list, list)
|
|
||||||
if (!compare_ether_addr(an->an_addr, addr)) {
|
|
||||||
an_found = an;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return an_found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1437,7 +1412,6 @@ void ath_newassoc(struct ath_softc *sc,
|
|||||||
ath_rx_aggr_teardown(sc, an, tidno);
|
ath_rx_aggr_teardown(sc, an, tidno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
an->an_flags = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************/
|
/**************/
|
||||||
|
@ -373,7 +373,6 @@ void ath_flushrecv(struct ath_softc *sc);
|
|||||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||||
void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
|
void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
|
||||||
void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
|
void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
|
||||||
void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
|
|
||||||
void ath_handle_rx_intr(struct ath_softc *sc);
|
void ath_handle_rx_intr(struct ath_softc *sc);
|
||||||
int ath_rx_init(struct ath_softc *sc, int nbufs);
|
int ath_rx_init(struct ath_softc *sc, int nbufs);
|
||||||
void ath_rx_cleanup(struct ath_softc *sc);
|
void ath_rx_cleanup(struct ath_softc *sc);
|
||||||
@ -546,8 +545,7 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx);
|
|||||||
void ath_tx_draintxq(struct ath_softc *sc,
|
void ath_tx_draintxq(struct ath_softc *sc,
|
||||||
struct ath_txq *txq, bool retry_tx);
|
struct ath_txq *txq, bool retry_tx);
|
||||||
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
|
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
|
||||||
void ath_tx_node_cleanup(struct ath_softc *sc,
|
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
|
||||||
struct ath_node *an, bool bh_flag);
|
|
||||||
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
|
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
|
||||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
||||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
||||||
@ -568,11 +566,6 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
|
|||||||
/* Node / Aggregation */
|
/* Node / Aggregation */
|
||||||
/**********************/
|
/**********************/
|
||||||
|
|
||||||
/* indicates the node is clened up */
|
|
||||||
#define ATH_NODE_CLEAN 0x1
|
|
||||||
/* indicates the node is 80211 power save */
|
|
||||||
#define ATH_NODE_PWRSAVE 0x2
|
|
||||||
|
|
||||||
#define ADDBA_EXCHANGE_ATTEMPTS 10
|
#define ADDBA_EXCHANGE_ATTEMPTS 10
|
||||||
#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
|
#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
|
||||||
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
|
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
|
||||||
@ -584,6 +577,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
|
|||||||
#define IEEE80211_SEQ_SEQ_SHIFT 4
|
#define IEEE80211_SEQ_SEQ_SHIFT 4
|
||||||
#define IEEE80211_SEQ_MAX 4096
|
#define IEEE80211_SEQ_MAX 4096
|
||||||
#define IEEE80211_MIN_AMPDU_BUF 0x8
|
#define IEEE80211_MIN_AMPDU_BUF 0x8
|
||||||
|
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
|
||||||
|
|
||||||
/* return whether a bit at index _n in bitmap _bm is set
|
/* return whether a bit at index _n in bitmap _bm is set
|
||||||
* _sz is the size of the bitmap */
|
* _sz is the size of the bitmap */
|
||||||
@ -638,15 +632,10 @@ struct ath_node_aggr {
|
|||||||
|
|
||||||
/* driver-specific node state */
|
/* driver-specific node state */
|
||||||
struct ath_node {
|
struct ath_node {
|
||||||
struct list_head list;
|
|
||||||
struct ath_softc *an_sc;
|
struct ath_softc *an_sc;
|
||||||
atomic_t an_refcnt;
|
|
||||||
struct ath_chainmask_sel an_chainmask_sel;
|
struct ath_chainmask_sel an_chainmask_sel;
|
||||||
struct ath_node_aggr an_aggr;
|
struct ath_node_aggr an_aggr;
|
||||||
u8 an_smmode; /* SM Power save mode */
|
u8 an_smmode; /* SM Power save mode */
|
||||||
u8 an_flags;
|
|
||||||
u8 an_addr[ETH_ALEN];
|
|
||||||
|
|
||||||
u16 maxampdu;
|
u16 maxampdu;
|
||||||
u8 mpdudensity;
|
u8 mpdudensity;
|
||||||
};
|
};
|
||||||
@ -659,28 +648,17 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
|
|||||||
struct ath_node *an, u8 tidno);
|
struct ath_node *an, u8 tidno);
|
||||||
void ath_rx_aggr_teardown(struct ath_softc *sc,
|
void ath_rx_aggr_teardown(struct ath_softc *sc,
|
||||||
struct ath_node *an, u8 tidno);
|
struct ath_node *an, u8 tidno);
|
||||||
int ath_rx_aggr_start(struct ath_softc *sc,
|
int ath_rx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
const u8 *addr,
|
u16 tid, u16 *ssn);
|
||||||
u16 tid,
|
int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||||
u16 *ssn);
|
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
int ath_rx_aggr_stop(struct ath_softc *sc,
|
u16 tid, u16 *ssn);
|
||||||
const u8 *addr,
|
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||||
u16 tid);
|
|
||||||
int ath_tx_aggr_start(struct ath_softc *sc,
|
|
||||||
const u8 *addr,
|
|
||||||
u16 tid,
|
|
||||||
u16 *ssn);
|
|
||||||
int ath_tx_aggr_stop(struct ath_softc *sc,
|
|
||||||
const u8 *addr,
|
|
||||||
u16 tid);
|
|
||||||
void ath_newassoc(struct ath_softc *sc,
|
void ath_newassoc(struct ath_softc *sc,
|
||||||
struct ath_node *node, int isnew, int isuapsd);
|
struct ath_node *node, int isnew, int isuapsd);
|
||||||
struct ath_node *ath_node_attach(struct ath_softc *sc,
|
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
u8 addr[ETH_ALEN], int if_id);
|
int if_id);
|
||||||
void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
|
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
|
||||||
struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]);
|
|
||||||
void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
|
|
||||||
struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
|
|
||||||
|
|
||||||
/*******************/
|
/*******************/
|
||||||
/* Beacon Handling */
|
/* Beacon Handling */
|
||||||
@ -975,7 +953,6 @@ struct ath_softc {
|
|||||||
u8 sc_rxotherant; /* rx's on non-default antenna */
|
u8 sc_rxotherant; /* rx's on non-default antenna */
|
||||||
|
|
||||||
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
|
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
|
||||||
struct list_head node_list;
|
|
||||||
struct ath_ht_info sc_ht_info;
|
struct ath_ht_info sc_ht_info;
|
||||||
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
|
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
|
||||||
|
|
||||||
@ -1036,7 +1013,6 @@ struct ath_softc {
|
|||||||
spinlock_t sc_rxbuflock;
|
spinlock_t sc_rxbuflock;
|
||||||
spinlock_t sc_txbuflock;
|
spinlock_t sc_txbuflock;
|
||||||
spinlock_t sc_resetlock;
|
spinlock_t sc_resetlock;
|
||||||
spinlock_t node_lock;
|
|
||||||
|
|
||||||
/* LEDs */
|
/* LEDs */
|
||||||
struct ath_led radio_led;
|
struct ath_led radio_led;
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
#define ATH_PCI_VERSION "0.1"
|
#define ATH_PCI_VERSION "0.1"
|
||||||
|
|
||||||
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
|
|
||||||
|
|
||||||
static char *dev_info = "ath9k";
|
static char *dev_info = "ath9k";
|
||||||
|
|
||||||
MODULE_AUTHOR("Atheros Communications");
|
MODULE_AUTHOR("Atheros Communications");
|
||||||
@ -297,41 +295,6 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
|
|||||||
rx_status->flag |= RX_FLAG_TSFT;
|
rx_status->flag |= RX_FLAG_TSFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 parse_mpdudensity(u8 mpdudensity)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
|
|
||||||
* 0 for no restriction
|
|
||||||
* 1 for 1/4 us
|
|
||||||
* 2 for 1/2 us
|
|
||||||
* 3 for 1 us
|
|
||||||
* 4 for 2 us
|
|
||||||
* 5 for 4 us
|
|
||||||
* 6 for 8 us
|
|
||||||
* 7 for 16 us
|
|
||||||
*/
|
|
||||||
switch (mpdudensity) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
/* Our lower layer calculations limit our precision to
|
|
||||||
1 microsecond */
|
|
||||||
return 1;
|
|
||||||
case 4:
|
|
||||||
return 2;
|
|
||||||
case 5:
|
|
||||||
return 4;
|
|
||||||
case 6:
|
|
||||||
return 8;
|
|
||||||
case 7:
|
|
||||||
return 16;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ath9k_ht_conf(struct ath_softc *sc,
|
static void ath9k_ht_conf(struct ath_softc *sc,
|
||||||
struct ieee80211_bss_conf *bss_conf)
|
struct ieee80211_bss_conf *bss_conf)
|
||||||
{
|
{
|
||||||
@ -479,8 +442,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
|||||||
tx_info->status.rates[0].count = tx_status->retries + 1;
|
tx_info->status.rates[0].count = tx_status->retries + 1;
|
||||||
|
|
||||||
ieee80211_tx_status(hw, skb);
|
ieee80211_tx_status(hw, skb);
|
||||||
if (an)
|
|
||||||
ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _ath_rx_indicate(struct ath_softc *sc,
|
int _ath_rx_indicate(struct ath_softc *sc,
|
||||||
@ -518,10 +479,6 @@ int _ath_rx_indicate(struct ath_softc *sc,
|
|||||||
rx_status.flag |= RX_FLAG_DECRYPTED;
|
rx_status.flag |= RX_FLAG_DECRYPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
|
||||||
an = ath_node_find(sc, hdr->addr2);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (an) {
|
if (an) {
|
||||||
ath_rx_input(sc, an,
|
ath_rx_input(sc, an,
|
||||||
skb, status, &st);
|
skb, status, &st);
|
||||||
@ -913,11 +870,6 @@ static int ath_attach(u16 devid,
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* Init nodes */
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&sc->node_list);
|
|
||||||
spin_lock_init(&sc->node_lock);
|
|
||||||
|
|
||||||
/* get mac address from hardware and set in mac80211 */
|
/* get mac address from hardware and set in mac80211 */
|
||||||
|
|
||||||
SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
|
SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
|
||||||
@ -1404,50 +1356,22 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
|||||||
__func__, sc->rx_filter);
|
__func__, sc->rx_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only a single interface is currently supported,
|
||||||
|
so pass 0 as the interface id to ath_node_attach */
|
||||||
|
|
||||||
static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
enum sta_notify_cmd cmd,
|
enum sta_notify_cmd cmd,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = hw->priv;
|
struct ath_softc *sc = hw->priv;
|
||||||
struct ath_node *an;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sc->node_lock, flags);
|
|
||||||
an = ath_node_find(sc, sta->addr);
|
|
||||||
spin_unlock_irqrestore(&sc->node_lock, flags);
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case STA_NOTIFY_ADD:
|
case STA_NOTIFY_ADD:
|
||||||
spin_lock_irqsave(&sc->node_lock, flags);
|
ath_node_attach(sc, sta, 0);
|
||||||
if (!an) {
|
|
||||||
ath_node_attach(sc, sta->addr, 0);
|
|
||||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %pM\n",
|
|
||||||
__func__, sta->addr);
|
|
||||||
} else {
|
|
||||||
ath_node_get(sc, sta->addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: Is this right? Can the capabilities change? */
|
|
||||||
an = ath_node_find(sc, sta->addr);
|
|
||||||
an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
|
|
||||||
sta->ht_cap.ampdu_factor);
|
|
||||||
an->mpdudensity =
|
|
||||||
parse_mpdudensity(sta->ht_cap.ampdu_density);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sc->node_lock, flags);
|
|
||||||
break;
|
break;
|
||||||
case STA_NOTIFY_REMOVE:
|
case STA_NOTIFY_REMOVE:
|
||||||
if (!an)
|
ath_node_detach(sc, sta);
|
||||||
DPRINTF(sc, ATH_DBG_FATAL,
|
|
||||||
"%s: Removal of a non-existent node\n",
|
|
||||||
__func__);
|
|
||||||
else {
|
|
||||||
ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
|
|
||||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %pM\n",
|
|
||||||
__func__,
|
|
||||||
sta->addr);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1595,21 +1519,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case IEEE80211_AMPDU_RX_START:
|
case IEEE80211_AMPDU_RX_START:
|
||||||
ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
|
ret = ath_rx_aggr_start(sc, sta, tid, ssn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(sc, ATH_DBG_FATAL,
|
DPRINTF(sc, ATH_DBG_FATAL,
|
||||||
"%s: Unable to start RX aggregation\n",
|
"%s: Unable to start RX aggregation\n",
|
||||||
__func__);
|
__func__);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_RX_STOP:
|
case IEEE80211_AMPDU_RX_STOP:
|
||||||
ret = ath_rx_aggr_stop(sc, sta->addr, tid);
|
ret = ath_rx_aggr_stop(sc, sta, tid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(sc, ATH_DBG_FATAL,
|
DPRINTF(sc, ATH_DBG_FATAL,
|
||||||
"%s: Unable to stop RX aggregation\n",
|
"%s: Unable to stop RX aggregation\n",
|
||||||
__func__);
|
__func__);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
|
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(sc, ATH_DBG_FATAL,
|
DPRINTF(sc, ATH_DBG_FATAL,
|
||||||
"%s: Unable to start TX aggregation\n",
|
"%s: Unable to start TX aggregation\n",
|
||||||
@ -1618,7 +1542,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
|
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP:
|
case IEEE80211_AMPDU_TX_STOP:
|
||||||
ret = ath_tx_aggr_stop(sc, sta->addr, tid);
|
ret = ath_tx_aggr_stop(sc, sta, tid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(sc, ATH_DBG_FATAL,
|
DPRINTF(sc, ATH_DBG_FATAL,
|
||||||
"%s: Unable to stop TX aggregation\n",
|
"%s: Unable to stop TX aggregation\n",
|
||||||
|
@ -1867,9 +1867,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
|||||||
/* XXX: UGLY HACK!! */
|
/* XXX: UGLY HACK!! */
|
||||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
|
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
an = ath_node_find(sc, hdr->addr1);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (tx_info_priv == NULL)
|
if (tx_info_priv == NULL)
|
||||||
return;
|
return;
|
||||||
@ -1984,16 +1982,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
|||||||
qc = ieee80211_get_qos_ctl(hdr);
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
tid = qc[0] & 0xf;
|
tid = qc[0] & 0xf;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
an = ath_node_find(sc, hdr->addr1);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (!an) {
|
|
||||||
DPRINTF(sc, ATH_DBG_AGGR,
|
|
||||||
"%s: Node not found to "
|
|
||||||
"init/chk TX aggr\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chk = ath_tx_aggr_check(sc, an, tid);
|
chk = ath_tx_aggr_check(sc, an, tid);
|
||||||
if (chk == AGGR_REQUIRED) {
|
if (chk == AGGR_REQUIRED) {
|
||||||
|
@ -1095,7 +1095,7 @@ rx_next:
|
|||||||
/* Process ADDBA request in per-TID data structure */
|
/* Process ADDBA request in per-TID data structure */
|
||||||
|
|
||||||
int ath_rx_aggr_start(struct ath_softc *sc,
|
int ath_rx_aggr_start(struct ath_softc *sc,
|
||||||
const u8 *addr,
|
struct ieee80211_sta *sta,
|
||||||
u16 tid,
|
u16 tid,
|
||||||
u16 *ssn)
|
u16 *ssn)
|
||||||
{
|
{
|
||||||
@ -1105,17 +1105,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
|
|||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
u16 buffersize = 0;
|
u16 buffersize = 0;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
an = ath_node_find(sc, (u8 *) addr);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (!an) {
|
|
||||||
DPRINTF(sc, ATH_DBG_AGGR,
|
|
||||||
"%s: Node not found to initialize RX aggregation\n",
|
|
||||||
__func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sband = hw->wiphy->bands[hw->conf.channel->band];
|
sband = hw->wiphy->bands[hw->conf.channel->band];
|
||||||
buffersize = IEEE80211_MIN_AMPDU_BUF <<
|
buffersize = IEEE80211_MIN_AMPDU_BUF <<
|
||||||
sband->ht_cap.ampdu_factor; /* FIXME */
|
sband->ht_cap.ampdu_factor; /* FIXME */
|
||||||
@ -1172,21 +1162,9 @@ int ath_rx_aggr_start(struct ath_softc *sc,
|
|||||||
|
|
||||||
/* Process DELBA */
|
/* Process DELBA */
|
||||||
|
|
||||||
int ath_rx_aggr_stop(struct ath_softc *sc,
|
int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||||
const u8 *addr,
|
|
||||||
u16 tid)
|
|
||||||
{
|
{
|
||||||
struct ath_node *an;
|
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
|
||||||
an = ath_node_find(sc, (u8 *) addr);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (!an) {
|
|
||||||
DPRINTF(sc, ATH_DBG_AGGR,
|
|
||||||
"%s: RX aggr stop for non-existent node\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_rx_aggr_teardown(sc, an, tid);
|
ath_rx_aggr_teardown(sc, an, tid);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1194,8 +1172,7 @@ int ath_rx_aggr_stop(struct ath_softc *sc,
|
|||||||
|
|
||||||
/* Rx aggregation tear down */
|
/* Rx aggregation tear down */
|
||||||
|
|
||||||
void ath_rx_aggr_teardown(struct ath_softc *sc,
|
void ath_rx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
|
||||||
struct ath_node *an, u8 tid)
|
|
||||||
{
|
{
|
||||||
struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid];
|
struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid];
|
||||||
|
|
||||||
@ -1253,7 +1230,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
|
||||||
{
|
{
|
||||||
if (sc->sc_flags & SC_OP_RXAGGR) {
|
if (sc->sc_flags & SC_OP_RXAGGR) {
|
||||||
struct ath_arx_tid *rxtid;
|
struct ath_arx_tid *rxtid;
|
||||||
@ -1281,10 +1258,3 @@ void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup per-node receive state */
|
|
||||||
|
|
||||||
void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
|
|
||||||
{
|
|
||||||
ath_rx_node_cleanup(sc, an);
|
|
||||||
}
|
|
||||||
|
@ -214,15 +214,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
|||||||
rt = sc->sc_currates;
|
rt = sc->sc_currates;
|
||||||
BUG_ON(!rt);
|
BUG_ON(!rt);
|
||||||
|
|
||||||
/* Fill misc fields */
|
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
|
||||||
txctl->an = ath_node_get(sc, hdr->addr1);
|
|
||||||
/* create a temp node, if the node is not there already */
|
|
||||||
if (!txctl->an)
|
|
||||||
txctl->an = ath_node_attach(sc, hdr->addr1, 0);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (ieee80211_is_data_qos(fc)) {
|
if (ieee80211_is_data_qos(fc)) {
|
||||||
qc = ieee80211_get_qos_ctl(hdr);
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
txctl->tidno = qc[0] & 0xf;
|
txctl->tidno = qc[0] & 0xf;
|
||||||
@ -496,11 +487,9 @@ unlock:
|
|||||||
|
|
||||||
/* Compute the number of bad frames */
|
/* Compute the number of bad frames */
|
||||||
|
|
||||||
static int ath_tx_num_badfrms(struct ath_softc *sc,
|
static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
|
||||||
struct ath_buf *bf, int txok)
|
int txok)
|
||||||
{
|
{
|
||||||
struct ath_node *an = bf->bf_node;
|
|
||||||
int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
|
|
||||||
struct ath_buf *bf_last = bf->bf_lastbf;
|
struct ath_buf *bf_last = bf->bf_lastbf;
|
||||||
struct ath_desc *ds = bf_last->bf_desc;
|
struct ath_desc *ds = bf_last->bf_desc;
|
||||||
u16 seq_st = 0;
|
u16 seq_st = 0;
|
||||||
@ -509,7 +498,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc,
|
|||||||
int nbad = 0;
|
int nbad = 0;
|
||||||
int isaggr = 0;
|
int isaggr = 0;
|
||||||
|
|
||||||
if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
|
if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
isaggr = bf_isaggr(bf);
|
isaggr = bf_isaggr(bf);
|
||||||
@ -908,7 +897,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
|||||||
u16 seq_st = 0;
|
u16 seq_st = 0;
|
||||||
u32 ba[WME_BA_BMP_SIZE >> 5];
|
u32 ba[WME_BA_BMP_SIZE >> 5];
|
||||||
int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
|
int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
|
||||||
int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
|
|
||||||
|
|
||||||
isaggr = bf_isaggr(bf);
|
isaggr = bf_isaggr(bf);
|
||||||
if (isaggr) {
|
if (isaggr) {
|
||||||
@ -954,7 +942,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
|||||||
/* transmit completion */
|
/* transmit completion */
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (!tid->cleanup_inprogress && !isnodegone &&
|
if (!tid->cleanup_inprogress &&
|
||||||
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
|
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
|
||||||
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
|
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
|
||||||
ath_tx_set_retry(sc, bf);
|
ath_tx_set_retry(sc, bf);
|
||||||
@ -1083,15 +1071,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
|||||||
bf = bf_next;
|
bf = bf_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* node is already gone. no more assocication
|
|
||||||
* with the node. the node might have been freed
|
|
||||||
* any node acces can result in panic.note tid
|
|
||||||
* is part of the node.
|
|
||||||
*/
|
|
||||||
if (isnodegone)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tid->cleanup_inprogress) {
|
if (tid->cleanup_inprogress) {
|
||||||
/* check to see if we're done with cleaning the h/w queue */
|
/* check to see if we're done with cleaning the h/w queue */
|
||||||
spin_lock_bh(&txq->axq_lock);
|
spin_lock_bh(&txq->axq_lock);
|
||||||
@ -1795,8 +1774,8 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
|
|||||||
|
|
||||||
static void ath_tid_drain(struct ath_softc *sc,
|
static void ath_tid_drain(struct ath_softc *sc,
|
||||||
struct ath_txq *txq,
|
struct ath_txq *txq,
|
||||||
struct ath_atx_tid *tid,
|
struct ath_atx_tid *tid)
|
||||||
bool bh_flag)
|
|
||||||
{
|
{
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
struct list_head bf_head;
|
struct list_head bf_head;
|
||||||
@ -1817,18 +1796,12 @@ static void ath_tid_drain(struct ath_softc *sc,
|
|||||||
* do not indicate packets while holding txq spinlock.
|
* do not indicate packets while holding txq spinlock.
|
||||||
* unlock is intentional here
|
* unlock is intentional here
|
||||||
*/
|
*/
|
||||||
if (likely(bh_flag))
|
spin_unlock(&txq->axq_lock);
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
|
||||||
else
|
|
||||||
spin_unlock(&txq->axq_lock);
|
|
||||||
|
|
||||||
/* complete this sub-frame */
|
/* complete this sub-frame */
|
||||||
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
||||||
|
|
||||||
if (likely(bh_flag))
|
spin_lock(&txq->axq_lock);
|
||||||
spin_lock_bh(&txq->axq_lock);
|
|
||||||
else
|
|
||||||
spin_lock(&txq->axq_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1847,8 +1820,7 @@ static void ath_tid_drain(struct ath_softc *sc,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
||||||
struct ath_txq *txq,
|
struct ath_txq *txq)
|
||||||
bool bh_flag)
|
|
||||||
{
|
{
|
||||||
struct ath_atx_ac *ac, *ac_tmp;
|
struct ath_atx_ac *ac, *ac_tmp;
|
||||||
struct ath_atx_tid *tid, *tid_tmp;
|
struct ath_atx_tid *tid, *tid_tmp;
|
||||||
@ -1859,7 +1831,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
|||||||
list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
|
list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
|
||||||
list_del(&tid->list);
|
list_del(&tid->list);
|
||||||
tid->sched = false;
|
tid->sched = false;
|
||||||
ath_tid_drain(sc, txq, tid, bh_flag);
|
ath_tid_drain(sc, txq, tid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2294,8 +2266,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
|
|||||||
* or asynchrounsly once DMA is complete.
|
* or asynchrounsly once DMA is complete.
|
||||||
*/
|
*/
|
||||||
xmit_map_sg(sc, skb, &txctl);
|
xmit_map_sg(sc, skb, &txctl);
|
||||||
else
|
|
||||||
ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
|
|
||||||
|
|
||||||
/* failed packets will be dropped by the caller */
|
/* failed packets will be dropped by the caller */
|
||||||
return error;
|
return error;
|
||||||
@ -2374,8 +2344,7 @@ void ath_tx_draintxq(struct ath_softc *sc,
|
|||||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||||
if (!retry_tx) {
|
if (!retry_tx) {
|
||||||
spin_lock_bh(&txq->axq_lock);
|
spin_lock_bh(&txq->axq_lock);
|
||||||
ath_txq_drain_pending_buffers(sc, txq,
|
ath_txq_drain_pending_buffers(sc, txq);
|
||||||
ATH9K_BH_STATUS_CHANGE);
|
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
spin_unlock_bh(&txq->axq_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2441,24 +2410,13 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
|
|||||||
|
|
||||||
/* Start TX aggregation */
|
/* Start TX aggregation */
|
||||||
|
|
||||||
int ath_tx_aggr_start(struct ath_softc *sc,
|
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
const u8 *addr,
|
u16 tid, u16 *ssn)
|
||||||
u16 tid,
|
|
||||||
u16 *ssn)
|
|
||||||
{
|
{
|
||||||
struct ath_atx_tid *txtid;
|
struct ath_atx_tid *txtid;
|
||||||
struct ath_node *an;
|
struct ath_node *an;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
an = ath_node_find(sc, (u8 *) addr);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (!an) {
|
|
||||||
DPRINTF(sc, ATH_DBG_AGGR,
|
|
||||||
"%s: Node not found to initialize "
|
|
||||||
"TX aggregation\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||||
txtid = ATH_AN_2_TID(an, tid);
|
txtid = ATH_AN_2_TID(an, tid);
|
||||||
@ -2471,21 +2429,9 @@ int ath_tx_aggr_start(struct ath_softc *sc,
|
|||||||
|
|
||||||
/* Stop tx aggregation */
|
/* Stop tx aggregation */
|
||||||
|
|
||||||
int ath_tx_aggr_stop(struct ath_softc *sc,
|
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||||
const u8 *addr,
|
|
||||||
u16 tid)
|
|
||||||
{
|
{
|
||||||
struct ath_node *an;
|
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||||
|
|
||||||
spin_lock_bh(&sc->node_lock);
|
|
||||||
an = ath_node_find(sc, (u8 *) addr);
|
|
||||||
spin_unlock_bh(&sc->node_lock);
|
|
||||||
|
|
||||||
if (!an) {
|
|
||||||
DPRINTF(sc, ATH_DBG_AGGR,
|
|
||||||
"%s: TX aggr stop for non-existent node\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ath_tx_aggr_teardown(sc, an, tid);
|
ath_tx_aggr_teardown(sc, an, tid);
|
||||||
return 0;
|
return 0;
|
||||||
@ -2498,8 +2444,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc,
|
|||||||
* - Discard all retry frames from the s/w queue.
|
* - Discard all retry frames from the s/w queue.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ath_tx_aggr_teardown(struct ath_softc *sc,
|
void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
|
||||||
struct ath_node *an, u8 tid)
|
|
||||||
{
|
{
|
||||||
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
||||||
struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
|
struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
|
||||||
@ -2625,8 +2570,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
|||||||
struct ath_atx_ac *ac;
|
struct ath_atx_ac *ac;
|
||||||
int tidno, acno;
|
int tidno, acno;
|
||||||
|
|
||||||
an->maxampdu = ATH_AMPDU_LIMIT_DEFAULT;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Init per tid tx state
|
* Init per tid tx state
|
||||||
*/
|
*/
|
||||||
@ -2684,8 +2627,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
|||||||
|
|
||||||
/* Cleanupthe pending buffers for the node. */
|
/* Cleanupthe pending buffers for the node. */
|
||||||
|
|
||||||
void ath_tx_node_cleanup(struct ath_softc *sc,
|
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||||
struct ath_node *an, bool bh_flag)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ath_atx_ac *ac, *ac_tmp;
|
struct ath_atx_ac *ac, *ac_tmp;
|
||||||
@ -2695,10 +2637,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
|
|||||||
if (ATH_TXQ_SETUP(sc, i)) {
|
if (ATH_TXQ_SETUP(sc, i)) {
|
||||||
txq = &sc->sc_txq[i];
|
txq = &sc->sc_txq[i];
|
||||||
|
|
||||||
if (likely(bh_flag))
|
spin_lock(&txq->axq_lock);
|
||||||
spin_lock_bh(&txq->axq_lock);
|
|
||||||
else
|
|
||||||
spin_lock(&txq->axq_lock);
|
|
||||||
|
|
||||||
list_for_each_entry_safe(ac,
|
list_for_each_entry_safe(ac,
|
||||||
ac_tmp, &txq->axq_acq, list) {
|
ac_tmp, &txq->axq_acq, list) {
|
||||||
@ -2713,17 +2652,14 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
|
|||||||
tid_tmp, &ac->tid_q, list) {
|
tid_tmp, &ac->tid_q, list) {
|
||||||
list_del(&tid->list);
|
list_del(&tid->list);
|
||||||
tid->sched = false;
|
tid->sched = false;
|
||||||
ath_tid_drain(sc, txq, tid, bh_flag);
|
ath_tid_drain(sc, txq, tid);
|
||||||
tid->addba_exchangecomplete = 0;
|
tid->addba_exchangecomplete = 0;
|
||||||
tid->addba_exchangeattempts = 0;
|
tid->addba_exchangeattempts = 0;
|
||||||
tid->cleanup_inprogress = false;
|
tid->cleanup_inprogress = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(bh_flag))
|
spin_unlock(&txq->axq_lock);
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
|
||||||
else
|
|
||||||
spin_unlock(&txq->axq_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2794,7 +2730,6 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
|
|||||||
*/
|
*/
|
||||||
xmit_map_sg(sc, skb, &txctl);
|
xmit_map_sg(sc, skb, &txctl);
|
||||||
} else {
|
} else {
|
||||||
ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
|
|
||||||
DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
|
DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user