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

Commit e022edbd authored by Jouni Malinen's avatar Jouni Malinen Committed by John W. Linville
Browse files

ath9k: Use mac80211 for multicast power save buffering



Replace the internal ath9k implementation of multicast/broadcast frame
power save buffering (AP mode) in ath9k with use of mac80211
ieee80211_get_buffered_bc() mechanism. This removes quite a bit of
duplicated functionality and simplifies the driver part.

Signed-off-by: default avatarJouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 87e8b64e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ struct ath_desc {
#define ATH9K_TXDESC_EXT_AND_CTL	0x0080
#define ATH9K_TXDESC_VMF		0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 	0x0200
#define ATH9K_TXDESC_CAB		0x0400

#define ATH9K_RXDESC_INTREQ		0x0020

+7 −68
Original line number Diff line number Diff line
@@ -140,56 +140,6 @@ static void ath_beacon_setup(struct ath_softc *sc,
		ctsrate, ctsduration, series, 4, 0);
}

/* Move everything from the vap's mcast queue to the hardware cab queue.
 * Caller must hold mcasq lock and cabq lock
 * XXX MORE_DATA bit?
 */
static void empty_mcastq_into_cabq(struct ath_hal *ah,
	struct ath_txq *mcastq, struct ath_txq *cabq)
{
	struct ath_buf *bfmcast;

	BUG_ON(list_empty(&mcastq->axq_q));

	bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list);

	/* link the descriptors */
	if (!cabq->axq_link)
		ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr);
	else
		*cabq->axq_link = bfmcast->bf_daddr;

	/* append the private vap mcast list to  the cabq */

	cabq->axq_depth	+= mcastq->axq_depth;
	cabq->axq_totalqueued += mcastq->axq_totalqueued;
	cabq->axq_linkbuf = mcastq->axq_linkbuf;
	cabq->axq_link = mcastq->axq_link;
	list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q);
	mcastq->axq_depth = 0;
	mcastq->axq_totalqueued = 0;
	mcastq->axq_linkbuf = NULL;
	mcastq->axq_link = NULL;
}

/* TODO: use ieee80211_get_buffered_bc() to fetch power saved mcast frames */
/* This is only run at DTIM. We move everything from the vap's mcast queue
 * to the hardware cab queue. Caller must hold the mcastq lock. */
static void trigger_mcastq(struct ath_hal *ah,
	struct ath_txq *mcastq, struct ath_txq *cabq)
{
	spin_lock_bh(&cabq->axq_lock);

	if (!list_empty(&mcastq->axq_q))
		empty_mcastq_into_cabq(ah, mcastq, cabq);

	/* cabq is gated by beacon so it is safe to start here */
	if (!list_empty(&cabq->axq_q))
		ath9k_hw_txstart(ah, cabq->axq_qnum);

	spin_unlock_bh(&cabq->axq_lock);
}

/*
 *  Generate beacon frame and queue cab data for a vap.
 *
@@ -200,19 +150,14 @@ static void trigger_mcastq(struct ath_hal *ah,
*/
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
{
	struct ath_hal *ah = sc->sc_ah;
	struct ath_buf *bf;
	struct ath_vap *avp;
	struct sk_buff *skb;
	int cabq_depth;
	int mcastq_depth;
	int is_beacon_dtim = 0;
	struct ath_txq *cabq;
	struct ath_txq *mcastq;
	struct ieee80211_tx_info *info;
	avp = sc->sc_vaps[if_id];

	mcastq = &avp->av_mcastq;
	cabq = sc->sc_cabq;

	ASSERT(avp);
@@ -250,11 +195,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
			       skb_end_pointer(skb) - skb->head,
			       PCI_DMA_TODEVICE);

	/* TODO: convert to use ieee80211_get_buffered_bc() */
	/* XXX: spin_lock_bh should not be used here, but sparse bitches
	 * otherwise. We should fix sparse :) */
	spin_lock_bh(&mcastq->axq_lock);
	mcastq_depth = avp->av_mcastq.axq_depth;
	skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);

	/*
	 * if the CABQ traffic from previous DTIM is pending and the current
@@ -268,10 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
	cabq_depth = cabq->axq_depth;
	spin_unlock_bh(&cabq->axq_lock);

	if (avp->av_boff.bo_tim)
		is_beacon_dtim = avp->av_boff.bo_tim[4] & 1;

	if (mcastq_depth && is_beacon_dtim && cabq_depth) {
	if (skb && cabq_depth) {
		/*
		 * Unlock the cabq lock as ath_tx_draintxq acquires
		 * the lock again which is a common function and that
@@ -291,10 +229,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
	 * Enable the CAB queue before the beacon queue to
	 * insure cab frames are triggered by this beacon.
	 */
	if (is_beacon_dtim)
		trigger_mcastq(ah, mcastq, cabq);
	while (skb) {
		ath_tx_cabq(sc, skb);
		skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
	}

	spin_unlock_bh(&mcastq->axq_lock);
	return bf;
}

