Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5aa9bf9 authored by Sujith's avatar Sujith Committed by John W. Linville
Browse files

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: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 17683c65
Loading
Loading
Loading
Loading
+45 −71
Original line number Diff line number Diff line
@@ -47,6 +47,41 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
		*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
 *
@@ -1321,7 +1356,7 @@ void ath_deinit(struct ath_softc *sc)
/* 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_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];
	ASSERT(avp != NULL);

	/* mac80211 sta_notify callback is from an IRQ context, so no sleep */
	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);
	an = (struct ath_node *)sta->drv_priv;

	/* set up per-node tx/rx state */
	ath_tx_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_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);
	an->an_flags |= ATH_NODE_CLEAN;
	ath_tx_node_cleanup(sc, an, bh_flag);
	ath_rx_node_cleanup(sc, an);

	ath_tx_node_cleanup(sc, an);

	ath_tx_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);
		}
	}
	an->an_flags = 0;
}

/**************/
+11 −35
Original line number Diff line number Diff line
@@ -373,7 +373,6 @@ void ath_flushrecv(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_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);
int ath_rx_init(struct ath_softc *sc, int nbufs);
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,
		     struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc,
			 struct ath_node *an, bool bh_flag);
void ath_tx_node_cleanup(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);
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 */
/**********************/

/* 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 ATH_AGGR_DELIM_SZ          4   /* delimiter size   */
#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_MAX          4096
#define IEEE80211_MIN_AMPDU_BUF    0x8
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13

/* return whether a bit at index _n in bitmap _bm is set
 * _sz is the size of the bitmap  */
@@ -638,15 +632,10 @@ struct ath_node_aggr {

/* driver-specific node state */
struct ath_node {
	struct list_head list;
	struct ath_softc *an_sc;
	atomic_t an_refcnt;
	struct ath_chainmask_sel an_chainmask_sel;
	struct ath_node_aggr an_aggr;
	u8 an_smmode; /* SM Power save mode */
	u8 an_flags;
	u8 an_addr[ETH_ALEN];

	u16 maxampdu;
	u8 mpdudensity;
};
@@ -659,28 +648,17 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
	struct ath_node *an, u8 tidno);
void ath_rx_aggr_teardown(struct ath_softc *sc,
	struct ath_node *an, u8 tidno);
int ath_rx_aggr_start(struct ath_softc *sc,
		      const u8 *addr,
		      u16 tid,
		      u16 *ssn);
int ath_rx_aggr_stop(struct ath_softc *sc,
		     const u8 *addr,
		     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);
int ath_rx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
		      u16 tid, u16 *ssn);
int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
		      u16 tid, u16 *ssn);
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_newassoc(struct ath_softc *sc,
	struct ath_node *node, int isnew, int isuapsd);
struct ath_node *ath_node_attach(struct ath_softc *sc,
	u8 addr[ETH_ALEN], int if_id);
void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
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);
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
		     int if_id);
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);

/*******************/
/* Beacon Handling */
@@ -975,7 +953,6 @@ struct ath_softc {
	u8 sc_rxotherant;		/* rx's on non-default antenna */

	struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
	struct list_head node_list;
	struct ath_ht_info sc_ht_info;
	enum ath9k_ht_extprotspacing sc_ht_extprotspacing;

@@ -1036,7 +1013,6 @@ struct ath_softc {
	spinlock_t sc_rxbuflock;
	spinlock_t sc_txbuflock;
	spinlock_t sc_resetlock;
	spinlock_t node_lock;

	/* LEDs */
	struct ath_led radio_led;
+9 −85
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@

#define ATH_PCI_VERSION "0.1"

#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR	13

static char *dev_info = "ath9k";

MODULE_AUTHOR("Atheros Communications");
@@ -297,41 +295,6 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
	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,
			  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;

	ieee80211_tx_status(hw, skb);
	if (an)
		ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
}

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;
	}

	spin_lock_bh(&sc->node_lock);
	an = ath_node_find(sc, hdr->addr2);
	spin_unlock_bh(&sc->node_lock);

	if (an) {
		ath_rx_input(sc, an,
			     skb, status, &st);
@@ -913,11 +870,6 @@ static int ath_attach(u16 devid,
	if (error != 0)
		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 */

	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);
}

/* 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,
			     struct ieee80211_vif *vif,
			     enum sta_notify_cmd cmd,
			     struct ieee80211_sta *sta)
{
	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) {
	case STA_NOTIFY_ADD:
		spin_lock_irqsave(&sc->node_lock, flags);
		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);
		ath_node_attach(sc, sta, 0);
		break;
	case STA_NOTIFY_REMOVE:
		if (!an)
			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);
		}
		ath_node_detach(sc, sta);
		break;
	default:
		break;
@@ -1595,21 +1519,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,

	switch (action) {
	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)
			DPRINTF(sc, ATH_DBG_FATAL,
				"%s: Unable to start RX aggregation\n",
				__func__);
		break;
	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)
			DPRINTF(sc, ATH_DBG_FATAL,
				"%s: Unable to stop RX aggregation\n",
				__func__);
		break;
	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)
			DPRINTF(sc, ATH_DBG_FATAL,
				"%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);
		break;
	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)
			DPRINTF(sc, ATH_DBG_FATAL,
				"%s: Unable to stop TX aggregation\n",
+2 −13
Original line number Diff line number Diff line
@@ -1867,9 +1867,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
	/* XXX: UGLY HACK!! */
	tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;

	spin_lock_bh(&sc->node_lock);
	an = ath_node_find(sc, hdr->addr1);
	spin_unlock_bh(&sc->node_lock);
	an = (struct ath_node *)sta->drv_priv;

	if (tx_info_priv == NULL)
		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);
			tid = qc[0] & 0xf;

			spin_lock_bh(&sc->node_lock);
			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;
			}
			an = (struct ath_node *)sta->drv_priv;

			chk = ath_tx_aggr_check(sc, an, tid);
			if (chk == AGGR_REQUIRED) {
+6 −36
Original line number Diff line number Diff line
@@ -1095,7 +1095,7 @@ rx_next:
/* Process ADDBA request in per-TID data structure */

int ath_rx_aggr_start(struct ath_softc *sc,
		      const u8 *addr,
		      struct ieee80211_sta *sta,
		      u16 tid,
		      u16 *ssn)
{
@@ -1105,17 +1105,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
	struct ieee80211_supported_band *sband;
	u16 buffersize = 0;

	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: Node not found to initialize RX aggregation\n",
			__func__);
		return -1;
	}

	an = (struct ath_node *)sta->drv_priv;
	sband = hw->wiphy->bands[hw->conf.channel->band];
	buffersize = IEEE80211_MIN_AMPDU_BUF <<
		sband->ht_cap.ampdu_factor; /* FIXME */
@@ -1172,21 +1162,9 @@ int ath_rx_aggr_start(struct ath_softc *sc,

/* Process DELBA */

int ath_rx_aggr_stop(struct ath_softc *sc,
		     const u8 *addr,
		     u16 tid)
int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
	struct ath_node *an;

	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;
	}
	struct ath_node *an = (struct ath_node *)sta->drv_priv;

	ath_rx_aggr_teardown(sc, an, tid);
	return 0;
@@ -1194,8 +1172,7 @@ int ath_rx_aggr_stop(struct ath_softc *sc,

/* Rx aggregation tear down */

void ath_rx_aggr_teardown(struct ath_softc *sc,
	struct ath_node *an, u8 tid)
void ath_rx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 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) {
		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);
}
Loading