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

Commit 315dd114 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville
Browse files

ath9k: fix getting tx duration for dynack



On AR9003, tx control and tx status are in separate descriptor rings.
Tx duration is extracted from the tx control descriptor data, which
ar9003_hw_proc_txdesc cannot access.

Fix getting the duration by adding a separate callback for it.

Acked-by: default avatarLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4d9f634b
Loading
Loading
Loading
Loading
+19 −7
Original line number Diff line number Diff line
@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
	ts->evm1 = ads->AR_TxEVM1;
	ts->evm2 = ads->AR_TxEVM2;

	status = ACCESS_ONCE(ads->ds_ctl4);
	ts->duration[0] = MS(status, AR_PacketDur0);
	ts->duration[1] = MS(status, AR_PacketDur1);
	status = ACCESS_ONCE(ads->ds_ctl5);
	ts->duration[2] = MS(status, AR_PacketDur2);
	ts->duration[3] = MS(status, AR_PacketDur3);

	return 0;
}

static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
{
	struct ar5416_desc *ads = AR5416DESC(ds);

	switch (index) {
	case 0:
		return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0);
	case 1:
		return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1);
	case 2:
		return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2);
	case 3:
		return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3);
	default:
		return -1;
	}
}

void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
			  u32 size, u32 flags)
{
@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
	ops->get_isr = ar9002_hw_get_isr;
	ops->set_txdesc = ar9002_set_txdesc;
	ops->proc_txdesc = ar9002_hw_proc_txdesc;
	ops->get_duration = ar9002_hw_get_duration;
}
+19 −9
Original line number Diff line number Diff line
@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
				 struct ath_tx_status *ts)
{
	struct ar9003_txs *ads;
	struct ar9003_txc *adc;
	u32 status;

	ads = &ah->ts_ring[ah->ts_tail];
	adc = (struct ar9003_txc *)ads;

	status = ACCESS_ONCE(ads->status8);
	if ((status & AR_TxDone) == 0)
@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);

	status = ACCESS_ONCE(adc->ctl15);
	ts->duration[0] = MS(status, AR_PacketDur0);
	ts->duration[1] = MS(status, AR_PacketDur1);
	status = ACCESS_ONCE(adc->ctl16);
	ts->duration[2] = MS(status, AR_PacketDur2);
	ts->duration[3] = MS(status, AR_PacketDur3);

	memset(ads, 0, sizeof(*ads));

	return 0;
}

static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
{
	const struct ar9003_txc *adc = ds;

	switch (index) {
	case 0:
		return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0);
	case 1:
		return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1);
	case 2:
		return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2);
	case 3:
		return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3);
	default:
		return 0;
	}
}

void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{
	struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
	ops->get_isr = ar9003_hw_get_isr;
	ops->set_txdesc = ar9003_set_txdesc;
	ops->proc_txdesc = ar9003_hw_proc_txdesc;
	ops->get_duration = ar9003_hw_get_duration;
}

void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
+1 −1
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
	ridx = ts->ts_rateindex;

	da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
	da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex];
	da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration;
	ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
	ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);

+6 −0
Original line number Diff line number Diff line
@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
	return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
}

static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds,
					int index)
{
	return ath9k_hw_ops(ah)->get_duration(ah, ds, index);
}

static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
		struct ath_hw_antcomb_conf *antconf)
{
+1 −0
Original line number Diff line number Diff line
@@ -691,6 +691,7 @@ struct ath_hw_ops {
			   struct ath_tx_info *i);
	int (*proc_txdesc)(struct ath_hw *ah, void *ds,
			   struct ath_tx_status *ts);
	int (*get_duration)(struct ath_hw *ah, const void *ds, int index);
	void (*antdiv_comb_conf_get)(struct ath_hw *ah,
			struct ath_hw_antcomb_conf *antconf);
	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
Loading