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

Commit 293dff78 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by Kalle Valo
Browse files

rt2x00: use txdone_nomatch on rt2800usb



If we do not match skb entry, provide tx status via nomatch procedure.

Currently in that case we do rt2x00lib_txdone_noinfo(TXDONE_NOINFO),
which actually assume that entry->skb was posted without retries and
provide rate saved in skb desc as successful. Patch changed that to
rate read from TX_STAT_FIFO, however still do not provide correct
number of retries.

On SoC/PCI devices we keep providing status via standard txdone
procedure, no change in those devices, though we should thing about it.

Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent ec80ad70
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -852,7 +852,8 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);

void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
			 bool match)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -860,8 +861,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
	struct txdone_entry_desc txdesc;
	u32 word;
	u16 mcs, real_mcs;
	int aggr, ampdu;
	int wcid;
	int aggr, ampdu, wcid, ack_req;

	/*
	 * Obtain the status about this packet.
@@ -875,6 +875,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
	real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
	aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
	wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
	ack_req	= rt2x00_get_field32(status, TX_STA_FIFO_TX_ACK_REQUIRED);

	/*
	 * If a frame was meant to be sent as a single non-aggregated MPDU
@@ -891,8 +892,12 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
	 * Hence, replace the requested rate with the real tx rate to not
	 * confuse the rate control algortihm by providing clearly wrong
	 * data.
	 *
	 * FIXME: if we do not find matching entry, we tell that frame was
	 * posted without any retries. We need to find a way to fix that
	 * and provide retry count.
 	 */
	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
	if (unlikely((aggr == 1 && ampdu == 0 && real_mcs != mcs)) || !match) {
		skbdesc->tx_rate_idx = real_mcs;
		mcs = real_mcs;
	}
@@ -900,6 +905,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
	if (aggr == 1 || ampdu == 1)
		__set_bit(TXDONE_AMPDU, &txdesc.flags);

	if (!ack_req)
		__set_bit(TXDONE_NO_ACK_REQ, &txdesc.flags);

	/*
	 * Ralink has a retry mechanism using a global fallback
	 * table. We setup this fallback table to try the immediate
@@ -931,8 +939,19 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
	if (txdesc.retry)
		__set_bit(TXDONE_FALLBACK, &txdesc.flags);

	if (!match) {
		/* RCU assures non-null sta will not be freed by mac80211. */
		rcu_read_lock();
		if (likely(wcid >= WCID_START && wcid <= WCID_END))
			skbdesc->sta = drv_data->wcid_to_sta[wcid - WCID_START];
		else
			skbdesc->sta = NULL;
		rt2x00lib_txdone_nomatch(entry, &txdesc);
		rcu_read_unlock();
	} else {
		rt2x00lib_txdone(entry, &txdesc);
	}
}
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);

static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+2 −1
Original line number Diff line number Diff line
@@ -191,7 +191,8 @@ void rt2800_write_tx_data(struct queue_entry *entry,
			  struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);

void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
			 bool match);

void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry);
+1 −1
Original line number Diff line number Diff line
@@ -239,7 +239,7 @@ static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
{
	if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
		rt2800_txdone_entry(entry, entry->status,
				    rt2800mmio_get_txwi(entry));
				    rt2800mmio_get_txwi(entry), true);
		return false;
	}

+7 −11
Original line number Diff line number Diff line
@@ -501,8 +501,7 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
 * TX control handlers
 */
static enum txdone_entry_desc_flags
rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
{
	__le32 *txwi;
	u32 word;
@@ -515,7 +514,7 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
	 * frame.
	 */
	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
		return TXDONE_FAILURE;
		return false;

	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
@@ -537,10 +536,10 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
		rt2x00_dbg(entry->queue->rt2x00dev,
			   "TX status report missed for queue %d entry %d\n",
			   entry->queue->qid, entry->entry_idx);
		return TXDONE_UNKNOWN;
		return false;
	}

	return TXDONE_SUCCESS;
	return true;
}

static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
@@ -549,7 +548,7 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
	struct queue_entry *entry;
	u32 reg;
	u8 qid;
	enum txdone_entry_desc_flags done_status;
	bool match;

	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
		/*
@@ -574,11 +573,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
			break;
		}

		done_status = rt2800usb_txdone_entry_check(entry, reg);
		if (likely(done_status == TXDONE_SUCCESS))
			rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
		else
			rt2x00lib_txdone_noinfo(entry, done_status);
		match = rt2800usb_txdone_entry_check(entry, reg);
		rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
	}
}