@@ -426,7 +365,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
	 * NB: the beacon data buffer must be 32-bit aligned;
	 * we assume the wbuf routines will return us something
	 * with this alignment (perhaps should assert).
	 * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and
	 * FIXME: Fill avp->av_btxctl.txpower and
	 * avp->av_btxctl.shortPreamble
	 */
	skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+0 −6
Original line number Diff line number Diff line
@@ -533,9 +533,6 @@ int ath_vap_attach(struct ath_softc *sc,
	/* Set the VAP opmode */
	avp->av_opmode = opmode;
	avp->av_bslot = -1;
	INIT_LIST_HEAD(&avp->av_mcastq.axq_q);
	INIT_LIST_HEAD(&avp->av_mcastq.axq_acq);
	spin_lock_init(&avp->av_mcastq.axq_lock);

	ath9k_hw_set_tsfadjust(sc->sc_ah, 1);

@@ -575,9 +572,6 @@ int ath_vap_detach(struct ath_softc *sc, int if_id)
	ath_stoprecv(sc);	/* stop recv side */
	ath_flushrecv(sc);	/* flush recv queue */

	/* Reclaim any pending mcast bufs on the vap. */
	ath_tx_draintxq(sc, &avp->av_mcastq, false);

	kfree(avp);
	sc->sc_vaps[if_id] = NULL;
	sc->sc_nvaps--;
+1 −8
Original line number Diff line number Diff line
@@ -568,6 +568,7 @@ u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
		     struct ath_xmit_status *tx_status, struct ath_node *an);
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);

/**********************/
/* Node / Aggregation */
@@ -713,12 +714,6 @@ struct ath_beacon_config {
	} u; /* last received beacon/probe response timestamp of this BSS. */
};

/* offsets in a beacon frame for
 * quick acess of beacon content by low-level driver */
struct ath_beacon_offset {
	u8 *bo_tim;	/* start of atim/dtim */
};

void ath9k_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, int if_id);
int ath_beaconq_setup(struct ath_hal *ah);
@@ -755,10 +750,8 @@ struct ath_vap {
	struct ieee80211_vif *av_if_data;
	enum ath9k_opmode av_opmode;	/* VAP operational mode */
	struct ath_buf *av_bcbuf;	/* beacon buffer */
	struct ath_beacon_offset av_boff; /* dynamic update state */
	struct ath_tx_control av_btxctl;  /* txctl information for beacon */
	int av_bslot;			/* beacon slot index */
	struct ath_txq av_mcastq;	/* multicast transmit queue */
	struct ath_vap_config av_config;/* vap configuration parameters*/
	struct ath_rate_node *rc_node;
};
+1 −0
Original line number Diff line number Diff line
@@ -1362,6 +1362,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	}

	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
		IEEE80211_HW_SIGNAL_DBM |
		IEEE80211_HW_NOISE_DBM;

Loading