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

Commit dba5dc1a authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville
Browse files

rt2x00: Introduce extra queue entry sanity flag



Add a queue entry flag ENTRY_DATA_STATUS_PENDING,
which can be used to indicate a queue entry has
returned from the hardware and is waiting for
status processing. Using this flag we can add
some extra sanity checks to prevent queue corruption.

Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Acked-by: default avatarHelmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 64e7d723
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -235,6 +235,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);

void rt2x00lib_dmadone(struct queue_entry *entry)
{
	set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
}
+5 −1
Original line number Diff line number Diff line
@@ -340,12 +340,16 @@ struct txentry_desc {
 * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
 *	while transfering the data to the hardware. No TX status report will
 *	be expected from the hardware.
 * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
 *	returned. It is now waiting for the status reporting before the
 *	entry can be reused again.
 */
enum queue_entry_flags {
	ENTRY_BCN_ASSIGNED,
	ENTRY_OWNER_DEVICE_DATA,
	ENTRY_DATA_PENDING,
	ENTRY_DATA_IO_FAILED
	ENTRY_DATA_IO_FAILED,
	ENTRY_DATA_STATUS_PENDING,
};

/**
+8 −4
Original line number Diff line number Diff line
@@ -195,7 +195,8 @@ static void rt2x00usb_work_txdone(struct work_struct *work)
		while (!rt2x00queue_empty(queue)) {
			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);

			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
			    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
				break;

			rt2x00usb_work_txdone_entry(entry);
@@ -237,7 +238,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
	u32 length;
	int status;

	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
		return;

	/*
@@ -275,7 +277,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)
	while (!rt2x00queue_empty(rt2x00dev->rx)) {
		entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);

		if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
		if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
		    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
			break;

		/*
@@ -327,7 +330,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
	int status;

	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
		return;

	rt2x00lib_dmastart(entry);