Initial commit
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
From f483039cf51acf30494cd754194562c22cf98764 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Wed, 22 Aug 2018 13:41:26 +0300
|
||||
Subject: [PATCH 01/28] rt2x00: use simple_read_from_buffer()
|
||||
|
||||
The problem with this copy_to_user() calls is that they don't ensure
|
||||
that "size" is less than the "length" which the user provided.
|
||||
|
||||
Obviously, this is debugfs and "size" is normally going to be very small
|
||||
so it probably doesn't matter, but this is the correct thing to do.
|
||||
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2x00debug.c | 18 +++---------------
|
||||
1 file changed, 3 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
@@ -464,11 +464,7 @@ static ssize_t rt2x00debug_read_##__name
|
||||
\
|
||||
size = sprintf(line, __format, value); \
|
||||
\
|
||||
- if (copy_to_user(buf, line, size)) \
|
||||
- return -EFAULT; \
|
||||
- \
|
||||
- *offset += size; \
|
||||
- return size; \
|
||||
+ return simple_read_from_buffer(buf, length, offset, line, size); \
|
||||
}
|
||||
|
||||
#define RT2X00DEBUGFS_OPS_WRITE(__name, __type) \
|
||||
@@ -545,11 +541,7 @@ static ssize_t rt2x00debug_read_dev_flag
|
||||
|
||||
size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
|
||||
|
||||
- if (copy_to_user(buf, line, size))
|
||||
- return -EFAULT;
|
||||
-
|
||||
- *offset += size;
|
||||
- return size;
|
||||
+ return simple_read_from_buffer(buf, length, offset, line, size);
|
||||
}
|
||||
|
||||
static const struct file_operations rt2x00debug_fop_dev_flags = {
|
||||
@@ -574,11 +566,7 @@ static ssize_t rt2x00debug_read_cap_flag
|
||||
|
||||
size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
|
||||
|
||||
- if (copy_to_user(buf, line, size))
|
||||
- return -EFAULT;
|
||||
-
|
||||
- *offset += size;
|
||||
- return size;
|
||||
+ return simple_read_from_buffer(buf, length, offset, line, size);
|
||||
}
|
||||
|
||||
static const struct file_operations rt2x00debug_fop_cap_flags = {
|
||||
@@ -0,0 +1,357 @@
|
||||
From 5c656c71b1bf5611ce8262bab338104e04d10b8d Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 26 Sep 2018 12:24:53 +0200
|
||||
Subject: [PATCH 02/28] rt2800: move usb specific txdone/txstatus routines to
|
||||
rt2800lib
|
||||
|
||||
In order to reuse usb txdone/txstatus routines for mmio, move them
|
||||
to common rt2800lib.c file.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 138 +++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 3 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 143 +-----------------
|
||||
3 files changed, 145 insertions(+), 139 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -957,6 +957,47 @@ static void rt2800_rate_from_status(stru
|
||||
skbdesc->tx_rate_flags = flags;
|
||||
}
|
||||
|
||||
+static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
|
||||
+{
|
||||
+ __le32 *txwi;
|
||||
+ u32 word;
|
||||
+ int wcid, ack, pid;
|
||||
+ int tx_wcid, tx_ack, tx_pid, is_agg;
|
||||
+
|
||||
+ /*
|
||||
+ * This frames has returned with an IO error,
|
||||
+ * so the status report is not intended for this
|
||||
+ * frame.
|
||||
+ */
|
||||
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
|
||||
+ return false;
|
||||
+
|
||||
+ wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
|
||||
+ ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
|
||||
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
|
||||
+ is_agg = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
|
||||
+
|
||||
+ /*
|
||||
+ * Validate if this TX status report is intended for
|
||||
+ * this entry by comparing the WCID/ACK/PID fields.
|
||||
+ */
|
||||
+ txwi = rt2800_drv_get_txwi(entry);
|
||||
+
|
||||
+ word = rt2x00_desc_read(txwi, 1);
|
||||
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
|
||||
+ tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
|
||||
+ tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
|
||||
+
|
||||
+ if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
|
||||
+ rt2x00_dbg(entry->queue->rt2x00dev,
|
||||
+ "TX status report missed for queue %d entry %d\n",
|
||||
+ entry->queue->qid, entry->entry_idx);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
|
||||
bool match)
|
||||
{
|
||||
@@ -1059,6 +1100,103 @@ void rt2800_txdone_entry(struct queue_en
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
|
||||
|
||||
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct data_queue *queue;
|
||||
+ struct queue_entry *entry;
|
||||
+ u32 reg;
|
||||
+ u8 qid;
|
||||
+ bool match;
|
||||
+
|
||||
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
|
||||
+ /*
|
||||
+ * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
|
||||
+ * guaranteed to be one of the TX QIDs .
|
||||
+ */
|
||||
+ qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
|
||||
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
|
||||
+
|
||||
+ if (unlikely(rt2x00queue_empty(queue))) {
|
||||
+ rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
|
||||
+ qid);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
+
|
||||
+ if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
+ !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
|
||||
+ rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
|
||||
+ entry->entry_idx, qid);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ match = rt2800_txdone_entry_check(entry, reg);
|
||||
+ rt2800_txdone_entry(entry, reg, rt2800_drv_get_txwi(entry), match);
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_txdone);
|
||||
+
|
||||
+static inline bool rt2800_entry_txstatus_timeout(struct queue_entry *entry)
|
||||
+{
|
||||
+ bool tout;
|
||||
+
|
||||
+ if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
+ return false;
|
||||
+
|
||||
+ tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
|
||||
+ if (unlikely(tout))
|
||||
+ rt2x00_dbg(entry->queue->rt2x00dev,
|
||||
+ "TX status timeout for entry %d in queue %d\n",
|
||||
+ entry->entry_idx, entry->queue->qid);
|
||||
+ return tout;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct data_queue *queue;
|
||||
+ struct queue_entry *entry;
|
||||
+
|
||||
+ tx_queue_for_each(rt2x00dev, queue) {
|
||||
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
+ if (rt2800_entry_txstatus_timeout(entry))
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
|
||||
+
|
||||
+void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct data_queue *queue;
|
||||
+ struct queue_entry *entry;
|
||||
+
|
||||
+ /*
|
||||
+ * Process any trailing TX status reports for IO failures,
|
||||
+ * we loop until we find the first non-IO error entry. This
|
||||
+ * can either be a frame which is free, is being uploaded,
|
||||
+ * or has completed the upload but didn't have an entry
|
||||
+ * in the TX_STAT_FIFO register yet.
|
||||
+ */
|
||||
+ tx_queue_for_each(rt2x00dev, queue) {
|
||||
+ while (!rt2x00queue_empty(queue)) {
|
||||
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
+
|
||||
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
+ !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
+ break;
|
||||
+
|
||||
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
|
||||
+ rt2800_entry_txstatus_timeout(entry))
|
||||
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
|
||||
+
|
||||
static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int index)
|
||||
{
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -195,6 +195,9 @@ void rt2800_process_rxwi(struct queue_en
|
||||
|
||||
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
|
||||
bool match);
|
||||
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
|
||||
+bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
|
||||
void rt2800_clear_beacon(struct queue_entry *entry);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -116,35 +116,6 @@ static bool rt2800usb_txstatus_pending(s
|
||||
return false;
|
||||
}
|
||||
|
||||
-static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
|
||||
-{
|
||||
- bool tout;
|
||||
-
|
||||
- if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
- return false;
|
||||
-
|
||||
- tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
|
||||
- if (unlikely(tout))
|
||||
- rt2x00_dbg(entry->queue->rt2x00dev,
|
||||
- "TX status timeout for entry %d in queue %d\n",
|
||||
- entry->entry_idx, entry->queue->qid);
|
||||
- return tout;
|
||||
-
|
||||
-}
|
||||
-
|
||||
-static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- struct data_queue *queue;
|
||||
- struct queue_entry *entry;
|
||||
-
|
||||
- tx_queue_for_each(rt2x00dev, queue) {
|
||||
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
- if (rt2800usb_entry_txstatus_timeout(entry))
|
||||
- return true;
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
#define TXSTATUS_READ_INTERVAL 1000000
|
||||
|
||||
static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -171,7 +142,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
|
||||
}
|
||||
|
||||
/* Check if there is any entry that timedout waiting on TX status */
|
||||
- if (rt2800usb_txstatus_timeout(rt2x00dev))
|
||||
+ if (rt2800_txstatus_timeout(rt2x00dev))
|
||||
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
|
||||
|
||||
if (rt2800usb_txstatus_pending(rt2x00dev)) {
|
||||
@@ -501,123 +472,17 @@ static int rt2800usb_get_tx_data_len(str
|
||||
/*
|
||||
* TX control handlers
|
||||
*/
|
||||
-static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
|
||||
-{
|
||||
- __le32 *txwi;
|
||||
- u32 word;
|
||||
- int wcid, ack, pid;
|
||||
- int tx_wcid, tx_ack, tx_pid, is_agg;
|
||||
-
|
||||
- /*
|
||||
- * This frames has returned with an IO error,
|
||||
- * so the status report is not intended for this
|
||||
- * frame.
|
||||
- */
|
||||
- if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
|
||||
- return false;
|
||||
-
|
||||
- wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
|
||||
- ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
|
||||
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
|
||||
- is_agg = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
|
||||
-
|
||||
- /*
|
||||
- * Validate if this TX status report is intended for
|
||||
- * this entry by comparing the WCID/ACK/PID fields.
|
||||
- */
|
||||
- txwi = rt2800usb_get_txwi(entry);
|
||||
-
|
||||
- word = rt2x00_desc_read(txwi, 1);
|
||||
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
|
||||
- tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
|
||||
- tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
|
||||
-
|
||||
- if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
|
||||
- rt2x00_dbg(entry->queue->rt2x00dev,
|
||||
- "TX status report missed for queue %d entry %d\n",
|
||||
- entry->queue->qid, entry->entry_idx);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- struct data_queue *queue;
|
||||
- struct queue_entry *entry;
|
||||
- u32 reg;
|
||||
- u8 qid;
|
||||
- bool match;
|
||||
-
|
||||
- while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
|
||||
- /*
|
||||
- * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
|
||||
- * guaranteed to be one of the TX QIDs .
|
||||
- */
|
||||
- qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
|
||||
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
|
||||
-
|
||||
- if (unlikely(rt2x00queue_empty(queue))) {
|
||||
- rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
|
||||
- qid);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
-
|
||||
- if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
|
||||
- rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
|
||||
- entry->entry_idx, qid);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- match = rt2800usb_txdone_entry_check(entry, reg);
|
||||
- rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry), match);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- struct data_queue *queue;
|
||||
- struct queue_entry *entry;
|
||||
-
|
||||
- /*
|
||||
- * Process any trailing TX status reports for IO failures,
|
||||
- * we loop until we find the first non-IO error entry. This
|
||||
- * can either be a frame which is free, is being uploaded,
|
||||
- * or has completed the upload but didn't have an entry
|
||||
- * in the TX_STAT_FIFO register yet.
|
||||
- */
|
||||
- tx_queue_for_each(rt2x00dev, queue) {
|
||||
- while (!rt2x00queue_empty(queue)) {
|
||||
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
-
|
||||
- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
- break;
|
||||
-
|
||||
- if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
|
||||
- rt2800usb_entry_txstatus_timeout(entry))
|
||||
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
|
||||
- else
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static void rt2800usb_work_txdone(struct work_struct *work)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev =
|
||||
container_of(work, struct rt2x00_dev, txdone_work);
|
||||
|
||||
while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
|
||||
- rt2800usb_txstatus_timeout(rt2x00dev)) {
|
||||
+ rt2800_txstatus_timeout(rt2x00dev)) {
|
||||
|
||||
- rt2800usb_txdone(rt2x00dev);
|
||||
+ rt2800_txdone(rt2x00dev);
|
||||
|
||||
- rt2800usb_txdone_nostatus(rt2x00dev);
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
|
||||
/*
|
||||
* The hw may delay sending the packet after DMA complete
|
||||
@@ -0,0 +1,244 @@
|
||||
From 0b0d556e0ebb6c966bc993e21a22a156812d8fdf Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 26 Sep 2018 12:24:54 +0200
|
||||
Subject: [PATCH 03/28] rt2800mmio: use txdone/txstatus routines from lib
|
||||
|
||||
Use usb txdone/txstatus routines (now in rt2800libc) for mmio devices.
|
||||
|
||||
Note this also change how we handle INT_SOURCE_CSR_TX_FIFO_STATUS
|
||||
interrupt. Now it is disabled since IRQ routine till end of the txstatus
|
||||
tasklet (the same behaviour like others interrupts). Reason to do not
|
||||
disable this interrupt was not to miss any tx status from 16 entries
|
||||
FIFO register. Now, since we check for tx status timeout, we can
|
||||
allow to miss some tx statuses. However this will be improved in further
|
||||
patch where I also implement read status FIFO register in the tasklet.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 180 +-----------------
|
||||
.../net/wireless/ralink/rt2x00/rt2x00queue.c | 1 +
|
||||
2 files changed, 9 insertions(+), 172 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -175,161 +175,6 @@ static void rt2800mmio_wakeup(struct rt2
|
||||
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
|
||||
}
|
||||
|
||||
-static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
|
||||
-{
|
||||
- __le32 *txwi;
|
||||
- u32 word;
|
||||
- int wcid, tx_wcid;
|
||||
-
|
||||
- wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
|
||||
-
|
||||
- txwi = rt2800_drv_get_txwi(entry);
|
||||
- word = rt2x00_desc_read(txwi, 1);
|
||||
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
|
||||
-
|
||||
- return (tx_wcid == wcid);
|
||||
-}
|
||||
-
|
||||
-static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
|
||||
-{
|
||||
- u32 status = *(u32 *)data;
|
||||
-
|
||||
- /*
|
||||
- * rt2800pci hardware might reorder frames when exchanging traffic
|
||||
- * with multiple BA enabled STAs.
|
||||
- *
|
||||
- * For example, a tx queue
|
||||
- * [ STA1 | STA2 | STA1 | STA2 ]
|
||||
- * can result in tx status reports
|
||||
- * [ STA1 | STA1 | STA2 | STA2 ]
|
||||
- * when the hw decides to aggregate the frames for STA1 into one AMPDU.
|
||||
- *
|
||||
- * To mitigate this effect, associate the tx status to the first frame
|
||||
- * in the tx queue with a matching wcid.
|
||||
- */
|
||||
- if (rt2800mmio_txdone_entry_check(entry, status) &&
|
||||
- !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
|
||||
- /*
|
||||
- * Got a matching frame, associate the tx status with
|
||||
- * the frame
|
||||
- */
|
||||
- entry->status = status;
|
||||
- set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- /* Check the next frame */
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
-static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
|
||||
-{
|
||||
- u32 status = *(u32 *)data;
|
||||
-
|
||||
- /*
|
||||
- * Find the first frame without tx status and assign this status to it
|
||||
- * regardless if it matches or not.
|
||||
- */
|
||||
- if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
|
||||
- /*
|
||||
- * Got a matching frame, associate the tx status with
|
||||
- * the frame
|
||||
- */
|
||||
- entry->status = status;
|
||||
- set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- /* Check the next frame */
|
||||
- return false;
|
||||
-}
|
||||
-static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
|
||||
- void *data)
|
||||
-{
|
||||
- if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
|
||||
- rt2800_txdone_entry(entry, entry->status,
|
||||
- rt2800mmio_get_txwi(entry), true);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- /* No more frames to release */
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- struct data_queue *queue;
|
||||
- u32 status;
|
||||
- u8 qid;
|
||||
- int max_tx_done = 16;
|
||||
-
|
||||
- while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
|
||||
- qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
|
||||
- if (unlikely(qid >= QID_RX)) {
|
||||
- /*
|
||||
- * Unknown queue, this shouldn't happen. Just drop
|
||||
- * this tx status.
|
||||
- */
|
||||
- rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
|
||||
- qid);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
|
||||
- if (unlikely(queue == NULL)) {
|
||||
- /*
|
||||
- * The queue is NULL, this shouldn't happen. Stop
|
||||
- * processing here and drop the tx status
|
||||
- */
|
||||
- rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
|
||||
- qid);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (unlikely(rt2x00queue_empty(queue))) {
|
||||
- /*
|
||||
- * The queue is empty. Stop processing here
|
||||
- * and drop the tx status.
|
||||
- */
|
||||
- rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
|
||||
- qid);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Let's associate this tx status with the first
|
||||
- * matching frame.
|
||||
- */
|
||||
- if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
|
||||
- Q_INDEX, &status,
|
||||
- rt2800mmio_txdone_find_entry)) {
|
||||
- /*
|
||||
- * We cannot match the tx status to any frame, so just
|
||||
- * use the first one.
|
||||
- */
|
||||
- if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
|
||||
- Q_INDEX, &status,
|
||||
- rt2800mmio_txdone_match_first)) {
|
||||
- rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
|
||||
- qid);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Release all frames with a valid tx status.
|
||||
- */
|
||||
- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
|
||||
- Q_INDEX, NULL,
|
||||
- rt2800mmio_txdone_release_entries);
|
||||
-
|
||||
- if (--max_tx_done == 0)
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return !max_tx_done;
|
||||
-}
|
||||
-
|
||||
static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
|
||||
struct rt2x00_field32 irq_field)
|
||||
{
|
||||
@@ -349,14 +194,14 @@ static inline void rt2800mmio_enable_int
|
||||
void rt2800mmio_txstatus_tasklet(unsigned long data)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
|
||||
- if (rt2800mmio_txdone(rt2x00dev))
|
||||
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
|
||||
- /*
|
||||
- * No need to enable the tx status interrupt here as we always
|
||||
- * leave it enabled to minimize the possibility of a tx status
|
||||
- * register overflow. See comment in interrupt handler.
|
||||
- */
|
||||
+ rt2800_txdone(rt2x00dev);
|
||||
+
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
+
|
||||
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
+ rt2800mmio_enable_interrupt(rt2x00dev,
|
||||
+ INT_SOURCE_CSR_TX_FIFO_STATUS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
|
||||
|
||||
@@ -440,10 +285,6 @@ static void rt2800mmio_txstatus_interrup
|
||||
* because we can schedule the tasklet multiple times (when the
|
||||
* interrupt fires again during tx status processing).
|
||||
*
|
||||
- * Furthermore we don't disable the TX_FIFO_STATUS
|
||||
- * interrupt here but leave it enabled so that the TX_STA_FIFO
|
||||
- * can also be read while the tx status tasklet gets executed.
|
||||
- *
|
||||
* Since we have only one producer and one consumer we don't
|
||||
* need to lock the kfifo.
|
||||
*/
|
||||
@@ -485,13 +326,8 @@ irqreturn_t rt2800mmio_interrupt(int irq
|
||||
*/
|
||||
mask = ~reg;
|
||||
|
||||
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
|
||||
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
|
||||
rt2800mmio_txstatus_interrupt(rt2x00dev);
|
||||
- /*
|
||||
- * Never disable the TX_FIFO_STATUS interrupt.
|
||||
- */
|
||||
- rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
|
||||
- }
|
||||
|
||||
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
|
||||
tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
@@ -113,6 +113,7 @@ int rt2x00queue_map_txskb(struct queue_e
|
||||
return -ENOMEM;
|
||||
|
||||
skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
|
||||
+ rt2x00lib_dmadone(entry);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
|
||||
@@ -0,0 +1,72 @@
|
||||
From 5022efb50f625d11fdf18b1fee0f64ebb1863664 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 26 Sep 2018 12:24:55 +0200
|
||||
Subject: [PATCH 04/28] rt2x00: do not check for txstatus timeout every time on
|
||||
tasklet
|
||||
|
||||
Do not check for tx status timeout everytime we perform txstatus tasklet.
|
||||
Perform check once per half a second.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 +++++++
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 3 ++-
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 2 ++
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 1 +
|
||||
4 files changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1158,11 +1158,18 @@ bool rt2800_txstatus_timeout(struct rt2x
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
|
||||
+ if (time_before(jiffies,
|
||||
+ rt2x00dev->last_nostatus_check + msecs_to_jiffies(500)))
|
||||
+ return false;
|
||||
+
|
||||
+ rt2x00dev->last_nostatus_check = jiffies;
|
||||
+
|
||||
tx_queue_for_each(rt2x00dev, queue) {
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
if (rt2800_entry_txstatus_timeout(entry))
|
||||
return true;
|
||||
}
|
||||
+
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -197,7 +197,8 @@ void rt2800mmio_txstatus_tasklet(unsigne
|
||||
|
||||
rt2800_txdone(rt2x00dev);
|
||||
|
||||
- rt2800_txdone_nostatus(rt2x00dev);
|
||||
+ if (rt2800_txstatus_timeout(rt2x00dev))
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2800mmio_enable_interrupt(rt2x00dev,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -979,6 +979,8 @@ struct rt2x00_dev {
|
||||
*/
|
||||
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
|
||||
|
||||
+ unsigned long last_nostatus_check;
|
||||
+
|
||||
/*
|
||||
* Timer to ensure tx status reports are read (rt2800usb).
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
@@ -1042,6 +1042,7 @@ void rt2x00queue_start_queues(struct rt2
|
||||
*/
|
||||
tx_queue_for_each(rt2x00dev, queue)
|
||||
rt2x00queue_start_queue(queue);
|
||||
+ rt2x00dev->last_nostatus_check = jiffies;
|
||||
|
||||
rt2x00queue_start_queue(rt2x00dev->rx);
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
From adf26a356f132e35093585521ea3e36cd185af83 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 26 Sep 2018 12:24:56 +0200
|
||||
Subject: [PATCH 05/28] rt2x00: use different txstatus timeouts when flushing
|
||||
|
||||
Use different tx status timeouts for normal operation and when flushing.
|
||||
This increase timeout to 2s for normal operation as when there are bad
|
||||
radio conditions and frames are reposted many times device can not provide
|
||||
the status for quite long. With new timeout we can still get valid status
|
||||
on such bad conditions.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 31 +++++++++++++------
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2x00mac.c | 4 +++
|
||||
3 files changed, 26 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1137,36 +1137,47 @@ void rt2800_txdone(struct rt2x00_dev *rt
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txdone);
|
||||
|
||||
-static inline bool rt2800_entry_txstatus_timeout(struct queue_entry *entry)
|
||||
+static inline bool rt2800_entry_txstatus_timeout(struct rt2x00_dev *rt2x00dev,
|
||||
+ struct queue_entry *entry)
|
||||
{
|
||||
- bool tout;
|
||||
+ bool ret;
|
||||
+ unsigned long tout;
|
||||
|
||||
if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
return false;
|
||||
|
||||
- tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
|
||||
- if (unlikely(tout))
|
||||
+ if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
|
||||
+ tout = msecs_to_jiffies(100);
|
||||
+ else
|
||||
+ tout = msecs_to_jiffies(2000);
|
||||
+
|
||||
+ ret = time_after(jiffies, entry->last_action + tout);
|
||||
+ if (unlikely(ret))
|
||||
rt2x00_dbg(entry->queue->rt2x00dev,
|
||||
"TX status timeout for entry %d in queue %d\n",
|
||||
entry->entry_idx, entry->queue->qid);
|
||||
- return tout;
|
||||
-
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
+ unsigned long tout;
|
||||
+
|
||||
+ if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
|
||||
+ tout = msecs_to_jiffies(50);
|
||||
+ else
|
||||
+ tout = msecs_to_jiffies(1000);
|
||||
|
||||
- if (time_before(jiffies,
|
||||
- rt2x00dev->last_nostatus_check + msecs_to_jiffies(500)))
|
||||
+ if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
|
||||
return false;
|
||||
|
||||
rt2x00dev->last_nostatus_check = jiffies;
|
||||
|
||||
tx_queue_for_each(rt2x00dev, queue) {
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
- if (rt2800_entry_txstatus_timeout(entry))
|
||||
+ if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1195,7 +1206,7 @@ void rt2800_txdone_nostatus(struct rt2x0
|
||||
break;
|
||||
|
||||
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
|
||||
- rt2800_entry_txstatus_timeout(entry))
|
||||
+ rt2800_entry_txstatus_timeout(rt2x00dev, entry))
|
||||
rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
|
||||
else
|
||||
break;
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -665,6 +665,7 @@ enum rt2x00_state_flags {
|
||||
DEVICE_STATE_STARTED,
|
||||
DEVICE_STATE_ENABLED_RADIO,
|
||||
DEVICE_STATE_SCANNING,
|
||||
+ DEVICE_STATE_FLUSHING,
|
||||
|
||||
/*
|
||||
* Driver configuration
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
|
||||
@@ -710,8 +710,12 @@ void rt2x00mac_flush(struct ieee80211_hw
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
+ set_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags);
|
||||
+
|
||||
tx_queue_for_each(rt2x00dev, queue)
|
||||
rt2x00queue_flush_queue(queue, drop);
|
||||
+
|
||||
+ clear_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_flush);
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
From 0240564430c0697d8fde3743d70346a922466b36 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 26 Sep 2018 12:24:57 +0200
|
||||
Subject: [PATCH 06/28] rt2800: flush and txstatus rework for rt2800mmio
|
||||
|
||||
Implement custom rt2800mmio flush routine and change txstatus
|
||||
routine to read TX_STA_FIFO also in the tasklet.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 14 +--
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 118 +++++++++++++-----
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800pci.c | 2 +-
|
||||
4 files changed, 97 insertions(+), 38 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1147,7 +1147,7 @@ static inline bool rt2800_entry_txstatus
|
||||
return false;
|
||||
|
||||
if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
|
||||
- tout = msecs_to_jiffies(100);
|
||||
+ tout = msecs_to_jiffies(50);
|
||||
else
|
||||
tout = msecs_to_jiffies(2000);
|
||||
|
||||
@@ -1163,15 +1163,13 @@ bool rt2800_txstatus_timeout(struct rt2x
|
||||
{
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
- unsigned long tout;
|
||||
|
||||
- if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
|
||||
- tout = msecs_to_jiffies(50);
|
||||
- else
|
||||
- tout = msecs_to_jiffies(1000);
|
||||
+ if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) {
|
||||
+ unsigned long tout = msecs_to_jiffies(1000);
|
||||
|
||||
- if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
|
||||
- return false;
|
||||
+ if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
rt2x00dev->last_nostatus_check = jiffies;
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -191,21 +191,6 @@ static inline void rt2800mmio_enable_int
|
||||
spin_unlock_irq(&rt2x00dev->irqmask_lock);
|
||||
}
|
||||
|
||||
-void rt2800mmio_txstatus_tasklet(unsigned long data)
|
||||
-{
|
||||
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
|
||||
-
|
||||
- rt2800_txdone(rt2x00dev);
|
||||
-
|
||||
- if (rt2800_txstatus_timeout(rt2x00dev))
|
||||
- rt2800_txdone_nostatus(rt2x00dev);
|
||||
-
|
||||
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
- rt2800mmio_enable_interrupt(rt2x00dev,
|
||||
- INT_SOURCE_CSR_TX_FIFO_STATUS);
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
|
||||
-
|
||||
void rt2800mmio_pretbtt_tasklet(unsigned long data)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
|
||||
@@ -270,12 +255,26 @@ void rt2800mmio_autowake_tasklet(unsigne
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
|
||||
|
||||
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
|
||||
+static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ bool timeout = false;
|
||||
+
|
||||
+ while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
|
||||
+ (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
|
||||
+
|
||||
+ rt2800_txdone(rt2x00dev);
|
||||
+
|
||||
+ if (timeout)
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 status;
|
||||
- int i;
|
||||
+ bool more = false;
|
||||
|
||||
- /*
|
||||
+ /* FIXEME: rewrite this comment
|
||||
* The TX_FIFO_STATUS interrupt needs special care. We should
|
||||
* read TX_STA_FIFO but we should do it immediately as otherwise
|
||||
* the register can overflow and we would lose status reports.
|
||||
@@ -286,25 +285,37 @@ static void rt2800mmio_txstatus_interrup
|
||||
* because we can schedule the tasklet multiple times (when the
|
||||
* interrupt fires again during tx status processing).
|
||||
*
|
||||
- * Since we have only one producer and one consumer we don't
|
||||
+ * txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS
|
||||
+ * disabled so have only one producer and one consumer - we don't
|
||||
* need to lock the kfifo.
|
||||
*/
|
||||
- for (i = 0; i < rt2x00dev->tx->limit; i++) {
|
||||
+ while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
|
||||
status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
|
||||
-
|
||||
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
|
||||
break;
|
||||
|
||||
- if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
|
||||
- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
|
||||
- break;
|
||||
- }
|
||||
+ kfifo_put(&rt2x00dev->txstatus_fifo, status);
|
||||
+ more = true;
|
||||
}
|
||||
|
||||
- /* Schedule the tasklet for processing the tx status. */
|
||||
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
+ return more;
|
||||
}
|
||||
|
||||
+void rt2800mmio_txstatus_tasklet(unsigned long data)
|
||||
+{
|
||||
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
|
||||
+
|
||||
+ do {
|
||||
+ rt2800mmio_txdone(rt2x00dev);
|
||||
+
|
||||
+ } while (rt2800mmio_fetch_txstatus(rt2x00dev));
|
||||
+
|
||||
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
+ rt2800mmio_enable_interrupt(rt2x00dev,
|
||||
+ INT_SOURCE_CSR_TX_FIFO_STATUS);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
|
||||
+
|
||||
irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = dev_instance;
|
||||
@@ -327,8 +338,10 @@ irqreturn_t rt2800mmio_interrupt(int irq
|
||||
*/
|
||||
mask = ~reg;
|
||||
|
||||
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
|
||||
- rt2800mmio_txstatus_interrupt(rt2x00dev);
|
||||
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
|
||||
+ rt2800mmio_fetch_txstatus(rt2x00dev);
|
||||
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
+ }
|
||||
|
||||
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
|
||||
tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
|
||||
@@ -453,6 +466,53 @@ void rt2800mmio_kick_queue(struct data_q
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue);
|
||||
|
||||
+void rt2800mmio_flush_queue(struct data_queue *queue, bool drop)
|
||||
+{
|
||||
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
+ bool tx_queue = false;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ switch (queue->qid) {
|
||||
+ case QID_AC_VO:
|
||||
+ case QID_AC_VI:
|
||||
+ case QID_AC_BE:
|
||||
+ case QID_AC_BK:
|
||||
+ tx_queue = true;
|
||||
+ break;
|
||||
+ case QID_RX:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ /*
|
||||
+ * Check if the driver is already done, otherwise we
|
||||
+ * have to sleep a little while to give the driver/hw
|
||||
+ * the oppurtunity to complete interrupt process itself.
|
||||
+ */
|
||||
+ if (rt2x00queue_empty(queue))
|
||||
+ break;
|
||||
+
|
||||
+ /*
|
||||
+ * For TX queues schedule completion tasklet to catch
|
||||
+ * tx status timeouts, othewise just wait.
|
||||
+ */
|
||||
+ if (tx_queue) {
|
||||
+ tasklet_disable(&rt2x00dev->txstatus_tasklet);
|
||||
+ rt2800mmio_txdone(rt2x00dev);
|
||||
+ tasklet_enable(&rt2x00dev->txstatus_tasklet);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for a little while to give the driver
|
||||
+ * the oppurtunity to recover itself.
|
||||
+ */
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800mmio_flush_queue);
|
||||
+
|
||||
void rt2800mmio_stop_queue(struct data_queue *queue)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
@@ -148,6 +148,7 @@ void rt2800mmio_toggle_irq(struct rt2x00
|
||||
/* Queue handlers */
|
||||
void rt2800mmio_start_queue(struct data_queue *queue);
|
||||
void rt2800mmio_kick_queue(struct data_queue *queue);
|
||||
+void rt2800mmio_flush_queue(struct data_queue *queue, bool drop);
|
||||
void rt2800mmio_stop_queue(struct data_queue *queue);
|
||||
void rt2800mmio_queue_init(struct data_queue *queue);
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -364,7 +364,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.start_queue = rt2800mmio_start_queue,
|
||||
.kick_queue = rt2800mmio_kick_queue,
|
||||
.stop_queue = rt2800mmio_stop_queue,
|
||||
- .flush_queue = rt2x00mmio_flush_queue,
|
||||
+ .flush_queue = rt2800mmio_flush_queue,
|
||||
.write_tx_desc = rt2800mmio_write_tx_desc,
|
||||
.write_tx_data = rt2800_write_tx_data,
|
||||
.write_beacon = rt2800_write_beacon,
|
||||
@@ -0,0 +1,25 @@
|
||||
From 6eba8fd2235237784dfd01da55c3210d493aebdb Mon Sep 17 00:00:00 2001
|
||||
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
|
||||
Date: Mon, 22 Oct 2018 22:44:34 +0200
|
||||
Subject: [PATCH 07/28] rt2x00: rt2400pci: mark expected switch fall-through
|
||||
|
||||
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
|
||||
where we are expecting to fall through.
|
||||
|
||||
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2400pci.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
@@ -1302,7 +1302,7 @@ static void rt2400pci_txdone(struct rt2x
|
||||
break;
|
||||
case 2: /* Failure, excessive retries */
|
||||
__set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
|
||||
- /* Don't break, this is a failed frame! */
|
||||
+ /* Fall through - this is a failed frame! */
|
||||
default: /* Failure */
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
From 10bb92217747c3384a01ebec005faa2f5e72bbd8 Mon Sep 17 00:00:00 2001
|
||||
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
|
||||
Date: Mon, 22 Oct 2018 22:45:19 +0200
|
||||
Subject: [PATCH 08/28] rt2x00: rt2500pci: mark expected switch fall-through
|
||||
|
||||
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
|
||||
where we are expecting to fall through.
|
||||
|
||||
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2500pci.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
@@ -1430,7 +1430,7 @@ static void rt2500pci_txdone(struct rt2x
|
||||
break;
|
||||
case 2: /* Failure, excessive retries */
|
||||
__set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
|
||||
- /* Don't break, this is a failed frame! */
|
||||
+ /* Fall through - this is a failed frame! */
|
||||
default: /* Failure */
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
From 916e6bbcfcff6cc5d7d33bba8557a30f3af50326 Mon Sep 17 00:00:00 2001
|
||||
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
|
||||
Date: Mon, 22 Oct 2018 22:46:03 +0200
|
||||
Subject: [PATCH 09/28] rt2x00: rt2800lib: mark expected switch fall-throughs
|
||||
|
||||
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
|
||||
where we are expecting to fall through.
|
||||
|
||||
Addresses-Coverity-ID: 145198 ("Missing break in switch")
|
||||
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -2482,6 +2482,7 @@ static void rt2800_config_channel_rf3052
|
||||
switch (rt2x00dev->default_ant.tx_chain_num) {
|
||||
case 1:
|
||||
rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
|
||||
+ /* fall through */
|
||||
case 2:
|
||||
rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
|
||||
break;
|
||||
@@ -2490,6 +2491,7 @@ static void rt2800_config_channel_rf3052
|
||||
switch (rt2x00dev->default_ant.rx_chain_num) {
|
||||
case 1:
|
||||
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
|
||||
+ /* fall through */
|
||||
case 2:
|
||||
rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
|
||||
break;
|
||||
@@ -9457,8 +9459,10 @@ static int rt2800_probe_hw_mode(struct r
|
||||
switch (rx_chains) {
|
||||
case 3:
|
||||
spec->ht.mcs.rx_mask[2] = 0xff;
|
||||
+ /* fall through */
|
||||
case 2:
|
||||
spec->ht.mcs.rx_mask[1] = 0xff;
|
||||
+ /* fall through */
|
||||
case 1:
|
||||
spec->ht.mcs.rx_mask[0] = 0xff;
|
||||
spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
|
||||
@@ -0,0 +1,25 @@
|
||||
From 641dd8068ecb078e7d12efe465df202bc16ca5eb Mon Sep 17 00:00:00 2001
|
||||
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
|
||||
Date: Mon, 22 Oct 2018 22:46:47 +0200
|
||||
Subject: [PATCH 10/28] rt2x00: rt61pci: mark expected switch fall-through
|
||||
|
||||
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
|
||||
where we are expecting to fall through.
|
||||
|
||||
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt61pci.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
@@ -2226,7 +2226,7 @@ static void rt61pci_txdone(struct rt2x00
|
||||
break;
|
||||
case 6: /* Failure, excessive retries */
|
||||
__set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
|
||||
- /* Don't break, this is a failed frame! */
|
||||
+ /* Fall through - this is a failed frame! */
|
||||
default: /* Failure */
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
From 750afb08ca71310fcf0c4e2cb1565c63b8235b60 Mon Sep 17 00:00:00 2001
|
||||
From: Luis Chamberlain <mcgrof@kernel.org>
|
||||
Date: Fri, 4 Jan 2019 09:23:09 +0100
|
||||
Subject: [PATCH 11/28] cross-tree: phase out dma_zalloc_coherent()
|
||||
|
||||
We already need to zero out memory for dma_alloc_coherent(), as such
|
||||
using dma_zalloc_coherent() is superflous. Phase it out.
|
||||
|
||||
This change was generated with the following Coccinelle SmPL patch:
|
||||
|
||||
@ replace_dma_zalloc_coherent @
|
||||
expression dev, size, data, handle, flags;
|
||||
@@
|
||||
|
||||
-dma_zalloc_coherent(dev, size, handle, flags)
|
||||
+dma_alloc_coherent(dev, size, handle, flags)
|
||||
|
||||
Suggested-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
|
||||
[hch: re-ran the script on the latest tree]
|
||||
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
|
||||
@@ -119,9 +119,9 @@ static int rt2x00mmio_alloc_queue_dma(st
|
||||
/*
|
||||
* Allocate DMA memory for descriptor and buffer.
|
||||
*/
|
||||
- addr = dma_zalloc_coherent(rt2x00dev->dev,
|
||||
- queue->limit * queue->desc_size, &dma,
|
||||
- GFP_KERNEL);
|
||||
+ addr = dma_alloc_coherent(rt2x00dev->dev,
|
||||
+ queue->limit * queue->desc_size, &dma,
|
||||
+ GFP_KERNEL);
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From c2e28ef7711ffcb083474ee5f154264c6ec1ec07 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tomislav=20Po=C5=BEega?= <pozega.tomislav@gmail.com>
|
||||
Date: Thu, 27 Dec 2018 15:05:25 +0100
|
||||
Subject: [PATCH 12/28] rt2x00: reduce tx power to nominal level on RT6352
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Current implementation of RT6352 support provides too high tx power
|
||||
at least on iPA/eLNA devices. Reduce amplification of variable gain
|
||||
amplifier by 6dB to match board target power of 17dBm.
|
||||
Transmited signal strength with this patch is similar to that of
|
||||
stock firmware or pandorabox firmware. Throughput measured with iperf
|
||||
improves. Device tested: Xiaomi Miwifi Mini.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -5477,7 +5477,7 @@ static int rt2800_init_registers(struct
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
|
||||
rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002);
|
||||
rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F);
|
||||
- rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x06060606);
|
||||
+ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
|
||||
rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
|
||||
rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
|
||||
rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C);
|
||||
@@ -0,0 +1,143 @@
|
||||
From a4296994eb8061ee3455721a296c387c639bf635 Mon Sep 17 00:00:00 2001
|
||||
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
Date: Tue, 15 Jan 2019 14:01:29 +0000
|
||||
Subject: [PATCH 13/28] rt2x00: Work around a firmware bug with shared keys
|
||||
|
||||
Apparently the rt2x61 firmware fails temporarily to decode
|
||||
broadcast packets if the shared keys are not assigned
|
||||
in the "correct" sequence. At the same time unicast
|
||||
packets work fine, since they are encrypted with the
|
||||
pairwise key.
|
||||
|
||||
At least with WPA2 CCMP mode the shared keys are
|
||||
set in the following sequence: keyidx=1, 2, 1, 2.
|
||||
After a while only keyidx 2 gets decrypted, and
|
||||
keyidx 1 is ignored, probably because there is never
|
||||
a keyidx 3.
|
||||
|
||||
Symptoms are arping -b works for 10 minutes, since
|
||||
keyidx=2 is used for broadcast, and then it stops
|
||||
working for 10 minutes, because keyidx=1 is used.
|
||||
That failure mode repeats forever.
|
||||
|
||||
Note, the firmware does not even know which keyidx
|
||||
corresponds to which hw_key_idx so the firmware is
|
||||
trying to be smarter than the driver, which is bound
|
||||
to fail.
|
||||
|
||||
As workaround the function rt61pci_config_shared_key
|
||||
requests software decryption of the shared keys,
|
||||
by returning EOPNOTSUPP. However, pairwise keys are
|
||||
still handled by hardware which works just fine.
|
||||
|
||||
Signed-off-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt61pci.c | 93 +-------------------
|
||||
1 file changed, 4 insertions(+), 89 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
@@ -321,97 +321,12 @@ static int rt61pci_config_shared_key(str
|
||||
struct rt2x00lib_crypto *crypto,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
- struct hw_key_entry key_entry;
|
||||
- struct rt2x00_field32 field;
|
||||
- u32 mask;
|
||||
- u32 reg;
|
||||
-
|
||||
- if (crypto->cmd == SET_KEY) {
|
||||
- /*
|
||||
- * rt2x00lib can't determine the correct free
|
||||
- * key_idx for shared keys. We have 1 register
|
||||
- * with key valid bits. The goal is simple, read
|
||||
- * the register, if that is full we have no slots
|
||||
- * left.
|
||||
- * Note that each BSS is allowed to have up to 4
|
||||
- * shared keys, so put a mask over the allowed
|
||||
- * entries.
|
||||
- */
|
||||
- mask = (0xf << crypto->bssidx);
|
||||
-
|
||||
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
|
||||
- reg &= mask;
|
||||
-
|
||||
- if (reg && reg == mask)
|
||||
- return -ENOSPC;
|
||||
-
|
||||
- key->hw_key_idx += reg ? ffz(reg) : 0;
|
||||
-
|
||||
- /*
|
||||
- * Upload key to hardware
|
||||
- */
|
||||
- memcpy(key_entry.key, crypto->key,
|
||||
- sizeof(key_entry.key));
|
||||
- memcpy(key_entry.tx_mic, crypto->tx_mic,
|
||||
- sizeof(key_entry.tx_mic));
|
||||
- memcpy(key_entry.rx_mic, crypto->rx_mic,
|
||||
- sizeof(key_entry.rx_mic));
|
||||
-
|
||||
- reg = SHARED_KEY_ENTRY(key->hw_key_idx);
|
||||
- rt2x00mmio_register_multiwrite(rt2x00dev, reg,
|
||||
- &key_entry, sizeof(key_entry));
|
||||
-
|
||||
- /*
|
||||
- * The cipher types are stored over 2 registers.
|
||||
- * bssidx 0 and 1 keys are stored in SEC_CSR1 and
|
||||
- * bssidx 1 and 2 keys are stored in SEC_CSR5.
|
||||
- * Using the correct defines correctly will cause overhead,
|
||||
- * so just calculate the correct offset.
|
||||
- */
|
||||
- if (key->hw_key_idx < 8) {
|
||||
- field.bit_offset = (3 * key->hw_key_idx);
|
||||
- field.bit_mask = 0x7 << field.bit_offset;
|
||||
-
|
||||
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR1);
|
||||
- rt2x00_set_field32(®, field, crypto->cipher);
|
||||
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
|
||||
- } else {
|
||||
- field.bit_offset = (3 * (key->hw_key_idx - 8));
|
||||
- field.bit_mask = 0x7 << field.bit_offset;
|
||||
-
|
||||
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR5);
|
||||
- rt2x00_set_field32(®, field, crypto->cipher);
|
||||
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * The driver does not support the IV/EIV generation
|
||||
- * in hardware. However it doesn't support the IV/EIV
|
||||
- * inside the ieee80211 frame either, but requires it
|
||||
- * to be provided separately for the descriptor.
|
||||
- * rt2x00lib will cut the IV/EIV data out of all frames
|
||||
- * given to us by mac80211, but we must tell mac80211
|
||||
- * to generate the IV/EIV data.
|
||||
- */
|
||||
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
- * SEC_CSR0 contains only single-bit fields to indicate
|
||||
- * a particular key is valid. Because using the FIELD32()
|
||||
- * defines directly will cause a lot of overhead, we use
|
||||
- * a calculation to determine the correct bit directly.
|
||||
+ * Let the software handle the shared keys,
|
||||
+ * since the hardware decryption does not work reliably,
|
||||
+ * because the firmware does not know the key's keyidx.
|
||||
*/
|
||||
- mask = 1 << key->hw_key_idx;
|
||||
-
|
||||
- reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
|
||||
- if (crypto->cmd == SET_KEY)
|
||||
- reg |= mask;
|
||||
- else if (crypto->cmd == DISABLE_KEY)
|
||||
- reg &= ~mask;
|
||||
- rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
|
||||
-
|
||||
- return 0;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -0,0 +1,107 @@
|
||||
From 2587791d57588562c21e5ef7e678f02ab2f3eb82 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Date: Tue, 22 Jan 2019 16:21:34 +0100
|
||||
Subject: [PATCH 14/28] rt2x00: no need to check return value of debugfs_create
|
||||
functions
|
||||
|
||||
When calling debugfs functions, there is no need to ever check the
|
||||
return value. The function can work or not, but the code logic should
|
||||
never do something different based on this.
|
||||
|
||||
Cc: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Cc: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@codeaurora.org>
|
||||
Cc: linux-wireless@vger.kernel.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2x00debug.c | 27 -------------------
|
||||
1 file changed, 27 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
@@ -656,36 +656,24 @@ void rt2x00debug_register(struct rt2x00_
|
||||
intf->driver_folder =
|
||||
debugfs_create_dir(intf->rt2x00dev->ops->name,
|
||||
rt2x00dev->hw->wiphy->debugfsdir);
|
||||
- if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
|
||||
- goto exit;
|
||||
|
||||
intf->driver_entry =
|
||||
rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
|
||||
- if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
|
||||
- goto exit;
|
||||
|
||||
intf->chipset_entry =
|
||||
rt2x00debug_create_file_chipset("chipset",
|
||||
intf, &intf->chipset_blob);
|
||||
- if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
|
||||
- goto exit;
|
||||
|
||||
intf->dev_flags = debugfs_create_file("dev_flags", 0400,
|
||||
intf->driver_folder, intf,
|
||||
&rt2x00debug_fop_dev_flags);
|
||||
- if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
|
||||
- goto exit;
|
||||
|
||||
intf->cap_flags = debugfs_create_file("cap_flags", 0400,
|
||||
intf->driver_folder, intf,
|
||||
&rt2x00debug_fop_cap_flags);
|
||||
- if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
|
||||
- goto exit;
|
||||
|
||||
intf->register_folder =
|
||||
debugfs_create_dir("register", intf->driver_folder);
|
||||
- if (IS_ERR(intf->register_folder) || !intf->register_folder)
|
||||
- goto exit;
|
||||
|
||||
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
|
||||
({ \
|
||||
@@ -695,9 +683,6 @@ void rt2x00debug_register(struct rt2x00_
|
||||
0600, \
|
||||
(__intf)->register_folder, \
|
||||
&(__intf)->offset_##__name); \
|
||||
- if (IS_ERR((__intf)->__name##_off_entry) || \
|
||||
- !(__intf)->__name##_off_entry) \
|
||||
- goto exit; \
|
||||
\
|
||||
(__intf)->__name##_val_entry = \
|
||||
debugfs_create_file(__stringify(__name) "_value", \
|
||||
@@ -705,9 +690,6 @@ void rt2x00debug_register(struct rt2x00_
|
||||
(__intf)->register_folder, \
|
||||
(__intf), \
|
||||
&rt2x00debug_fop_##__name); \
|
||||
- if (IS_ERR((__intf)->__name##_val_entry) || \
|
||||
- !(__intf)->__name##_val_entry) \
|
||||
- goto exit; \
|
||||
} \
|
||||
})
|
||||
|
||||
@@ -721,15 +703,10 @@ void rt2x00debug_register(struct rt2x00_
|
||||
|
||||
intf->queue_folder =
|
||||
debugfs_create_dir("queue", intf->driver_folder);
|
||||
- if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
|
||||
- goto exit;
|
||||
|
||||
intf->queue_frame_dump_entry =
|
||||
debugfs_create_file("dump", 0400, intf->queue_folder,
|
||||
intf, &rt2x00debug_fop_queue_dump);
|
||||
- if (IS_ERR(intf->queue_frame_dump_entry)
|
||||
- || !intf->queue_frame_dump_entry)
|
||||
- goto exit;
|
||||
|
||||
skb_queue_head_init(&intf->frame_dump_skbqueue);
|
||||
init_waitqueue_head(&intf->frame_dump_waitqueue);
|
||||
@@ -747,10 +724,6 @@ void rt2x00debug_register(struct rt2x00_
|
||||
#endif
|
||||
|
||||
return;
|
||||
-
|
||||
-exit:
|
||||
- rt2x00debug_deregister(rt2x00dev);
|
||||
- rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
|
||||
}
|
||||
|
||||
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
|
||||
@@ -0,0 +1,137 @@
|
||||
From 17ae2acd1a6f5148edd80d84194e5d7c80be360e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tomislav=20Po=C5=BEega?= <pozega.tomislav@gmail.com>
|
||||
Date: Wed, 13 Feb 2019 11:09:12 +0100
|
||||
Subject: [PATCH 15/28] rt2x00: remove unneeded check
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Remove band check from rf53xx channel config routine since all chips
|
||||
using it are single band.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 103 +++++++++---------
|
||||
1 file changed, 50 insertions(+), 53 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -2966,6 +2966,7 @@ static void rt2800_config_channel_rf53xx
|
||||
struct channel_info *info)
|
||||
{
|
||||
u8 rfcsr;
|
||||
+ int idx = rf->channel-1;
|
||||
|
||||
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
|
||||
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
|
||||
@@ -3003,60 +3004,56 @@ static void rt2800_config_channel_rf53xx
|
||||
|
||||
rt2800_freq_cal_mode1(rt2x00dev);
|
||||
|
||||
- if (rf->channel <= 14) {
|
||||
- int idx = rf->channel-1;
|
||||
+ if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
|
||||
+ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
|
||||
+ /* r55/r59 value array of channel 1~14 */
|
||||
+ static const char r55_bt_rev[] = {0x83, 0x83,
|
||||
+ 0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
|
||||
+ 0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
|
||||
+ static const char r59_bt_rev[] = {0x0e, 0x0e,
|
||||
+ 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
|
||||
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 55,
|
||||
+ r55_bt_rev[idx]);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
+ r59_bt_rev[idx]);
|
||||
+ } else {
|
||||
+ static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
|
||||
+ 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
|
||||
+ 0x88, 0x88, 0x86, 0x85, 0x84};
|
||||
|
||||
- if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
|
||||
- if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
|
||||
- /* r55/r59 value array of channel 1~14 */
|
||||
- static const char r55_bt_rev[] = {0x83, 0x83,
|
||||
- 0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
|
||||
- 0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
|
||||
- static const char r59_bt_rev[] = {0x0e, 0x0e,
|
||||
- 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
|
||||
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
|
||||
-
|
||||
- rt2800_rfcsr_write(rt2x00dev, 55,
|
||||
- r55_bt_rev[idx]);
|
||||
- rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
- r59_bt_rev[idx]);
|
||||
- } else {
|
||||
- static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
|
||||
- 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
|
||||
- 0x88, 0x88, 0x86, 0x85, 0x84};
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
|
||||
+ static const char r55_nonbt_rev[] = {0x23, 0x23,
|
||||
+ 0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
|
||||
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
|
||||
+ static const char r59_nonbt_rev[] = {0x07, 0x07,
|
||||
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
+ 0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 55,
|
||||
+ r55_nonbt_rev[idx]);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
+ r59_nonbt_rev[idx]);
|
||||
+ } else if (rt2x00_rt(rt2x00dev, RT5390) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT5392) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
+ static const char r59_non_bt[] = {0x8f, 0x8f,
|
||||
+ 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
|
||||
+ 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
+ r59_non_bt[idx]);
|
||||
+ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
|
||||
+ static const char r59_non_bt[] = {0x0b, 0x0b,
|
||||
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
|
||||
+ 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
|
||||
|
||||
- rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
|
||||
- }
|
||||
- } else {
|
||||
- if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
|
||||
- static const char r55_nonbt_rev[] = {0x23, 0x23,
|
||||
- 0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
|
||||
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
|
||||
- static const char r59_nonbt_rev[] = {0x07, 0x07,
|
||||
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
- 0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
|
||||
-
|
||||
- rt2800_rfcsr_write(rt2x00dev, 55,
|
||||
- r55_nonbt_rev[idx]);
|
||||
- rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
- r59_nonbt_rev[idx]);
|
||||
- } else if (rt2x00_rt(rt2x00dev, RT5390) ||
|
||||
- rt2x00_rt(rt2x00dev, RT5392) ||
|
||||
- rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
- static const char r59_non_bt[] = {0x8f, 0x8f,
|
||||
- 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
|
||||
- 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
|
||||
-
|
||||
- rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
- r59_non_bt[idx]);
|
||||
- } else if (rt2x00_rt(rt2x00dev, RT5350)) {
|
||||
- static const char r59_non_bt[] = {0x0b, 0x0b,
|
||||
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
|
||||
- 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
|
||||
-
|
||||
- rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
- r59_non_bt[idx]);
|
||||
- }
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59,
|
||||
+ r59_non_bt[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
From 5991a2ecd070ce5ef646b4e8e0bc8d99110604ed Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tomislav=20Po=C5=BEega?= <pozega.tomislav@gmail.com>
|
||||
Date: Wed, 13 Feb 2019 11:09:13 +0100
|
||||
Subject: [PATCH 16/28] rt2x00: remove confusing AGC register
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Register 66 was causing issues on RT6352 if set to the same value as
|
||||
in MTK driver. With 1c reg value device was working fine in both HT20
|
||||
and HT40 modes.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 +-----
|
||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -3983,11 +3983,7 @@ static void rt2800_config_channel(struct
|
||||
rt2800_bbp_write(rt2x00dev, 196, reg);
|
||||
|
||||
/* AGC init */
|
||||
- if (rt2x00_rt(rt2x00dev, RT6352))
|
||||
- reg = 0x04;
|
||||
- else
|
||||
- reg = rf->channel <= 14 ? 0x1c : 0x24;
|
||||
-
|
||||
+ reg = rf->channel <= 14 ? 0x1c : 0x24;
|
||||
reg += 2 * rt2x00dev->lna_gain;
|
||||
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 9ad3b55654455258a9463384edb40077439d879f Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 13 Feb 2019 11:09:14 +0100
|
||||
Subject: [PATCH 17/28] rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band
|
||||
|
||||
Do not enable TX_PIN_CFG_LNA_PE_A* bits for 2.4GHz band and
|
||||
vice versa TX_PIN_CFG_LNA_PE_G* bits for 5GHz.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 18 ++++++++++++------
|
||||
1 file changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -3893,18 +3893,24 @@ static void rt2800_config_channel(struct
|
||||
switch (rt2x00dev->default_ant.rx_chain_num) {
|
||||
case 3:
|
||||
/* Turn on tertiary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
|
||||
+ rf->channel > 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
|
||||
+ rf->channel <= 14);
|
||||
/* fall-through */
|
||||
case 2:
|
||||
/* Turn on secondary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
|
||||
+ rf->channel > 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
|
||||
+ rf->channel <= 14);
|
||||
/* fall-through */
|
||||
case 1:
|
||||
/* Turn on primary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
|
||||
+ rf->channel > 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
|
||||
+ rf->channel <= 14);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
From 7aca14885edeab536a8cbe1e7cfeadd4c3310b9b Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 13 Feb 2019 11:09:15 +0100
|
||||
Subject: [PATCH 18/28] rt2800: enable TX_PIN_CFG_RFRX_EN only for MT7620
|
||||
|
||||
The TX_PIN_CFG_RFRX_EN bit was not set on other devices than MT7620,
|
||||
restore old behavaviour since setting this bit maight not be
|
||||
correct for older devices.
|
||||
|
||||
Fixes: 41977e86c984 ("rt2x00: add support for MT7620")
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -3858,10 +3858,12 @@ static void rt2800_config_channel(struct
|
||||
if (rt2x00_rt(rt2x00dev, RT3572))
|
||||
rt2800_rfcsr_write(rt2x00dev, 8, 0);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT6352))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
|
||||
- else
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1);
|
||||
+ } else {
|
||||
tx_pin = 0;
|
||||
+ }
|
||||
|
||||
switch (rt2x00dev->default_ant.tx_chain_num) {
|
||||
case 3:
|
||||
@@ -3916,7 +3918,6 @@ static void rt2800_config_channel(struct
|
||||
|
||||
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
|
||||
rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); /* mt7620 */
|
||||
|
||||
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From c7ff1bfeaf1ca69e3e401be211b55d1738d0c5fc Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Wed, 13 Feb 2019 11:09:16 +0100
|
||||
Subject: [PATCH 19/28] rt2800: comment and simplify AGC init for RT6352
|
||||
|
||||
We do not need separate lines for calculating register values.
|
||||
Also add comment that value is different than in vendor driver.
|
||||
|
||||
Suggested-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -3989,9 +3989,12 @@ static void rt2800_config_channel(struct
|
||||
rt2800_bbp_write(rt2x00dev, 195, 141);
|
||||
rt2800_bbp_write(rt2x00dev, 196, reg);
|
||||
|
||||
- /* AGC init */
|
||||
- reg = rf->channel <= 14 ? 0x1c : 0x24;
|
||||
- reg += 2 * rt2x00dev->lna_gain;
|
||||
+ /* AGC init.
|
||||
+ * Despite the vendor driver using different values here for
|
||||
+ * RT6352 chip, we use 0x1c for now. This may have to be changed
|
||||
+ * once TSSI got implemented.
|
||||
+ */
|
||||
+ reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
|
||||
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
|
||||
|
||||
rt2800_iq_calibrate(rt2x00dev, rf->channel);
|
||||
@@ -0,0 +1,39 @@
|
||||
From patchwork Tue Mar 12 09:51:40 2019
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10848957
|
||||
X-Patchwork-Delegate: johannes@sipsolutions.net
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
To: linux-wireless@vger.kernel.org
|
||||
Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
|
||||
Mathias Kresin <dev@kresin.me>
|
||||
Subject: [PATCH v3 1/4] cfg80211: add ratelimited variants of err and warn
|
||||
Date: Tue, 12 Mar 2019 10:51:40 +0100
|
||||
Message-Id: <1552384303-29529-2-git-send-email-sgruszka@redhat.com>
|
||||
In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
|
||||
wiphy_{err,warn}_ratelimited will be used by rt2x00
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
include/net/cfg80211.h | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -6632,6 +6632,11 @@ bool cfg80211_iftype_allowed(struct wiph
|
||||
#define wiphy_info(wiphy, format, args...) \
|
||||
dev_info(&(wiphy)->dev, format, ##args)
|
||||
|
||||
+#define wiphy_err_ratelimited(wiphy, format, args...) \
|
||||
+ dev_err_ratelimited(&(wiphy)->dev, format, ##args)
|
||||
+#define wiphy_warn_ratelimited(wiphy, format, args...) \
|
||||
+ dev_warn_ratelimited(&(wiphy)->dev, format, ##args)
|
||||
+
|
||||
#define wiphy_debug(wiphy, format, args...) \
|
||||
wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From patchwork Tue Mar 12 09:51:41 2019
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10848959
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
To: linux-wireless@vger.kernel.org
|
||||
Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
|
||||
Mathias Kresin <dev@kresin.me>
|
||||
Subject: [PATCH v3 2/4] rt2x00: use ratelimited variants dev_warn/dev_err
|
||||
Date: Tue, 12 Mar 2019 10:51:41 +0100
|
||||
Message-Id: <1552384303-29529-3-git-send-email-sgruszka@redhat.com>
|
||||
In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
|
||||
As reported by Randy we can overwhelm logs on some USB error conditions.
|
||||
To avoid that use dev_warn_ratelimited() and dev_err_ratelimitd().
|
||||
|
||||
Reported-and-tested-by: Randy Oostdyk <linux-kernel@oostdyk.com>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -69,10 +69,10 @@
|
||||
printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
#define rt2x00_err(dev, fmt, ...) \
|
||||
- wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt, \
|
||||
+ wiphy_err_ratelimited((dev)->hw->wiphy, "%s: Error - " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
#define rt2x00_warn(dev, fmt, ...) \
|
||||
- wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt, \
|
||||
+ wiphy_warn_ratelimited((dev)->hw->wiphy, "%s: Warning - " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
#define rt2x00_info(dev, fmt, ...) \
|
||||
wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt, \
|
||||
@@ -0,0 +1,96 @@
|
||||
From patchwork Tue Mar 12 09:51:42 2019
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10848961
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
To: linux-wireless@vger.kernel.org
|
||||
Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
|
||||
Mathias Kresin <dev@kresin.me>
|
||||
Subject: [PATCH v3 3/4] rt2x00: check number of EPROTO errors
|
||||
Date: Tue, 12 Mar 2019 10:51:42 +0100
|
||||
Message-Id: <1552384303-29529-4-git-send-email-sgruszka@redhat.com>
|
||||
In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
|
||||
Some USB host devices/drivers on some conditions can always return
|
||||
EPROTO error on submitted URBs. That can cause infinity loop in the
|
||||
rt2x00 driver.
|
||||
|
||||
Since we can have single EPROTO errors we can not mark as device as
|
||||
removed to avoid infinity loop. However we can count consecutive
|
||||
EPROTO errors and mark device as removed if get lot of it.
|
||||
I choose number 10 as threshold.
|
||||
|
||||
Reported-and-tested-by: Randy Oostdyk <linux-kernel@oostdyk.com>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 22 +++++++++++++++++++---
|
||||
2 files changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -1016,6 +1016,7 @@ struct rt2x00_dev {
|
||||
unsigned int extra_tx_headroom;
|
||||
|
||||
struct usb_anchor *anchor;
|
||||
+ unsigned int num_proto_errs;
|
||||
|
||||
/* Clock for System On Chip devices. */
|
||||
struct clk *clk;
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
@@ -31,6 +31,22 @@
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00usb.h"
|
||||
|
||||
+static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status)
|
||||
+{
|
||||
+ if (status == -ENODEV || status == -ENOENT)
|
||||
+ return true;
|
||||
+
|
||||
+ if (status == -EPROTO || status == -ETIMEDOUT)
|
||||
+ rt2x00dev->num_proto_errs++;
|
||||
+ else
|
||||
+ rt2x00dev->num_proto_errs = 0;
|
||||
+
|
||||
+ if (rt2x00dev->num_proto_errs > 3)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Interfacing with the HW.
|
||||
*/
|
||||
@@ -57,7 +73,7 @@ int rt2x00usb_vendor_request(struct rt2x
|
||||
if (status >= 0)
|
||||
return 0;
|
||||
|
||||
- if (status == -ENODEV || status == -ENOENT) {
|
||||
+ if (rt2x00usb_check_usb_error(rt2x00dev, status)) {
|
||||
/* Device has disappeared. */
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
break;
|
||||
@@ -321,7 +337,7 @@ static bool rt2x00usb_kick_tx_entry(stru
|
||||
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
- if (status == -ENODEV || status == -ENOENT)
|
||||
+ if (rt2x00usb_check_usb_error(rt2x00dev, status))
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
rt2x00lib_dmadone(entry);
|
||||
@@ -410,7 +426,7 @@ static bool rt2x00usb_kick_rx_entry(stru
|
||||
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
- if (status == -ENODEV || status == -ENOENT)
|
||||
+ if (rt2x00usb_check_usb_error(rt2x00dev, status))
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
rt2x00lib_dmadone(entry);
|
||||
@@ -0,0 +1,43 @@
|
||||
From patchwork Tue Mar 12 09:51:43 2019
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10848963
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
To: linux-wireless@vger.kernel.org
|
||||
Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
|
||||
Mathias Kresin <dev@kresin.me>
|
||||
Subject: [PATCH v3 4/4] rt2x00: do not print error when queue is full
|
||||
Date: Tue, 12 Mar 2019 10:51:43 +0100
|
||||
Message-Id: <1552384303-29529-5-git-send-email-sgruszka@redhat.com>
|
||||
In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
|
||||
|
||||
For unknown reasons printk() on some context can cause CPU hung on
|
||||
embedded MT7620 AP/router MIPS platforms. What can result on wifi
|
||||
disconnects.
|
||||
|
||||
This patch move queue full messages to debug level what is consistent
|
||||
with other mac80211 drivers which drop packet silently if tx queue is
|
||||
full. This make MT7620 OpenWRT routers more stable, what was reported
|
||||
by various users.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
@@ -674,7 +674,7 @@ int rt2x00queue_write_tx_frame(struct da
|
||||
spin_lock(&queue->tx_lock);
|
||||
|
||||
if (unlikely(rt2x00queue_full(queue))) {
|
||||
- rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
|
||||
+ rt2x00_dbg(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
|
||||
queue->qid);
|
||||
ret = -ENOBUFS;
|
||||
goto out;
|
||||
@@ -0,0 +1,128 @@
|
||||
From 91a5340db0526b7263bc8da14b120ea3129b5f28 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:31 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804437
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 21/28] rt2800: partially restore old mmio txstatus behaviour
|
||||
|
||||
Do not disable txstatus interrupt and add quota of processed tx statuses in
|
||||
one tasklet. Quota is needed to allow to fed device with new frames during
|
||||
processing of tx statuses.
|
||||
|
||||
Patch fixes about 15% performance degradation on some scenarios coused by
|
||||
0b0d556e0ebb ("rt2800mmio: use txdone/txstatus routines from lib").
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 4 +--
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 2 +-
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 30 +++++--------------
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 2 +-
|
||||
4 files changed, 12 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1100,7 +1100,7 @@ void rt2800_txdone_entry(struct queue_en
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
|
||||
|
||||
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota)
|
||||
{
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
@@ -1108,7 +1108,7 @@ void rt2800_txdone(struct rt2x00_dev *rt
|
||||
u8 qid;
|
||||
bool match;
|
||||
|
||||
- while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
|
||||
+ while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
|
||||
/*
|
||||
* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
|
||||
* guaranteed to be one of the TX QIDs .
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -195,7 +195,7 @@ void rt2800_process_rxwi(struct queue_en
|
||||
|
||||
void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
|
||||
bool match);
|
||||
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
|
||||
void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
|
||||
bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -255,20 +255,6 @@ void rt2800mmio_autowake_tasklet(unsigne
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
|
||||
|
||||
-static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- bool timeout = false;
|
||||
-
|
||||
- while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
|
||||
- (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
|
||||
-
|
||||
- rt2800_txdone(rt2x00dev);
|
||||
-
|
||||
- if (timeout)
|
||||
- rt2800_txdone_nostatus(rt2x00dev);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 status;
|
||||
@@ -305,14 +291,11 @@ void rt2800mmio_txstatus_tasklet(unsigne
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
|
||||
|
||||
- do {
|
||||
- rt2800mmio_txdone(rt2x00dev);
|
||||
+ rt2800_txdone(rt2x00dev, 16);
|
||||
|
||||
- } while (rt2800mmio_fetch_txstatus(rt2x00dev));
|
||||
+ if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
|
||||
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
|
||||
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
- rt2800mmio_enable_interrupt(rt2x00dev,
|
||||
- INT_SOURCE_CSR_TX_FIFO_STATUS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
|
||||
|
||||
@@ -339,8 +322,10 @@ irqreturn_t rt2800mmio_interrupt(int irq
|
||||
mask = ~reg;
|
||||
|
||||
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
|
||||
+ rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
|
||||
rt2800mmio_fetch_txstatus(rt2x00dev);
|
||||
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
+ if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
|
||||
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
}
|
||||
|
||||
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
|
||||
@@ -500,7 +485,8 @@ void rt2800mmio_flush_queue(struct data_
|
||||
*/
|
||||
if (tx_queue) {
|
||||
tasklet_disable(&rt2x00dev->txstatus_tasklet);
|
||||
- rt2800mmio_txdone(rt2x00dev);
|
||||
+ rt2800_txdone(rt2x00dev, UINT_MAX);
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
tasklet_enable(&rt2x00dev->txstatus_tasklet);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -480,7 +480,7 @@ static void rt2800usb_work_txdone(struct
|
||||
while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
|
||||
rt2800_txstatus_timeout(rt2x00dev)) {
|
||||
|
||||
- rt2800_txdone(rt2x00dev);
|
||||
+ rt2800_txdone(rt2x00dev, UINT_MAX);
|
||||
|
||||
rt2800_txdone_nostatus(rt2x00dev);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 11f8ad1656035176bad9d89de7ea0e7fe6d82c32 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:32 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804439
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 22/28] rt2800: new flush implementation for SoC devices
|
||||
|
||||
Use new flush_queue() calback for SoC devices, what was already done for
|
||||
PCIe devices.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800soc.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -203,7 +203,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.start_queue = rt2800mmio_start_queue,
|
||||
.kick_queue = rt2800mmio_kick_queue,
|
||||
.stop_queue = rt2800mmio_stop_queue,
|
||||
- .flush_queue = rt2x00mmio_flush_queue,
|
||||
+ .flush_queue = rt2800mmio_flush_queue,
|
||||
.write_tx_desc = rt2800mmio_write_tx_desc,
|
||||
.write_tx_data = rt2800_write_tx_data,
|
||||
.write_beacon = rt2800_write_beacon,
|
||||
@@ -0,0 +1,106 @@
|
||||
From 2bbea7645c3d095014a080db170941818650e141 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:33 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804441
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 23/28] rt2800: move txstatus pending routine
|
||||
|
||||
Move rt2800usb_txstatus_pending routine to rt2800lib. It will be reused
|
||||
by rt2800mmio code.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 17 ++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 22 +++----------------
|
||||
3 files changed, 21 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1183,6 +1183,23 @@ bool rt2800_txstatus_timeout(struct rt2x
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
|
||||
|
||||
+/*
|
||||
+ * test if there is an entry in any TX queue for which DMA is done
|
||||
+ * but the TX status has not been returned yet
|
||||
+ */
|
||||
+bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct data_queue *queue;
|
||||
+
|
||||
+ tx_queue_for_each(rt2x00dev, queue) {
|
||||
+ if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
|
||||
+ rt2x00queue_get_entry(queue, Q_INDEX_DONE))
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_txstatus_pending);
|
||||
+
|
||||
void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_queue *queue;
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -198,6 +198,7 @@ void rt2800_txdone_entry(struct queue_en
|
||||
void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
|
||||
void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
|
||||
bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
|
||||
+bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
|
||||
void rt2800_clear_beacon(struct queue_entry *entry);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -100,22 +100,6 @@ static void rt2800usb_stop_queue(struct
|
||||
}
|
||||
}
|
||||
|
||||
-/*
|
||||
- * test if there is an entry in any TX queue for which DMA is done
|
||||
- * but the TX status has not been returned yet
|
||||
- */
|
||||
-static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- struct data_queue *queue;
|
||||
-
|
||||
- tx_queue_for_each(rt2x00dev, queue) {
|
||||
- if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
|
||||
- rt2x00queue_get_entry(queue, Q_INDEX_DONE))
|
||||
- return true;
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
#define TXSTATUS_READ_INTERVAL 1000000
|
||||
|
||||
static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -145,7 +129,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
|
||||
if (rt2800_txstatus_timeout(rt2x00dev))
|
||||
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
|
||||
|
||||
- if (rt2800usb_txstatus_pending(rt2x00dev)) {
|
||||
+ if (rt2800_txstatus_pending(rt2x00dev)) {
|
||||
/* Read register after 1 ms */
|
||||
hrtimer_start(&rt2x00dev->txstatus_timer,
|
||||
TXSTATUS_READ_INTERVAL,
|
||||
@@ -160,7 +144,7 @@ stop_reading:
|
||||
* clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
|
||||
* here again if status reading is needed.
|
||||
*/
|
||||
- if (rt2800usb_txstatus_pending(rt2x00dev) &&
|
||||
+ if (rt2800_txstatus_pending(rt2x00dev) &&
|
||||
!test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
|
||||
return true;
|
||||
else
|
||||
@@ -489,7 +473,7 @@ static void rt2800usb_work_txdone(struct
|
||||
* if the medium is busy, thus the TX_STA_FIFO entry is
|
||||
* also delayed -> use a timer to retrieve it.
|
||||
*/
|
||||
- if (rt2800usb_txstatus_pending(rt2x00dev))
|
||||
+ if (rt2800_txstatus_pending(rt2x00dev))
|
||||
rt2800usb_async_read_tx_status(rt2x00dev);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
From f6a9618198e190a2ba09ce3f0aa8e9ee1763bd38 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:34 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804443
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 24/28] rt2800mmio: fetch tx status changes
|
||||
|
||||
Prepare to use rt2800mmio_fetch_txstatus() in concurrent manner and drop
|
||||
return value since is not longer needed.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -255,12 +255,12 @@ void rt2800mmio_autowake_tasklet(unsigne
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
|
||||
|
||||
-static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
|
||||
+static void rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 status;
|
||||
- bool more = false;
|
||||
+ unsigned long flags;
|
||||
|
||||
- /* FIXEME: rewrite this comment
|
||||
+ /*
|
||||
* The TX_FIFO_STATUS interrupt needs special care. We should
|
||||
* read TX_STA_FIFO but we should do it immediately as otherwise
|
||||
* the register can overflow and we would lose status reports.
|
||||
@@ -271,20 +271,21 @@ static bool rt2800mmio_fetch_txstatus(st
|
||||
* because we can schedule the tasklet multiple times (when the
|
||||
* interrupt fires again during tx status processing).
|
||||
*
|
||||
- * txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS
|
||||
- * disabled so have only one producer and one consumer - we don't
|
||||
- * need to lock the kfifo.
|
||||
+ * We also read statuses from tx status timeout timer, use
|
||||
+ * lock to prevent concurent writes to fifo.
|
||||
*/
|
||||
+
|
||||
+ spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
|
||||
+
|
||||
while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
|
||||
status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
|
||||
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
|
||||
break;
|
||||
|
||||
kfifo_put(&rt2x00dev->txstatus_fifo, status);
|
||||
- more = true;
|
||||
}
|
||||
|
||||
- return more;
|
||||
+ spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
|
||||
}
|
||||
|
||||
void rt2800mmio_txstatus_tasklet(unsigned long data)
|
||||
@@ -0,0 +1,194 @@
|
||||
From 175c2548332b45b144af673e70fdbb1a947d7aba Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:35 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804445
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 25/28] rt2800mmio: use timer and work for handling tx statuses
|
||||
timeouts
|
||||
|
||||
Sometimes we can get into situation when there are pending statuses,
|
||||
but we do not get INT_SOURCE_CSR_TX_FIFO_STATUS. Handle this situation
|
||||
by arming timeout timer and read statuses (it will fix case when
|
||||
we just do not have irq) and queue work to handle case we missed
|
||||
statues from hardware FIFO.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 81 +++++++++++++++++--
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800pci.c | 2 +-
|
||||
.../net/wireless/ralink/rt2x00/rt2800soc.c | 2 +-
|
||||
.../net/wireless/ralink/rt2x00/rt2x00dev.c | 4 +
|
||||
5 files changed, 82 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -426,6 +426,9 @@ void rt2800mmio_start_queue(struct data_
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
|
||||
|
||||
+/* 200 ms */
|
||||
+#define TXSTATUS_TIMEOUT 200000000
|
||||
+
|
||||
void rt2800mmio_kick_queue(struct data_queue *queue)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
@@ -440,6 +443,8 @@ void rt2800mmio_kick_queue(struct data_q
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX);
|
||||
rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
|
||||
entry->entry_idx);
|
||||
+ hrtimer_start(&rt2x00dev->txstatus_timer,
|
||||
+ TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
|
||||
break;
|
||||
case QID_MGMT:
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX);
|
||||
@@ -484,12 +489,8 @@ void rt2800mmio_flush_queue(struct data_
|
||||
* For TX queues schedule completion tasklet to catch
|
||||
* tx status timeouts, othewise just wait.
|
||||
*/
|
||||
- if (tx_queue) {
|
||||
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
|
||||
- rt2800_txdone(rt2x00dev, UINT_MAX);
|
||||
- rt2800_txdone_nostatus(rt2x00dev);
|
||||
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
|
||||
- }
|
||||
+ if (tx_queue)
|
||||
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
|
||||
|
||||
/*
|
||||
* Wait for a little while to give the driver
|
||||
@@ -627,6 +628,10 @@ void rt2800mmio_clear_entry(struct queue
|
||||
word = rt2x00_desc_read(entry_priv->desc, 1);
|
||||
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
|
||||
rt2x00_desc_write(entry_priv->desc, 1, word);
|
||||
+
|
||||
+ /* If last entry stop txstatus timer */
|
||||
+ if (entry->queue->length == 1)
|
||||
+ hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
|
||||
@@ -759,6 +764,70 @@ int rt2800mmio_enable_radio(struct rt2x0
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
|
||||
|
||||
+static void rt2800mmio_work_txdone(struct work_struct *work)
|
||||
+{
|
||||
+ struct rt2x00_dev *rt2x00dev =
|
||||
+ container_of(work, struct rt2x00_dev, txdone_work);
|
||||
+
|
||||
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
+ return;
|
||||
+
|
||||
+ while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
|
||||
+ rt2800_txstatus_timeout(rt2x00dev)) {
|
||||
+
|
||||
+ tasklet_disable(&rt2x00dev->txstatus_tasklet);
|
||||
+ rt2800_txdone(rt2x00dev, UINT_MAX);
|
||||
+ rt2800_txdone_nostatus(rt2x00dev);
|
||||
+ tasklet_enable(&rt2x00dev->txstatus_tasklet);
|
||||
+ }
|
||||
+
|
||||
+ if (rt2800_txstatus_pending(rt2x00dev))
|
||||
+ hrtimer_start(&rt2x00dev->txstatus_timer,
|
||||
+ TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
|
||||
+}
|
||||
+
|
||||
+static enum hrtimer_restart rt2800mmio_tx_sta_fifo_timeout(struct hrtimer *timer)
|
||||
+{
|
||||
+ struct rt2x00_dev *rt2x00dev =
|
||||
+ container_of(timer, struct rt2x00_dev, txstatus_timer);
|
||||
+
|
||||
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!rt2800_txstatus_pending(rt2x00dev))
|
||||
+ goto out;
|
||||
+
|
||||
+ rt2800mmio_fetch_txstatus(rt2x00dev);
|
||||
+ if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
|
||||
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
|
||||
+ else
|
||||
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
|
||||
+out:
|
||||
+ return HRTIMER_NORESTART;
|
||||
+}
|
||||
+
|
||||
+int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ int retval;
|
||||
+
|
||||
+ retval = rt2800_probe_hw(rt2x00dev);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ /*
|
||||
+ * Set txstatus timer function.
|
||||
+ */
|
||||
+ rt2x00dev->txstatus_timer.function = rt2800mmio_tx_sta_fifo_timeout;
|
||||
+
|
||||
+ /*
|
||||
+ * Overwrite TX done handler
|
||||
+ */
|
||||
+ INIT_WORK(&rt2x00dev->txdone_work, rt2800mmio_work_txdone);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800mmio_probe_hw);
|
||||
+
|
||||
MODULE_AUTHOR(DRV_PROJECT);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_DESCRIPTION("rt2800 MMIO library");
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
@@ -153,6 +153,7 @@ void rt2800mmio_stop_queue(struct data_q
|
||||
void rt2800mmio_queue_init(struct data_queue *queue);
|
||||
|
||||
/* Initialization functions */
|
||||
+int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev);
|
||||
bool rt2800mmio_get_entry_state(struct queue_entry *entry);
|
||||
void rt2800mmio_clear_entry(struct queue_entry *entry);
|
||||
int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -346,7 +346,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.tbtt_tasklet = rt2800mmio_tbtt_tasklet,
|
||||
.rxdone_tasklet = rt2800mmio_rxdone_tasklet,
|
||||
.autowake_tasklet = rt2800mmio_autowake_tasklet,
|
||||
- .probe_hw = rt2800_probe_hw,
|
||||
+ .probe_hw = rt2800mmio_probe_hw,
|
||||
.get_firmware_name = rt2800pci_get_firmware_name,
|
||||
.check_firmware = rt2800_check_firmware,
|
||||
.load_firmware = rt2800_load_firmware,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -185,7 +185,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.tbtt_tasklet = rt2800mmio_tbtt_tasklet,
|
||||
.rxdone_tasklet = rt2800mmio_rxdone_tasklet,
|
||||
.autowake_tasklet = rt2800mmio_autowake_tasklet,
|
||||
- .probe_hw = rt2800_probe_hw,
|
||||
+ .probe_hw = rt2800mmio_probe_hw,
|
||||
.get_firmware_name = rt2800soc_get_firmware_name,
|
||||
.check_firmware = rt2800soc_check_firmware,
|
||||
.load_firmware = rt2800soc_load_firmware,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1391,6 +1391,8 @@ int rt2x00lib_probe_dev(struct rt2x00_de
|
||||
mutex_init(&rt2x00dev->conf_mutex);
|
||||
INIT_LIST_HEAD(&rt2x00dev->bar_list);
|
||||
spin_lock_init(&rt2x00dev->bar_list_lock);
|
||||
+ hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
|
||||
+ HRTIMER_MODE_REL);
|
||||
|
||||
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
|
||||
@@ -1515,6 +1517,8 @@ void rt2x00lib_remove_dev(struct rt2x00_
|
||||
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
|
||||
cancel_work_sync(&rt2x00dev->sleep_work);
|
||||
|
||||
+ hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
+
|
||||
/*
|
||||
* Kill the tx status tasklet.
|
||||
*/
|
||||
@@ -0,0 +1,57 @@
|
||||
From 6013a91f15c9dabd668d5736652b9bcfb0ef0378 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:36 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804447
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 26/28] rt2x00: remove last_nostatus_check
|
||||
|
||||
We do not any longer check txstatus timeout from tasklet, so do not need
|
||||
this optimization.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ---------
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 2 --
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 1 -
|
||||
3 files changed, 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1164,15 +1164,6 @@ bool rt2800_txstatus_timeout(struct rt2x
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
|
||||
- if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) {
|
||||
- unsigned long tout = msecs_to_jiffies(1000);
|
||||
-
|
||||
- if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- rt2x00dev->last_nostatus_check = jiffies;
|
||||
-
|
||||
tx_queue_for_each(rt2x00dev, queue) {
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -980,8 +980,6 @@ struct rt2x00_dev {
|
||||
*/
|
||||
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
|
||||
|
||||
- unsigned long last_nostatus_check;
|
||||
-
|
||||
/*
|
||||
* Timer to ensure tx status reports are read (rt2800usb).
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
|
||||
@@ -1042,7 +1042,6 @@ void rt2x00queue_start_queues(struct rt2
|
||||
*/
|
||||
tx_queue_for_each(rt2x00dev, queue)
|
||||
rt2x00queue_start_queue(queue);
|
||||
- rt2x00dev->last_nostatus_check = jiffies;
|
||||
|
||||
rt2x00queue_start_queue(rt2x00dev->rx);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
From 2758f09b22bc08e89e0391486b2d707ad2479599 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:37 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804449
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 27/28] rt2x00: remove not used entry field
|
||||
|
||||
Remove not used any longer queue_entry field and flag.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
|
||||
@@ -361,7 +361,6 @@ enum queue_entry_flags {
|
||||
ENTRY_DATA_PENDING,
|
||||
ENTRY_DATA_IO_FAILED,
|
||||
ENTRY_DATA_STATUS_PENDING,
|
||||
- ENTRY_DATA_STATUS_SET,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -387,8 +386,6 @@ struct queue_entry {
|
||||
|
||||
unsigned int entry_idx;
|
||||
|
||||
- u32 status;
|
||||
-
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From f44e145869bb517460648e4ed71b7e9001964d06 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 9 Feb 2019 12:08:38 +0100
|
||||
X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
X-Patchwork-Id: 10804451
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Subject: [PATCH 28/28] rt2x00mmio: remove legacy comment
|
||||
|
||||
Remove comment about fields that ware removed.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
|
||||
@@ -80,8 +80,6 @@ int rt2x00mmio_regbusy_read(struct rt2x0
|
||||
*
|
||||
* @desc: Pointer to device descriptor
|
||||
* @desc_dma: DMA pointer to &desc.
|
||||
- * @data: Pointer to device's entry memory.
|
||||
- * @data_dma: DMA pointer to &data.
|
||||
*/
|
||||
struct queue_entry_priv_mmio {
|
||||
__le32 *desc;
|
||||
@@ -0,0 +1,959 @@
|
||||
From d0e61a0f7cca51ce340a5a73595189972122ff25 Mon Sep 17 00:00:00 2001
|
||||
From: Gabor Juhos <juhosg@openwrt.org>
|
||||
Date: Wed, 24 Apr 2019 09:49:24 +0200
|
||||
Subject: [PATCH] rt2x00: add RT3883 support
|
||||
|
||||
Patch add support for RT3883 chip. Code was taken direclty
|
||||
from openwrt project and merge into one patch.
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800.h | 19 +-
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 598 +++++++++++++++++-
|
||||
.../net/wireless/ralink/rt2x00/rt2800soc.c | 9 +-
|
||||
3 files changed, 607 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
@@ -48,7 +48,8 @@
|
||||
* RF2853 2.4G/5G 3T3R
|
||||
* RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
|
||||
* RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
|
||||
- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
|
||||
+ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593)
|
||||
+ * RF3853 2.4G/5G 3T3R(RT3883/RT3662)
|
||||
* RF5592 2.4G/5G 2T2R
|
||||
* RF3070 2.4G 1T1R
|
||||
* RF5360 2.4G 1T1R
|
||||
@@ -72,6 +73,7 @@
|
||||
#define RF5592 0x000f
|
||||
#define RF3070 0x3070
|
||||
#define RF3290 0x3290
|
||||
+#define RF3853 0x3853
|
||||
#define RF5350 0x5350
|
||||
#define RF5360 0x5360
|
||||
#define RF5362 0x5362
|
||||
@@ -1726,6 +1728,20 @@
|
||||
#define TX_PWR_CFG_9B_STBC_MCS7 FIELD32(0x000000ff)
|
||||
|
||||
/*
|
||||
+ * TX_TXBF_CFG:
|
||||
+ */
|
||||
+#define TX_TXBF_CFG_0 0x138c
|
||||
+#define TX_TXBF_CFG_1 0x13a4
|
||||
+#define TX_TXBF_CFG_2 0x13a8
|
||||
+#define TX_TXBF_CFG_3 0x13ac
|
||||
+
|
||||
+/*
|
||||
+ * TX_FBK_CFG_3S:
|
||||
+ */
|
||||
+#define TX_FBK_CFG_3S_0 0x13c4
|
||||
+#define TX_FBK_CFG_3S_1 0x13c8
|
||||
+
|
||||
+/*
|
||||
* RX_FILTER_CFG: RX configuration register.
|
||||
*/
|
||||
#define RX_FILTER_CFG 0x1400
|
||||
@@ -2296,6 +2312,7 @@ struct mac_iveiv_entry {
|
||||
/*
|
||||
* RFCSR 2:
|
||||
*/
|
||||
+#define RFCSR2_RESCAL_BP FIELD8(0x40)
|
||||
#define RFCSR2_RESCAL_EN FIELD8(0x80)
|
||||
#define RFCSR2_RX2_EN_MT7620 FIELD8(0x02)
|
||||
#define RFCSR2_TX2_EN_MT7620 FIELD8(0x20)
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -381,7 +381,8 @@ static unsigned int rt2800_eeprom_word_i
|
||||
wiphy_name(rt2x00dev->hw->wiphy), word))
|
||||
return 0;
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
map = rt2800_eeprom_map_ext;
|
||||
else
|
||||
map = rt2800_eeprom_map;
|
||||
@@ -590,6 +591,7 @@ void rt2800_get_txwi_rxwi_size(struct rt
|
||||
{
|
||||
switch (rt2x00dev->chip.rt) {
|
||||
case RT3593:
|
||||
+ case RT3883:
|
||||
*txwi_size = TXWI_DESC_SIZE_4WORDS;
|
||||
*rxwi_size = RXWI_DESC_SIZE_5WORDS;
|
||||
break;
|
||||
@@ -2180,7 +2182,8 @@ void rt2800_config_ant(struct rt2x00_dev
|
||||
rt2800_bbp_write(rt2x00dev, 3, r3);
|
||||
rt2800_bbp_write(rt2x00dev, 1, r1);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
if (ant->rx_chain_num == 1)
|
||||
rt2800_bbp_write(rt2x00dev, 86, 0x00);
|
||||
else
|
||||
@@ -2202,7 +2205,8 @@ static void rt2800_config_lna_gain(struc
|
||||
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
|
||||
lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
|
||||
} else if (libconf->rf.channel <= 128) {
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
|
||||
lna_gain = rt2x00_get_field16(eeprom,
|
||||
EEPROM_EXT_LNA2_A1);
|
||||
@@ -2212,7 +2216,8 @@ static void rt2800_config_lna_gain(struc
|
||||
EEPROM_RSSI_BG2_LNA_A1);
|
||||
}
|
||||
} else {
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
|
||||
lna_gain = rt2x00_get_field16(eeprom,
|
||||
EEPROM_EXT_LNA2_A2);
|
||||
@@ -2880,6 +2885,211 @@ static void rt2800_config_channel_rf3053
|
||||
}
|
||||
}
|
||||
|
||||
+static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
|
||||
+ struct ieee80211_conf *conf,
|
||||
+ struct rf_channel *rf,
|
||||
+ struct channel_info *info)
|
||||
+{
|
||||
+ u8 rfcsr;
|
||||
+ u8 bbp;
|
||||
+ u8 pwr1, pwr2, pwr3;
|
||||
+
|
||||
+ const bool txbf_enabled = false; /* TODO */
|
||||
+
|
||||
+ /* TODO: add band selection */
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
|
||||
+ else if (rf->channel < 132)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
|
||||
+
|
||||
+ switch (rt2x00dev->default_ant.tx_chain_num) {
|
||||
+ case 3:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
|
||||
+ /* fallthrough */
|
||||
+ case 2:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
|
||||
+ /* fallthrough */
|
||||
+ case 1:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ switch (rt2x00dev->default_ant.rx_chain_num) {
|
||||
+ case 3:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
|
||||
+ /* fallthrough */
|
||||
+ case 2:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
|
||||
+ /* fallthrough */
|
||||
+ case 1:
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
|
||||
+ break;
|
||||
+ }
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
|
||||
+
|
||||
+ rt2800_freq_cal_mode1(rt2x00dev);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
|
||||
+ if (!conf_is_ht40(conf))
|
||||
+ rfcsr &= ~(0x06);
|
||||
+ else
|
||||
+ rfcsr |= 0x06;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
|
||||
+
|
||||
+ if (conf_is_ht40(conf))
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
|
||||
+
|
||||
+ /* loopback RF_BS */
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 36);
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
|
||||
+ else
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rfcsr = 0x23;
|
||||
+ else if (rf->channel < 100)
|
||||
+ rfcsr = 0x36;
|
||||
+ else if (rf->channel < 132)
|
||||
+ rfcsr = 0x32;
|
||||
+ else
|
||||
+ rfcsr = 0x30;
|
||||
+
|
||||
+ if (txbf_enabled)
|
||||
+ rfcsr |= 0x40;
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rfcsr = 0xbb;
|
||||
+ else if (rf->channel < 100)
|
||||
+ rfcsr = 0xeb;
|
||||
+ else if (rf->channel < 132)
|
||||
+ rfcsr = 0xb3;
|
||||
+ else
|
||||
+ rfcsr = 0x9b;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
|
||||
+
|
||||
+ if (rf->channel <= 14)
|
||||
+ rfcsr = 0x8e;
|
||||
+ else
|
||||
+ rfcsr = 0x8a;
|
||||
+
|
||||
+ if (txbf_enabled)
|
||||
+ rfcsr |= 0x20;
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 52);
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
|
||||
+
|
||||
+ if (rf->channel <= 14) {
|
||||
+ pwr1 = info->default_power1 & 0x1f;
|
||||
+ pwr2 = info->default_power2 & 0x1f;
|
||||
+ pwr3 = info->default_power3 & 0x1f;
|
||||
+ } else {
|
||||
+ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
|
||||
+ (info->default_power1 & 0x7);
|
||||
+ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
|
||||
+ (info->default_power2 & 0x7);
|
||||
+ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
|
||||
+ (info->default_power3 & 0x7);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
|
||||
+ rf->channel, pwr1, pwr2, pwr3);
|
||||
+
|
||||
+ bbp = (info->default_power1 >> 5) |
|
||||
+ ((info->default_power2 & 0xe0) >> 1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 109, bbp);
|
||||
+
|
||||
+ bbp = rt2800_bbp_read(rt2x00dev, 110);
|
||||
+ bbp &= 0x0f;
|
||||
+ bbp |= (info->default_power3 & 0xe0) >> 1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 110, bbp);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 57);
|
||||
+ if (rf->channel <= 14)
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
|
||||
+ else
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
|
||||
+
|
||||
+ /* Enable RF tuning */
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
|
||||
+
|
||||
+ udelay(2000);
|
||||
+
|
||||
+ bbp = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+ /* clear update flag */
|
||||
+ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
|
||||
+ rt2800_bbp_write(rt2x00dev, 49, bbp);
|
||||
+
|
||||
+ /* TODO: add calibration for TxBF */
|
||||
+}
|
||||
+
|
||||
#define POWER_BOUND 0x27
|
||||
#define POWER_BOUND_5G 0x2b
|
||||
|
||||
@@ -3683,19 +3893,51 @@ static char rt2800_txpower_to_dev(struct
|
||||
unsigned int channel,
|
||||
char txpower)
|
||||
{
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
|
||||
|
||||
if (channel <= 14)
|
||||
return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
|
||||
MAX_A_TXPOWER_3593);
|
||||
else
|
||||
return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
|
||||
}
|
||||
|
||||
+static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev,
|
||||
+ struct rf_channel *rf)
|
||||
+{
|
||||
+ u8 bbp;
|
||||
+
|
||||
+ bbp = (rf->channel > 14) ? 0x48 : 0x38;
|
||||
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 69, 0x12);
|
||||
+
|
||||
+ if (rf->channel <= 14) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
||||
+ } else {
|
||||
+ /* Disable CCK packet detection */
|
||||
+ rt2800_bbp_write(rt2x00dev, 70, 0x00);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 73, 0x10);
|
||||
+
|
||||
+ if (rf->channel > 14) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 62, 0x1d);
|
||||
+ rt2800_bbp_write(rt2x00dev, 63, 0x1d);
|
||||
+ rt2800_bbp_write(rt2x00dev, 64, 0x1d);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 62, 0x2d);
|
||||
+ rt2800_bbp_write(rt2x00dev, 63, 0x2d);
|
||||
+ rt2800_bbp_write(rt2x00dev, 64, 0x2d);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
struct ieee80211_conf *conf,
|
||||
struct rf_channel *rf,
|
||||
@@ -3714,6 +3956,12 @@ static void rt2800_config_channel(struct
|
||||
rt2800_txpower_to_dev(rt2x00dev, rf->channel,
|
||||
info->default_power3);
|
||||
|
||||
+ switch (rt2x00dev->chip.rt) {
|
||||
+ case RT3883:
|
||||
+ rt3883_bbp_adjust(rt2x00dev, rf);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
switch (rt2x00dev->chip.rf) {
|
||||
case RF2020:
|
||||
case RF3020:
|
||||
@@ -3734,6 +3982,9 @@ static void rt2800_config_channel(struct
|
||||
case RF3322:
|
||||
rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
|
||||
break;
|
||||
+ case RF3853:
|
||||
+ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
|
||||
+ break;
|
||||
case RF3070:
|
||||
case RF5350:
|
||||
case RF5360:
|
||||
@@ -3815,6 +4066,15 @@ static void rt2800_config_channel(struct
|
||||
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
|
||||
rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
|
||||
rt2800_bbp_write(rt2x00dev, 77, 0x98);
|
||||
+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
|
||||
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
|
||||
+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
|
||||
+
|
||||
+ if (rt2x00dev->default_ant.rx_chain_num > 1)
|
||||
+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
|
||||
+ else
|
||||
+ rt2800_bbp_write(rt2x00dev, 86, 0);
|
||||
} else {
|
||||
rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
|
||||
rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
|
||||
@@ -3828,6 +4088,7 @@ static void rt2800_config_channel(struct
|
||||
!rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
|
||||
rt2800_bbp_write(rt2x00dev, 82, 0x62);
|
||||
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
|
||||
rt2800_bbp_write(rt2x00dev, 75, 0x46);
|
||||
} else {
|
||||
if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
@@ -3836,19 +4097,22 @@ static void rt2800_config_channel(struct
|
||||
rt2800_bbp_write(rt2x00dev, 82, 0x84);
|
||||
rt2800_bbp_write(rt2x00dev, 75, 0x50);
|
||||
}
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
rt2800_bbp_write(rt2x00dev, 83, 0x8a);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (rt2x00_rt(rt2x00dev, RT3572))
|
||||
rt2800_bbp_write(rt2x00dev, 82, 0x94);
|
||||
- else if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ else if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
rt2800_bbp_write(rt2x00dev, 82, 0x82);
|
||||
else if (!rt2x00_rt(rt2x00dev, RT6352))
|
||||
rt2800_bbp_write(rt2x00dev, 82, 0xf2);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
rt2800_bbp_write(rt2x00dev, 83, 0x9a);
|
||||
|
||||
if (rt2x00_has_cap_external_lna_a(rt2x00dev))
|
||||
@@ -3984,6 +4248,23 @@ static void rt2800_config_channel(struct
|
||||
usleep_range(1000, 1500);
|
||||
}
|
||||
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
+ if (!conf_is_ht40(conf))
|
||||
+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
|
||||
+ else
|
||||
+ rt2800_bbp_write(rt2x00dev, 105, 0x04);
|
||||
+
|
||||
+ /* AGC init */
|
||||
+ if (rf->channel <= 14)
|
||||
+ reg = 0x2e + rt2x00dev->lna_gain;
|
||||
+ else
|
||||
+ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3);
|
||||
+
|
||||
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
|
||||
+
|
||||
+ usleep_range(1000, 1500);
|
||||
+ }
|
||||
+
|
||||
if (rt2x00_rt(rt2x00dev, RT5592) || rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
reg = 0x10;
|
||||
if (!conf_is_ht40(conf)) {
|
||||
@@ -4243,6 +4524,9 @@ static u8 rt2800_compensate_txpower(stru
|
||||
if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
return min_t(u8, txpower, 0xc);
|
||||
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3883))
|
||||
+ return min_t(u8, txpower, 0xf);
|
||||
+
|
||||
if (rt2x00_has_cap_power_limit(rt2x00dev)) {
|
||||
/*
|
||||
* Check if eirp txpower exceed txpower_limit.
|
||||
@@ -5004,7 +5288,8 @@ static void rt2800_config_txpower(struct
|
||||
struct ieee80211_channel *chan,
|
||||
int power_level)
|
||||
{
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
|
||||
else if (rt2x00_rt(rt2x00dev, RT6352))
|
||||
rt2800_config_txpower_rt6352(rt2x00dev, chan, power_level);
|
||||
@@ -5051,6 +5336,7 @@ void rt2800_vco_calibration(struct rt2x0
|
||||
case RF3053:
|
||||
case RF3070:
|
||||
case RF3290:
|
||||
+ case RF3853:
|
||||
case RF5350:
|
||||
case RF5360:
|
||||
case RF5362:
|
||||
@@ -5251,7 +5537,8 @@ static u8 rt2800_get_default_vgc(struct
|
||||
else
|
||||
vgc = 0x2e + rt2x00dev->lna_gain;
|
||||
} else { /* 5GHZ band */
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
|
||||
else if (rt2x00_rt(rt2x00dev, RT5592))
|
||||
vgc = 0x24 + (2 * rt2x00dev->lna_gain);
|
||||
@@ -5271,7 +5558,8 @@ static inline void rt2800_set_vgc(struct
|
||||
{
|
||||
if (qual->vgc_level != vgc_level) {
|
||||
if (rt2x00_rt(rt2x00dev, RT3572) ||
|
||||
- rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
|
||||
vgc_level);
|
||||
} else if (rt2x00_rt(rt2x00dev, RT5592)) {
|
||||
@@ -5318,6 +5606,11 @@ void rt2800_link_tuner(struct rt2x00_dev
|
||||
}
|
||||
break;
|
||||
|
||||
+ case RT3883:
|
||||
+ if (qual->rssi > -65)
|
||||
+ vgc += 0x10;
|
||||
+ break;
|
||||
+
|
||||
case RT5592:
|
||||
if (qual->rssi > -65)
|
||||
vgc += 0x20;
|
||||
@@ -5470,6 +5763,12 @@ static int rt2800_init_registers(struct
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2,
|
||||
0x00000000);
|
||||
}
|
||||
+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
|
||||
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
|
||||
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
|
||||
+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
|
||||
+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
|
||||
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
|
||||
rt2x00_rt(rt2x00dev, RT5392) ||
|
||||
rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
@@ -5683,6 +5982,11 @@ static int rt2800_init_registers(struct
|
||||
reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
|
||||
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
|
||||
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
|
||||
+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
|
||||
+ }
|
||||
+
|
||||
reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
|
||||
rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7);
|
||||
rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES,
|
||||
@@ -6299,6 +6603,47 @@ static void rt2800_init_bbp_3593(struct
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
|
||||
}
|
||||
|
||||
+static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ rt2800_init_bbp_early(rt2x00dev);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, 0x50);
|
||||
+ rt2800_bbp_write(rt2x00dev, 47, 0x48);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
|
||||
+ rt2800_bbp_write(rt2x00dev, 88, 0x90);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 92, 0x02);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 104, 0x92);
|
||||
+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
|
||||
+ rt2800_bbp_write(rt2x00dev, 106, 0x12);
|
||||
+ rt2800_bbp_write(rt2x00dev, 120, 0x50);
|
||||
+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
|
||||
+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
|
||||
+
|
||||
+ /* Set ITxBF timeout to 0x9C40=1000msec */
|
||||
+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
|
||||
+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
|
||||
+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
|
||||
+
|
||||
+ /* Reprogram the inband interface to put right values in RXWI */
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
|
||||
+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
|
||||
+}
|
||||
+
|
||||
static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int ant, div_mode;
|
||||
@@ -6743,6 +7088,9 @@ static void rt2800_init_bbp(struct rt2x0
|
||||
case RT3593:
|
||||
rt2800_init_bbp_3593(rt2x00dev);
|
||||
return;
|
||||
+ case RT3883:
|
||||
+ rt2800_init_bbp_3883(rt2x00dev);
|
||||
+ return;
|
||||
case RT5390:
|
||||
case RT5392:
|
||||
rt2800_init_bbp_53xx(rt2x00dev);
|
||||
@@ -7614,6 +7962,144 @@ static void rt2800_init_rfcsr_5350(struc
|
||||
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
|
||||
}
|
||||
|
||||
+static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 rfcsr;
|
||||
+
|
||||
+ /* TODO: get the actual ECO value from the SoC */
|
||||
+ const unsigned int eco = 5;
|
||||
+
|
||||
+ rt2800_rf_init_calibration(rt2x00dev, 2);
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x20);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x08);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
|
||||
+
|
||||
+ /* RFCSR 17 will be initialized later based on the
|
||||
+ * frequency offset stored in the EEPROM
|
||||
+ */
|
||||
+
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 41, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 42, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 53, 0x76);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 54, 0x76);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x76);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 58, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
|
||||
+
|
||||
+ /* TODO: rx filter calibration? */
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
|
||||
+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
|
||||
+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
|
||||
+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
|
||||
+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
|
||||
+
|
||||
+ if (eco == 5) {
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x32);
|
||||
+ }
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
|
||||
+ msleep(1);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
|
||||
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
|
||||
+ rfcsr |= 0xc0;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
|
||||
+ rfcsr |= 0x20;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 46);
|
||||
+ rfcsr |= 0x20;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr);
|
||||
+
|
||||
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
|
||||
+ rfcsr &= ~0xee;
|
||||
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
|
||||
+}
|
||||
+
|
||||
static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt2800_rf_init_calibration(rt2x00dev, 2);
|
||||
@@ -8456,6 +8942,9 @@ static void rt2800_init_rfcsr(struct rt2
|
||||
case RT3390:
|
||||
rt2800_init_rfcsr_3390(rt2x00dev);
|
||||
break;
|
||||
+ case RT3883:
|
||||
+ rt2800_init_rfcsr_3883(rt2x00dev);
|
||||
+ break;
|
||||
case RT3572:
|
||||
rt2800_init_rfcsr_3572(rt2x00dev);
|
||||
break;
|
||||
@@ -8661,7 +9150,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
|
||||
{
|
||||
u16 word;
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
return 0;
|
||||
|
||||
word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
|
||||
@@ -8675,7 +9165,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
|
||||
{
|
||||
u16 word;
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593))
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883))
|
||||
return 0;
|
||||
|
||||
word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
|
||||
@@ -8781,7 +9272,8 @@ static int rt2800_validate_eeprom(struct
|
||||
word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
|
||||
- if (!rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
|
||||
+ !rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
|
||||
@@ -8801,7 +9293,8 @@ static int rt2800_validate_eeprom(struct
|
||||
word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
|
||||
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
|
||||
- if (!rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
|
||||
+ !rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
|
||||
@@ -8809,7 +9302,8 @@ static int rt2800_validate_eeprom(struct
|
||||
}
|
||||
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3593)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT3883)) {
|
||||
word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
|
||||
if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
|
||||
rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
|
||||
@@ -8848,6 +9342,8 @@ static int rt2800_init_eeprom(struct rt2
|
||||
rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID);
|
||||
else if (rt2x00_rt(rt2x00dev, RT3352))
|
||||
rf = RF3322;
|
||||
+ else if (rt2x00_rt(rt2x00dev, RT3883))
|
||||
+ rf = RF3853;
|
||||
else if (rt2x00_rt(rt2x00dev, RT5350))
|
||||
rf = RF5350;
|
||||
else
|
||||
@@ -8868,6 +9364,7 @@ static int rt2800_init_eeprom(struct rt2
|
||||
case RF3290:
|
||||
case RF3320:
|
||||
case RF3322:
|
||||
+ case RF3853:
|
||||
case RF5350:
|
||||
case RF5360:
|
||||
case RF5362:
|
||||
@@ -9154,6 +9651,66 @@ static const struct rf_channel rf_vals_3
|
||||
{14, 0xF0, 2, 0x18},
|
||||
};
|
||||
|
||||
+static const struct rf_channel rf_vals_3853[] = {
|
||||
+ {1, 241, 6, 2},
|
||||
+ {2, 241, 6, 7},
|
||||
+ {3, 242, 6, 2},
|
||||
+ {4, 242, 6, 7},
|
||||
+ {5, 243, 6, 2},
|
||||
+ {6, 243, 6, 7},
|
||||
+ {7, 244, 6, 2},
|
||||
+ {8, 244, 6, 7},
|
||||
+ {9, 245, 6, 2},
|
||||
+ {10, 245, 6, 7},
|
||||
+ {11, 246, 6, 2},
|
||||
+ {12, 246, 6, 7},
|
||||
+ {13, 247, 6, 2},
|
||||
+ {14, 248, 6, 4},
|
||||
+
|
||||
+ {36, 0x56, 8, 4},
|
||||
+ {38, 0x56, 8, 6},
|
||||
+ {40, 0x56, 8, 8},
|
||||
+ {44, 0x57, 8, 0},
|
||||
+ {46, 0x57, 8, 2},
|
||||
+ {48, 0x57, 8, 4},
|
||||
+ {52, 0x57, 8, 8},
|
||||
+ {54, 0x57, 8, 10},
|
||||
+ {56, 0x58, 8, 0},
|
||||
+ {60, 0x58, 8, 4},
|
||||
+ {62, 0x58, 8, 6},
|
||||
+ {64, 0x58, 8, 8},
|
||||
+
|
||||
+ {100, 0x5b, 8, 8},
|
||||
+ {102, 0x5b, 8, 10},
|
||||
+ {104, 0x5c, 8, 0},
|
||||
+ {108, 0x5c, 8, 4},
|
||||
+ {110, 0x5c, 8, 6},
|
||||
+ {112, 0x5c, 8, 8},
|
||||
+ {114, 0x5c, 8, 10},
|
||||
+ {116, 0x5d, 8, 0},
|
||||
+ {118, 0x5d, 8, 2},
|
||||
+ {120, 0x5d, 8, 4},
|
||||
+ {124, 0x5d, 8, 8},
|
||||
+ {126, 0x5d, 8, 10},
|
||||
+ {128, 0x5e, 8, 0},
|
||||
+ {132, 0x5e, 8, 4},
|
||||
+ {134, 0x5e, 8, 6},
|
||||
+ {136, 0x5e, 8, 8},
|
||||
+ {140, 0x5f, 8, 0},
|
||||
+
|
||||
+ {149, 0x5f, 8, 9},
|
||||
+ {151, 0x5f, 8, 11},
|
||||
+ {153, 0x60, 8, 1},
|
||||
+ {157, 0x60, 8, 5},
|
||||
+ {159, 0x60, 8, 7},
|
||||
+ {161, 0x60, 8, 9},
|
||||
+ {165, 0x61, 8, 1},
|
||||
+ {167, 0x61, 8, 3},
|
||||
+ {169, 0x61, 8, 5},
|
||||
+ {171, 0x61, 8, 7},
|
||||
+ {173, 0x61, 8, 9},
|
||||
+};
|
||||
+
|
||||
static const struct rf_channel rf_vals_5592_xtal20[] = {
|
||||
/* Channel, N, K, mod, R */
|
||||
{1, 482, 4, 10, 3},
|
||||
@@ -9417,6 +9974,11 @@ static int rt2800_probe_hw_mode(struct r
|
||||
spec->channels = rf_vals_3x;
|
||||
break;
|
||||
|
||||
+ case RF3853:
|
||||
+ spec->num_channels = ARRAY_SIZE(rf_vals_3853);
|
||||
+ spec->channels = rf_vals_3853;
|
||||
+ break;
|
||||
+
|
||||
case RF5592:
|
||||
reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
|
||||
if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
|
||||
@@ -9536,6 +10098,7 @@ static int rt2800_probe_hw_mode(struct r
|
||||
case RF3053:
|
||||
case RF3070:
|
||||
case RF3290:
|
||||
+ case RF3853:
|
||||
case RF5350:
|
||||
case RF5360:
|
||||
case RF5362:
|
||||
@@ -9578,6 +10141,7 @@ static int rt2800_probe_rt(struct rt2x00
|
||||
case RT3390:
|
||||
case RT3572:
|
||||
case RT3593:
|
||||
+ case RT3883:
|
||||
case RT5350:
|
||||
case RT5390:
|
||||
case RT5392:
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s
|
||||
|
||||
static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
+ u32 reg;
|
||||
+
|
||||
rt2800_disable_radio(rt2x00dev);
|
||||
rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
|
||||
- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
|
||||
+
|
||||
+ reg = 0;
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3883))
|
||||
+ rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1);
|
||||
+
|
||||
+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
|
||||
}
|
||||
|
||||
static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -0,0 +1,56 @@
|
||||
From 9f3e3323e9966d9f21bea0c81b1acb36c0e15cec Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:54 +0200
|
||||
Subject: [PATCH 01/15] rt2x00: allow to specify watchdog interval
|
||||
|
||||
Allow subdriver to change watchdog interval by intialize
|
||||
link->watchdog_interval value before rt2x00link_register().
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 13 +++++++++----
|
||||
2 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -336,6 +336,7 @@ struct link {
|
||||
* to bring the device/driver back into the desired state.
|
||||
*/
|
||||
struct delayed_work watchdog_work;
|
||||
+ unsigned int watchdog_interval;
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic AGC adjustments.
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
|
||||
@@ -398,7 +398,7 @@ void rt2x00link_start_watchdog(struct rt
|
||||
rt2x00dev->ops->lib->watchdog)
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->watchdog_work,
|
||||
- WATCHDOG_INTERVAL);
|
||||
+ link->watchdog_interval);
|
||||
}
|
||||
|
||||
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
|
||||
@@ -424,11 +424,16 @@ static void rt2x00link_watchdog(struct w
|
||||
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->watchdog_work,
|
||||
- WATCHDOG_INTERVAL);
|
||||
+ link->watchdog_interval);
|
||||
}
|
||||
|
||||
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
- INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
|
||||
- INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
|
||||
+ struct link *link = &rt2x00dev->link;
|
||||
+
|
||||
+ INIT_DELAYED_WORK(&link->work, rt2x00link_tuner);
|
||||
+ INIT_DELAYED_WORK(&link->watchdog_work, rt2x00link_watchdog);
|
||||
+
|
||||
+ if (link->watchdog_interval == 0)
|
||||
+ link->watchdog_interval = WATCHDOG_INTERVAL;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
From 2034afe4db4a2a4f22541d7f7b426e38d2093d38 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:55 +0200
|
||||
Subject: [PATCH 02/15] rt2800: add helpers for reading dma done index
|
||||
|
||||
For mmio we do not properlly trace dma done Q_INDEX_DMA_DONE index
|
||||
for TX queues. That would require implementing INT_SOURCE_CSR_*_DMA_DONE
|
||||
interrupts, what is rather not worth to do due to adding extra
|
||||
CPU load (small but still somewhat not necessary otherwise).
|
||||
|
||||
We can just read TX DMA done indexes from registers directly. What
|
||||
will be used by watchdog.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 8 +++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 31 +++++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800mmio.h | 2 ++
|
||||
.../net/wireless/ralink/rt2x00/rt2800pci.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800soc.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 9 ++++++
|
||||
6 files changed, 52 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -76,6 +76,7 @@ struct rt2800_ops {
|
||||
const u8 *data, const size_t len);
|
||||
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
|
||||
__le32 *(*drv_get_txwi)(struct queue_entry *entry);
|
||||
+ unsigned int (*drv_get_dma_done)(struct data_queue *queue);
|
||||
};
|
||||
|
||||
static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -177,6 +178,13 @@ static inline __le32 *rt2800_drv_get_txw
|
||||
return rt2800ops->drv_get_txwi(entry);
|
||||
}
|
||||
|
||||
+static inline unsigned int rt2800_drv_get_dma_done(struct data_queue *queue)
|
||||
+{
|
||||
+ const struct rt2800_ops *rt2800ops = queue->rt2x00dev->ops->drv;
|
||||
+
|
||||
+ return rt2800ops->drv_get_dma_done(queue);
|
||||
+}
|
||||
+
|
||||
void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
|
||||
const u8 command, const u8 token,
|
||||
const u8 arg0, const u8 arg1);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
|
||||
@@ -36,6 +36,37 @@
|
||||
#include "rt2800lib.h"
|
||||
#include "rt2800mmio.h"
|
||||
|
||||
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue)
|
||||
+{
|
||||
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
+ struct queue_entry *entry;
|
||||
+ int idx, qid;
|
||||
+
|
||||
+ switch (queue->qid) {
|
||||
+ case QID_AC_VO:
|
||||
+ case QID_AC_VI:
|
||||
+ case QID_AC_BE:
|
||||
+ case QID_AC_BK:
|
||||
+ qid = queue->qid;
|
||||
+ idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid));
|
||||
+ break;
|
||||
+ case QID_MGMT:
|
||||
+ idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(5));
|
||||
+ break;
|
||||
+ case QID_RX:
|
||||
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
|
||||
+ idx = entry->entry_idx;
|
||||
+ break;
|
||||
+ default:
|
||||
+ WARN_ON_ONCE(1);
|
||||
+ idx = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return idx;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800mmio_get_dma_done);
|
||||
+
|
||||
/*
|
||||
* TX descriptor initialization
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
|
||||
@@ -126,6 +126,8 @@
|
||||
#define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000)
|
||||
#define RXD_W3_PLCP_RSSI FIELD32(0x00040000)
|
||||
|
||||
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue);
|
||||
+
|
||||
/* TX descriptor initialization */
|
||||
__le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
|
||||
void rt2800mmio_write_tx_desc(struct queue_entry *entry,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -337,6 +337,7 @@ static const struct rt2800_ops rt2800pci
|
||||
.drv_write_firmware = rt2800pci_write_firmware,
|
||||
.drv_init_registers = rt2800mmio_init_registers,
|
||||
.drv_get_txwi = rt2800mmio_get_txwi,
|
||||
+ .drv_get_dma_done = rt2800mmio_get_dma_done,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -183,6 +183,7 @@ static const struct rt2800_ops rt2800soc
|
||||
.drv_write_firmware = rt2800soc_write_firmware,
|
||||
.drv_init_registers = rt2800mmio_init_registers,
|
||||
.drv_get_txwi = rt2800mmio_get_txwi,
|
||||
+ .drv_get_dma_done = rt2800mmio_get_dma_done,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -390,6 +390,14 @@ static int rt2800usb_set_device_state(st
|
||||
return retval;
|
||||
}
|
||||
|
||||
+static unsigned int rt2800usb_get_dma_done(struct data_queue *queue)
|
||||
+{
|
||||
+ struct queue_entry *entry;
|
||||
+
|
||||
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
|
||||
+ return entry->entry_idx;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* TX descriptor initialization
|
||||
*/
|
||||
@@ -672,6 +680,7 @@ static const struct rt2800_ops rt2800usb
|
||||
.drv_write_firmware = rt2800usb_write_firmware,
|
||||
.drv_init_registers = rt2800usb_init_registers,
|
||||
.drv_get_txwi = rt2800usb_get_txwi,
|
||||
+ .drv_get_dma_done = rt2800usb_get_dma_done,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
|
||||
@@ -0,0 +1,158 @@
|
||||
From 759c5b599cf4ddb3b56e66d459b1bf0fe2724fb8 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:56 +0200
|
||||
Subject: [PATCH 03/15] rt2800: initial watchdog implementation
|
||||
|
||||
Add watchdog for rt2800 devices. For now it only detect hung
|
||||
and print error.
|
||||
|
||||
[Note: I verified that printing messages from process context is
|
||||
fine on MT7620 (WT3020) platform that have problem when printk
|
||||
is called from interrupt context].
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 56 +++++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 2 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800pci.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800soc.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2x00queue.h | 6 ++
|
||||
6 files changed, 67 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1223,6 +1223,60 @@ void rt2800_txdone_nostatus(struct rt2x0
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
|
||||
|
||||
+static int rt2800_check_hung(struct data_queue *queue)
|
||||
+{
|
||||
+ unsigned int cur_idx = rt2800_drv_get_dma_done(queue);
|
||||
+
|
||||
+ if (queue->wd_idx != cur_idx)
|
||||
+ queue->wd_count = 0;
|
||||
+ else
|
||||
+ queue->wd_count++;
|
||||
+
|
||||
+ return queue->wd_count > 16;
|
||||
+}
|
||||
+
|
||||
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct data_queue *queue;
|
||||
+ bool hung_tx = false;
|
||||
+ bool hung_rx = false;
|
||||
+
|
||||
+ if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
|
||||
+ return;
|
||||
+
|
||||
+ queue_for_each(rt2x00dev, queue) {
|
||||
+ switch (queue->qid) {
|
||||
+ case QID_AC_VO:
|
||||
+ case QID_AC_VI:
|
||||
+ case QID_AC_BE:
|
||||
+ case QID_AC_BK:
|
||||
+ case QID_MGMT:
|
||||
+ if (rt2x00queue_empty(queue))
|
||||
+ continue;
|
||||
+ hung_tx = rt2800_check_hung(queue);
|
||||
+ break;
|
||||
+ case QID_RX:
|
||||
+ /* For station mode we should reactive at least
|
||||
+ * beacons. TODO: need to find good way detect
|
||||
+ * RX hung for AP mode.
|
||||
+ */
|
||||
+ if (rt2x00dev->intf_sta_count == 0)
|
||||
+ continue;
|
||||
+ hung_rx = rt2800_check_hung(queue);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (hung_tx)
|
||||
+ rt2x00_warn(rt2x00dev, "Watchdog TX hung detected\n");
|
||||
+
|
||||
+ if (hung_rx)
|
||||
+ rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_watchdog);
|
||||
+
|
||||
static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int index)
|
||||
{
|
||||
@@ -10222,6 +10276,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
|
||||
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
|
||||
}
|
||||
|
||||
+ rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
|
||||
+
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -208,6 +208,8 @@ void rt2800_txdone_nostatus(struct rt2x0
|
||||
bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
|
||||
bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev);
|
||||
+
|
||||
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
|
||||
void rt2800_clear_beacon(struct queue_entry *entry);
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -362,6 +362,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.link_tuner = rt2800_link_tuner,
|
||||
.gain_calibration = rt2800_gain_calibration,
|
||||
.vco_calibration = rt2800_vco_calibration,
|
||||
+ .watchdog = rt2800_watchdog,
|
||||
.start_queue = rt2800mmio_start_queue,
|
||||
.kick_queue = rt2800mmio_kick_queue,
|
||||
.stop_queue = rt2800mmio_stop_queue,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -208,6 +208,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.link_tuner = rt2800_link_tuner,
|
||||
.gain_calibration = rt2800_gain_calibration,
|
||||
.vco_calibration = rt2800_vco_calibration,
|
||||
+ .watchdog = rt2800_watchdog,
|
||||
.start_queue = rt2800mmio_start_queue,
|
||||
.kick_queue = rt2800mmio_kick_queue,
|
||||
.stop_queue = rt2800mmio_stop_queue,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -698,6 +698,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.link_tuner = rt2800_link_tuner,
|
||||
.gain_calibration = rt2800_gain_calibration,
|
||||
.vco_calibration = rt2800_vco_calibration,
|
||||
+ .watchdog = rt2800_watchdog,
|
||||
.start_queue = rt2800usb_start_queue,
|
||||
.kick_queue = rt2x00usb_kick_queue,
|
||||
.stop_queue = rt2800usb_stop_queue,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
|
||||
@@ -446,6 +446,9 @@ enum data_queue_flags {
|
||||
* @length: Number of frames in queue.
|
||||
* @index: Index pointers to entry positions in the queue,
|
||||
* use &enum queue_index to get a specific index field.
|
||||
+ * @wd_count: watchdog counter number of times entry does change
|
||||
+ * in the queue
|
||||
+ * @wd_idx: index of queue entry saved by watchdog
|
||||
* @txop: maximum burst time.
|
||||
* @aifs: The aifs value for outgoing frames (field ignored in RX queue).
|
||||
* @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
|
||||
@@ -473,6 +476,9 @@ struct data_queue {
|
||||
unsigned short length;
|
||||
unsigned short index[Q_INDEX_MAX];
|
||||
|
||||
+ unsigned short wd_count;
|
||||
+ unsigned int wd_idx;
|
||||
+
|
||||
unsigned short txop;
|
||||
unsigned short aifs;
|
||||
unsigned short cw_min;
|
||||
@@ -0,0 +1,96 @@
|
||||
From 09db3b000619b38d504e1fff66efed33dfacb6c0 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:57 +0200
|
||||
Subject: [PATCH 04/15] rt2800: add pre_reset_hw callback
|
||||
|
||||
Add routine to cleanup interfaces data before hw reset as
|
||||
ieee80211_restart_hw() will do setup interfaces again.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 19 +++++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800pci.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800soc.c | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800usb.c | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
6 files changed, 24 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1854,6 +1854,25 @@ int rt2800_sta_remove(struct ieee80211_h
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_sta_remove);
|
||||
|
||||
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
|
||||
+ struct data_queue *queue = rt2x00dev->bcn;
|
||||
+ struct queue_entry *entry;
|
||||
+ int i, wcid;
|
||||
+
|
||||
+ for (wcid = WCID_START; wcid < WCID_END; wcid++) {
|
||||
+ drv_data->wcid_to_sta[wcid - WCID_START] = NULL;
|
||||
+ __clear_bit(wcid - WCID_START, drv_data->sta_ids);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < queue->limit; i++) {
|
||||
+ entry = &queue->entries[i];
|
||||
+ clear_bit(ENTRY_BCN_ASSIGNED, &entry->flags);
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_pre_reset_hw);
|
||||
+
|
||||
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int filter_flags)
|
||||
{
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -268,5 +268,6 @@ void rt2800_disable_wpdma(struct rt2x00_
|
||||
void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned short *txwi_size,
|
||||
unsigned short *rxwi_size);
|
||||
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
#endif /* RT2800LIB_H */
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -379,6 +379,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.config_erp = rt2800_config_erp,
|
||||
.config_ant = rt2800_config_ant,
|
||||
.config = rt2800_config,
|
||||
+ .pre_reset_hw = rt2800_pre_reset_hw,
|
||||
};
|
||||
|
||||
static const struct rt2x00_ops rt2800pci_ops = {
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -225,6 +225,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.config_erp = rt2800_config_erp,
|
||||
.config_ant = rt2800_config_ant,
|
||||
.config = rt2800_config,
|
||||
+ .pre_reset_hw = rt2800_pre_reset_hw,
|
||||
};
|
||||
|
||||
static const struct rt2x00_ops rt2800soc_ops = {
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -717,6 +717,7 @@ static const struct rt2x00lib_ops rt2800
|
||||
.config_erp = rt2800_config_erp,
|
||||
.config_ant = rt2800_config_ant,
|
||||
.config = rt2800_config,
|
||||
+ .pre_reset_hw = rt2800_pre_reset_hw,
|
||||
};
|
||||
|
||||
static void rt2800usb_queue_init(struct data_queue *queue)
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -627,6 +627,7 @@ struct rt2x00lib_ops {
|
||||
void (*config) (struct rt2x00_dev *rt2x00dev,
|
||||
struct rt2x00lib_conf *libconf,
|
||||
const unsigned int changed_flags);
|
||||
+ void (*pre_reset_hw) (struct rt2x00_dev *rt2x00dev);
|
||||
int (*sta_add) (struct rt2x00_dev *rt2x00dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
@@ -0,0 +1,51 @@
|
||||
From 710e6cc1595e25378c4b9977f7a8b4ad4a72a109 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:58 +0200
|
||||
Subject: [PATCH 05/15] rt2800: do not nullify initialization vector data
|
||||
|
||||
If we restart hw we should keep existing IV (initialization vector)
|
||||
otherwise HW encryption will be broken after restart.
|
||||
|
||||
Also fix some coding style issues on the way.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1658,14 +1658,15 @@ static void rt2800_config_wcid_attr_ciph
|
||||
|
||||
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
|
||||
|
||||
- memset(&iveiv_entry, 0, sizeof(iveiv_entry));
|
||||
+ rt2800_register_multiread(rt2x00dev, offset,
|
||||
+ &iveiv_entry, sizeof(iveiv_entry));
|
||||
if ((crypto->cipher == CIPHER_TKIP) ||
|
||||
(crypto->cipher == CIPHER_TKIP_NO_MIC) ||
|
||||
(crypto->cipher == CIPHER_AES))
|
||||
iveiv_entry.iv[3] |= 0x20;
|
||||
iveiv_entry.iv[3] |= key->keyidx << 6;
|
||||
rt2800_register_multiwrite(rt2x00dev, offset,
|
||||
- &iveiv_entry, sizeof(iveiv_entry));
|
||||
+ &iveiv_entry, sizeof(iveiv_entry));
|
||||
}
|
||||
|
||||
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||
@@ -6090,13 +6091,11 @@ static int rt2800_init_registers(struct
|
||||
* ASIC will keep garbage value after boot, clear encryption keys.
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
- rt2800_register_write(rt2x00dev,
|
||||
- SHARED_KEY_MODE_ENTRY(i), 0);
|
||||
+ rt2800_register_write(rt2x00dev, SHARED_KEY_MODE_ENTRY(i), 0);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
rt2800_config_wcid(rt2x00dev, NULL, i);
|
||||
rt2800_delete_wcid_attr(rt2x00dev, i);
|
||||
- rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -0,0 +1,151 @@
|
||||
From e403fa31ed71e87de8e5991e23406b8377c9c894 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:00:59 +0200
|
||||
Subject: [PATCH 06/15] rt2x00: add restart hw
|
||||
|
||||
Add ieee80211_restart_hw() to watchdog and debugfs file for testing
|
||||
if restart works as expected.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 4 +++
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 7 ++++
|
||||
.../net/wireless/ralink/rt2x00/rt2x00debug.c | 35 +++++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2x00dev.c | 10 ++++--
|
||||
4 files changed, 54 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1274,6 +1274,9 @@ void rt2800_watchdog(struct rt2x00_dev *
|
||||
|
||||
if (hung_rx)
|
||||
rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
|
||||
+
|
||||
+ if (hung_tx || hung_rx)
|
||||
+ ieee80211_restart_hw(rt2x00dev->hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_watchdog);
|
||||
|
||||
@@ -10294,6 +10297,7 @@ int rt2800_probe_hw(struct rt2x00_dev *r
|
||||
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
|
||||
}
|
||||
|
||||
+ __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
|
||||
rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
|
||||
|
||||
/*
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -723,6 +723,7 @@ enum rt2x00_capability_flags {
|
||||
CAPABILITY_VCO_RECALIBRATION,
|
||||
CAPABILITY_EXTERNAL_PA_TX0,
|
||||
CAPABILITY_EXTERNAL_PA_TX1,
|
||||
+ CAPABILITY_RESTART_HW,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1279,6 +1280,12 @@ rt2x00_has_cap_vco_recalibration(struct
|
||||
return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION);
|
||||
}
|
||||
|
||||
+static inline bool
|
||||
+rt2x00_has_cap_restart_hw(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RESTART_HW);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
|
||||
* @entry: Pointer to &struct queue_entry
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
@@ -63,6 +63,7 @@ struct rt2x00debug_intf {
|
||||
* - chipset file
|
||||
* - device state flags file
|
||||
* - device capability flags file
|
||||
+ * - hardware restart file
|
||||
* - register folder
|
||||
* - csr offset/value files
|
||||
* - eeprom offset/value files
|
||||
@@ -79,6 +80,7 @@ struct rt2x00debug_intf {
|
||||
struct dentry *chipset_entry;
|
||||
struct dentry *dev_flags;
|
||||
struct dentry *cap_flags;
|
||||
+ struct dentry *restart_hw;
|
||||
struct dentry *register_folder;
|
||||
struct dentry *csr_off_entry;
|
||||
struct dentry *csr_val_entry;
|
||||
@@ -577,6 +579,34 @@ static const struct file_operations rt2x
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+static ssize_t rt2x00debug_write_restart_hw(struct file *file,
|
||||
+ const char __user *buf,
|
||||
+ size_t length,
|
||||
+ loff_t *offset)
|
||||
+{
|
||||
+ struct rt2x00debug_intf *intf = file->private_data;
|
||||
+ struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
|
||||
+ static unsigned long last_reset;
|
||||
+
|
||||
+ if (!rt2x00_has_cap_restart_hw(rt2x00dev))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (time_before(jiffies, last_reset + msecs_to_jiffies(2000)))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ last_reset = jiffies;
|
||||
+
|
||||
+ ieee80211_restart_hw(rt2x00dev->hw);
|
||||
+ return length;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations rt2x00debug_restart_hw = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .write = rt2x00debug_write_restart_hw,
|
||||
+ .open = simple_open,
|
||||
+ .llseek = generic_file_llseek,
|
||||
+};
|
||||
+
|
||||
static struct dentry *rt2x00debug_create_file_driver(const char *name,
|
||||
struct rt2x00debug_intf
|
||||
*intf,
|
||||
@@ -672,6 +702,10 @@ void rt2x00debug_register(struct rt2x00_
|
||||
intf->driver_folder, intf,
|
||||
&rt2x00debug_fop_cap_flags);
|
||||
|
||||
+ intf->restart_hw = debugfs_create_file("restart_hw", 0200,
|
||||
+ intf->driver_folder, intf,
|
||||
+ &rt2x00debug_restart_hw);
|
||||
+
|
||||
intf->register_folder =
|
||||
debugfs_create_dir("register", intf->driver_folder);
|
||||
|
||||
@@ -753,6 +787,7 @@ void rt2x00debug_deregister(struct rt2x0
|
||||
debugfs_remove(intf->csr_off_entry);
|
||||
debugfs_remove(intf->register_folder);
|
||||
debugfs_remove(intf->dev_flags);
|
||||
+ debugfs_remove(intf->restart_hw);
|
||||
debugfs_remove(intf->cap_flags);
|
||||
debugfs_remove(intf->chipset_entry);
|
||||
debugfs_remove(intf->driver_entry);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1269,8 +1269,14 @@ int rt2x00lib_start(struct rt2x00_dev *r
|
||||
{
|
||||
int retval;
|
||||
|
||||
- if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
- return 0;
|
||||
+ if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
|
||||
+ /*
|
||||
+ * This is special case for ieee80211_restart_hw(), otherwise
|
||||
+ * mac80211 never call start() two times in row without stop();
|
||||
+ */
|
||||
+ rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
|
||||
+ rt2x00lib_stop(rt2x00dev);
|
||||
+ }
|
||||
|
||||
/*
|
||||
* If this is the first interface which is added,
|
||||
@@ -0,0 +1,71 @@
|
||||
From 0f47aeeada2a1fe296258eab9a08ced258009481 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Sat, 15 Jun 2019 12:01:00 +0200
|
||||
Subject: [PATCH 07/15] rt2800: do not enable watchdog by default
|
||||
|
||||
Make watchdog disabled by default and add module parameter to enable it.
|
||||
|
||||
User will have to create file in /etc/modprobe.d/ with
|
||||
|
||||
options rt2800lib watchdog=1
|
||||
|
||||
to enable the watchdog or load "rt2800lib watchdog=1" module manually
|
||||
before loading rt2800{soc,pci,usb} module.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 12 ++++++++++--
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 2 +-
|
||||
3 files changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -41,6 +41,10 @@
|
||||
#include "rt2800lib.h"
|
||||
#include "rt2800.h"
|
||||
|
||||
+static bool modparam_watchdog;
|
||||
+module_param_named(watchdog, modparam_watchdog, bool, S_IRUGO);
|
||||
+MODULE_PARM_DESC(watchdog, "Enable watchdog to detect tx/rx hangs and reset hardware if detected");
|
||||
+
|
||||
/*
|
||||
* Register access.
|
||||
* All access to the CSR registers will go through the methods
|
||||
@@ -10297,8 +10301,12 @@ int rt2800_probe_hw(struct rt2x00_dev *r
|
||||
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
|
||||
}
|
||||
|
||||
- __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
|
||||
- rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
|
||||
+ if (modparam_watchdog) {
|
||||
+ __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
|
||||
+ rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
|
||||
+ } else {
|
||||
+ rt2x00dev->link.watchdog_disabled = true;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -337,6 +337,7 @@ struct link {
|
||||
*/
|
||||
struct delayed_work watchdog_work;
|
||||
unsigned int watchdog_interval;
|
||||
+ bool watchdog_disabled;
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic AGC adjustments.
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
|
||||
@@ -395,7 +395,7 @@ void rt2x00link_start_watchdog(struct rt
|
||||
struct link *link = &rt2x00dev->link;
|
||||
|
||||
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
|
||||
- rt2x00dev->ops->lib->watchdog)
|
||||
+ rt2x00dev->ops->lib->watchdog && !link->watchdog_disabled)
|
||||
ieee80211_queue_delayed_work(rt2x00dev->hw,
|
||||
&link->watchdog_work,
|
||||
link->watchdog_interval);
|
||||
@@ -0,0 +1,67 @@
|
||||
From 41a531ffa4c5aeb062f892227c00fabb3b4a9c91 Mon Sep 17 00:00:00 2001
|
||||
From: Soeren Moch <smoch@web.de>
|
||||
Date: Mon, 1 Jul 2019 12:53:13 +0200
|
||||
Subject: [PATCH 08/15] rt2x00usb: fix rx queue hang
|
||||
|
||||
Since commit ed194d136769 ("usb: core: remove local_irq_save() around
|
||||
->complete() handler") the handler rt2x00usb_interrupt_rxdone() is
|
||||
not running with interrupts disabled anymore. So this completion handler
|
||||
is not guaranteed to run completely before workqueue processing starts
|
||||
for the same queue entry.
|
||||
Be sure to set all other flags in the entry correctly before marking
|
||||
this entry ready for workqueue processing. This way we cannot miss error
|
||||
conditions that need to be signalled from the completion handler to the
|
||||
worker thread.
|
||||
Note that rt2x00usb_work_rxdone() processes all available entries, not
|
||||
only such for which queue_work() was called.
|
||||
|
||||
This patch is similar to what commit df71c9cfceea ("rt2x00: fix order
|
||||
of entry flags modification") did for TX processing.
|
||||
|
||||
This fixes a regression on a RT5370 based wifi stick in AP mode, which
|
||||
suddenly stopped data transmission after some period of heavy load. Also
|
||||
stopping the hanging hostapd resulted in the error message "ieee80211
|
||||
phy0: rt2x00queue_flush_queue: Warning - Queue 14 failed to flush".
|
||||
Other operation modes are probably affected as well, this just was
|
||||
the used testcase.
|
||||
|
||||
Fixes: ed194d136769 ("usb: core: remove local_irq_save() around ->complete() handler")
|
||||
Cc: stable@vger.kernel.org # 4.20+
|
||||
Signed-off-by: Soeren Moch <smoch@web.de>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
@@ -383,15 +383,10 @@ static void rt2x00usb_interrupt_rxdone(s
|
||||
struct queue_entry *entry = (struct queue_entry *)urb->context;
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
|
||||
- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
- * Report the frame as DMA done
|
||||
- */
|
||||
- rt2x00lib_dmadone(entry);
|
||||
-
|
||||
- /*
|
||||
* Check if the received data is simply too small
|
||||
* to be actually valid, or if the urb is signaling
|
||||
* a problem.
|
||||
@@ -400,6 +395,11 @@ static void rt2x00usb_interrupt_rxdone(s
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
|
||||
/*
|
||||
+ * Report the frame as DMA done
|
||||
+ */
|
||||
+ rt2x00lib_dmadone(entry);
|
||||
+
|
||||
+ /*
|
||||
* Schedule the delayed work for reading the RX status
|
||||
* from the device.
|
||||
*/
|
||||
@@ -0,0 +1,51 @@
|
||||
From 3b902fa811cf6bf7f9ad0ffb77d0a133e0b3bd61 Mon Sep 17 00:00:00 2001
|
||||
From: Soeren Moch <smoch@web.de>
|
||||
Date: Mon, 1 Jul 2019 12:53:14 +0200
|
||||
Subject: [PATCH 09/15] rt2x00usb: remove unnecessary rx flag checks
|
||||
|
||||
In contrast to the TX path, there is no need to separately read the transfer
|
||||
status from the device after receiving RX data. Consequently, there is no
|
||||
real STATUS_PENDING RX processing queue entry state.
|
||||
Remove the unnecessary ENTRY_DATA_STATUS_PENDING flag checks from the RX path.
|
||||
Also remove the misleading comment about reading RX status from device.
|
||||
|
||||
Suggested-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Soeren Moch <smoch@web.de>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
@@ -360,8 +360,7 @@ static void rt2x00usb_work_rxdone(struct
|
||||
while (!rt2x00queue_empty(rt2x00dev->rx)) {
|
||||
entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
|
||||
|
||||
- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -400,8 +399,7 @@ static void rt2x00usb_interrupt_rxdone(s
|
||||
rt2x00lib_dmadone(entry);
|
||||
|
||||
/*
|
||||
- * Schedule the delayed work for reading the RX status
|
||||
- * from the device.
|
||||
+ * Schedule the delayed work for processing RX data
|
||||
*/
|
||||
queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
|
||||
}
|
||||
@@ -413,8 +411,7 @@ static bool rt2x00usb_kick_rx_entry(stru
|
||||
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
|
||||
int status;
|
||||
|
||||
- if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
|
||||
- test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
|
||||
+ if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
return false;
|
||||
|
||||
rt2x00lib_dmastart(entry);
|
||||
@@ -0,0 +1,248 @@
|
||||
From 1dc244064c47d6df7925ca0895f8365e68d3abd1 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Date: Wed, 3 Jul 2019 13:39:56 +0200
|
||||
Subject: [PATCH 10/15] rt2x00: no need to check return value of debugfs_create
|
||||
functions
|
||||
|
||||
When calling debugfs functions, there is no need to ever check the
|
||||
return value. The function can work or not, but the code logic should
|
||||
never do something different based on this.
|
||||
|
||||
Because we don't need to save the individual debugfs files and
|
||||
directories, remove the local storage of them and just remove the entire
|
||||
debugfs directory in a single call, making things a lot simpler.
|
||||
|
||||
Cc: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Cc: Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@codeaurora.org>
|
||||
Cc: "David S. Miller" <davem@davemloft.net>
|
||||
Cc: linux-wireless@vger.kernel.org
|
||||
Cc: netdev@vger.kernel.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2x00debug.c | 136 +++++-------------
|
||||
1 file changed, 35 insertions(+), 101 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
|
||||
@@ -76,26 +76,6 @@ struct rt2x00debug_intf {
|
||||
* - crypto stats file
|
||||
*/
|
||||
struct dentry *driver_folder;
|
||||
- struct dentry *driver_entry;
|
||||
- struct dentry *chipset_entry;
|
||||
- struct dentry *dev_flags;
|
||||
- struct dentry *cap_flags;
|
||||
- struct dentry *restart_hw;
|
||||
- struct dentry *register_folder;
|
||||
- struct dentry *csr_off_entry;
|
||||
- struct dentry *csr_val_entry;
|
||||
- struct dentry *eeprom_off_entry;
|
||||
- struct dentry *eeprom_val_entry;
|
||||
- struct dentry *bbp_off_entry;
|
||||
- struct dentry *bbp_val_entry;
|
||||
- struct dentry *rf_off_entry;
|
||||
- struct dentry *rf_val_entry;
|
||||
- struct dentry *rfcsr_off_entry;
|
||||
- struct dentry *rfcsr_val_entry;
|
||||
- struct dentry *queue_folder;
|
||||
- struct dentry *queue_frame_dump_entry;
|
||||
- struct dentry *queue_stats_entry;
|
||||
- struct dentry *crypto_stats_entry;
|
||||
|
||||
/*
|
||||
* The frame dump file only allows a single reader,
|
||||
@@ -607,39 +587,34 @@ static const struct file_operations rt2x
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
-static struct dentry *rt2x00debug_create_file_driver(const char *name,
|
||||
- struct rt2x00debug_intf
|
||||
- *intf,
|
||||
- struct debugfs_blob_wrapper
|
||||
- *blob)
|
||||
+static void rt2x00debug_create_file_driver(const char *name,
|
||||
+ struct rt2x00debug_intf *intf,
|
||||
+ struct debugfs_blob_wrapper *blob)
|
||||
{
|
||||
char *data;
|
||||
|
||||
data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
|
||||
if (!data)
|
||||
- return NULL;
|
||||
+ return;
|
||||
|
||||
blob->data = data;
|
||||
data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
|
||||
data += sprintf(data, "version:\t%s\n", DRV_VERSION);
|
||||
blob->size = strlen(blob->data);
|
||||
|
||||
- return debugfs_create_blob(name, 0400, intf->driver_folder, blob);
|
||||
+ debugfs_create_blob(name, 0400, intf->driver_folder, blob);
|
||||
}
|
||||
|
||||
-static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
||||
- struct rt2x00debug_intf
|
||||
- *intf,
|
||||
- struct
|
||||
- debugfs_blob_wrapper
|
||||
- *blob)
|
||||
+static void rt2x00debug_create_file_chipset(const char *name,
|
||||
+ struct rt2x00debug_intf *intf,
|
||||
+ struct debugfs_blob_wrapper *blob)
|
||||
{
|
||||
const struct rt2x00debug *debug = intf->debug;
|
||||
char *data;
|
||||
|
||||
data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
|
||||
if (!data)
|
||||
- return NULL;
|
||||
+ return;
|
||||
|
||||
blob->data = data;
|
||||
data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
|
||||
@@ -665,13 +640,15 @@ static struct dentry *rt2x00debug_create
|
||||
|
||||
blob->size = strlen(blob->data);
|
||||
|
||||
- return debugfs_create_blob(name, 0400, intf->driver_folder, blob);
|
||||
+ debugfs_create_blob(name, 0400, intf->driver_folder, blob);
|
||||
}
|
||||
|
||||
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
|
||||
struct rt2x00debug_intf *intf;
|
||||
+ struct dentry *queue_folder;
|
||||
+ struct dentry *register_folder;
|
||||
|
||||
intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
|
||||
if (!intf) {
|
||||
@@ -687,43 +664,27 @@ void rt2x00debug_register(struct rt2x00_
|
||||
debugfs_create_dir(intf->rt2x00dev->ops->name,
|
||||
rt2x00dev->hw->wiphy->debugfsdir);
|
||||
|
||||
- intf->driver_entry =
|
||||
- rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
|
||||
-
|
||||
- intf->chipset_entry =
|
||||
- rt2x00debug_create_file_chipset("chipset",
|
||||
- intf, &intf->chipset_blob);
|
||||
-
|
||||
- intf->dev_flags = debugfs_create_file("dev_flags", 0400,
|
||||
- intf->driver_folder, intf,
|
||||
- &rt2x00debug_fop_dev_flags);
|
||||
-
|
||||
- intf->cap_flags = debugfs_create_file("cap_flags", 0400,
|
||||
- intf->driver_folder, intf,
|
||||
- &rt2x00debug_fop_cap_flags);
|
||||
-
|
||||
- intf->restart_hw = debugfs_create_file("restart_hw", 0200,
|
||||
- intf->driver_folder, intf,
|
||||
- &rt2x00debug_restart_hw);
|
||||
+ rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
|
||||
+ rt2x00debug_create_file_chipset("chipset", intf, &intf->chipset_blob);
|
||||
+ debugfs_create_file("dev_flags", 0400, intf->driver_folder, intf,
|
||||
+ &rt2x00debug_fop_dev_flags);
|
||||
+ debugfs_create_file("cap_flags", 0400, intf->driver_folder, intf,
|
||||
+ &rt2x00debug_fop_cap_flags);
|
||||
+ debugfs_create_file("restart_hw", 0200, intf->driver_folder, intf,
|
||||
+ &rt2x00debug_restart_hw);
|
||||
|
||||
- intf->register_folder =
|
||||
- debugfs_create_dir("register", intf->driver_folder);
|
||||
+ register_folder = debugfs_create_dir("register", intf->driver_folder);
|
||||
|
||||
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
|
||||
({ \
|
||||
if (debug->__name.read) { \
|
||||
- (__intf)->__name##_off_entry = \
|
||||
- debugfs_create_u32(__stringify(__name) "_offset", \
|
||||
- 0600, \
|
||||
- (__intf)->register_folder, \
|
||||
- &(__intf)->offset_##__name); \
|
||||
+ debugfs_create_u32(__stringify(__name) "_offset", 0600, \
|
||||
+ register_folder, \
|
||||
+ &(__intf)->offset_##__name); \
|
||||
\
|
||||
- (__intf)->__name##_val_entry = \
|
||||
- debugfs_create_file(__stringify(__name) "_value", \
|
||||
- 0600, \
|
||||
- (__intf)->register_folder, \
|
||||
- (__intf), \
|
||||
- &rt2x00debug_fop_##__name); \
|
||||
+ debugfs_create_file(__stringify(__name) "_value", 0600, \
|
||||
+ register_folder, (__intf), \
|
||||
+ &rt2x00debug_fop_##__name); \
|
||||
} \
|
||||
})
|
||||
|
||||
@@ -735,26 +696,21 @@ void rt2x00debug_register(struct rt2x00_
|
||||
|
||||
#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
|
||||
|
||||
- intf->queue_folder =
|
||||
- debugfs_create_dir("queue", intf->driver_folder);
|
||||
+ queue_folder = debugfs_create_dir("queue", intf->driver_folder);
|
||||
|
||||
- intf->queue_frame_dump_entry =
|
||||
- debugfs_create_file("dump", 0400, intf->queue_folder,
|
||||
- intf, &rt2x00debug_fop_queue_dump);
|
||||
+ debugfs_create_file("dump", 0400, queue_folder, intf,
|
||||
+ &rt2x00debug_fop_queue_dump);
|
||||
|
||||
skb_queue_head_init(&intf->frame_dump_skbqueue);
|
||||
init_waitqueue_head(&intf->frame_dump_waitqueue);
|
||||
|
||||
- intf->queue_stats_entry =
|
||||
- debugfs_create_file("queue", 0400, intf->queue_folder,
|
||||
- intf, &rt2x00debug_fop_queue_stats);
|
||||
+ debugfs_create_file("queue", 0400, queue_folder, intf,
|
||||
+ &rt2x00debug_fop_queue_stats);
|
||||
|
||||
#ifdef CPTCFG_RT2X00_LIB_CRYPTO
|
||||
if (rt2x00_has_cap_hw_crypto(rt2x00dev))
|
||||
- intf->crypto_stats_entry =
|
||||
- debugfs_create_file("crypto", 0444, intf->queue_folder,
|
||||
- intf,
|
||||
- &rt2x00debug_fop_crypto_stats);
|
||||
+ debugfs_create_file("crypto", 0444, queue_folder, intf,
|
||||
+ &rt2x00debug_fop_crypto_stats);
|
||||
#endif
|
||||
|
||||
return;
|
||||
@@ -769,31 +725,7 @@ void rt2x00debug_deregister(struct rt2x0
|
||||
|
||||
skb_queue_purge(&intf->frame_dump_skbqueue);
|
||||
|
||||
-#ifdef CPTCFG_RT2X00_LIB_CRYPTO
|
||||
- debugfs_remove(intf->crypto_stats_entry);
|
||||
-#endif
|
||||
- debugfs_remove(intf->queue_stats_entry);
|
||||
- debugfs_remove(intf->queue_frame_dump_entry);
|
||||
- debugfs_remove(intf->queue_folder);
|
||||
- debugfs_remove(intf->rfcsr_val_entry);
|
||||
- debugfs_remove(intf->rfcsr_off_entry);
|
||||
- debugfs_remove(intf->rf_val_entry);
|
||||
- debugfs_remove(intf->rf_off_entry);
|
||||
- debugfs_remove(intf->bbp_val_entry);
|
||||
- debugfs_remove(intf->bbp_off_entry);
|
||||
- debugfs_remove(intf->eeprom_val_entry);
|
||||
- debugfs_remove(intf->eeprom_off_entry);
|
||||
- debugfs_remove(intf->csr_val_entry);
|
||||
- debugfs_remove(intf->csr_off_entry);
|
||||
- debugfs_remove(intf->register_folder);
|
||||
- debugfs_remove(intf->dev_flags);
|
||||
- debugfs_remove(intf->restart_hw);
|
||||
- debugfs_remove(intf->cap_flags);
|
||||
- debugfs_remove(intf->chipset_entry);
|
||||
- debugfs_remove(intf->driver_entry);
|
||||
- debugfs_remove(intf->driver_folder);
|
||||
- kfree(intf->chipset_blob.data);
|
||||
- kfree(intf->driver_blob.data);
|
||||
+ debugfs_remove_recursive(intf->driver_folder);
|
||||
kfree(intf);
|
||||
|
||||
rt2x00dev->debugfs_intf = NULL;
|
||||
@@ -0,0 +1,29 @@
|
||||
From 706f0182b1add0fc41a8c40662f659b7426f0629 Mon Sep 17 00:00:00 2001
|
||||
From: Masanari Iida <standby24x7@gmail.com>
|
||||
Date: Sun, 28 Jul 2019 23:07:42 +0900
|
||||
Subject: [PATCH 11/15] rt2800usb: Add new rt2800usb device PLANEX GW-USMicroN
|
||||
|
||||
This patch add a device ID for PLANEX GW-USMicroN.
|
||||
Without this patch, I had to echo the device IDs in order to
|
||||
recognize the device.
|
||||
|
||||
# lsusb |grep PLANEX
|
||||
Bus 002 Device 005: ID 2019:ed14 PLANEX GW-USMicroN
|
||||
|
||||
Signed-off-by: Masanari Iida <standby24x7@gmail.com>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -1097,6 +1097,7 @@ static const struct usb_device_id rt2800
|
||||
{ USB_DEVICE(0x0846, 0x9013) },
|
||||
{ USB_DEVICE(0x0846, 0x9019) },
|
||||
/* Planex */
|
||||
+ { USB_DEVICE(0x2019, 0xed14) },
|
||||
{ USB_DEVICE(0x2019, 0xed19) },
|
||||
/* Ralink */
|
||||
{ USB_DEVICE(0x148f, 0x3573) },
|
||||
@@ -0,0 +1,102 @@
|
||||
From 95844124385eae4bd9ca5f9514a0fc33d561ac3c Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Mon, 19 Aug 2019 13:20:07 +0200
|
||||
Subject: [PATCH 12/15] rt2x00: clear IV's on start to fix AP mode regression
|
||||
|
||||
To do not brake HW restart we should keep initialization vectors data.
|
||||
I assumed that on start the data is already initialized to zeros, but
|
||||
that not true on some scenarios and we should clear it. So add
|
||||
additional flag to check if we are under HW restart and clear IV's
|
||||
data if we are not.
|
||||
|
||||
Patch fixes AP mode regression.
|
||||
|
||||
Reported-and-tested-by: Emil Karlson <jekarl@iki.fi>
|
||||
Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data")
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 +++++++++
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 13 ++++++++-----
|
||||
3 files changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -6106,6 +6106,15 @@ static int rt2800_init_registers(struct
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Clear encryption initialization vectors on start, but keep them
|
||||
+ * for watchdog reset. Otherwise we will have wrong IVs and not be
|
||||
+ * able to keep connections after reset.
|
||||
+ */
|
||||
+ if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
|
||||
+ for (i = 0; i < 256; i++)
|
||||
+ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
|
||||
+
|
||||
+ /*
|
||||
* Clear all beacons
|
||||
*/
|
||||
for (i = 0; i < 8; i++)
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -669,6 +669,7 @@ enum rt2x00_state_flags {
|
||||
DEVICE_STATE_ENABLED_RADIO,
|
||||
DEVICE_STATE_SCANNING,
|
||||
DEVICE_STATE_FLUSHING,
|
||||
+ DEVICE_STATE_RESET,
|
||||
|
||||
/*
|
||||
* Driver configuration
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1267,13 +1267,14 @@ static int rt2x00lib_initialize(struct r
|
||||
|
||||
int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
- int retval;
|
||||
+ int retval = 0;
|
||||
|
||||
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
|
||||
/*
|
||||
* This is special case for ieee80211_restart_hw(), otherwise
|
||||
* mac80211 never call start() two times in row without stop();
|
||||
*/
|
||||
+ set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
|
||||
rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
|
||||
rt2x00lib_stop(rt2x00dev);
|
||||
}
|
||||
@@ -1284,14 +1285,14 @@ int rt2x00lib_start(struct rt2x00_dev *r
|
||||
*/
|
||||
retval = rt2x00lib_load_firmware(rt2x00dev);
|
||||
if (retval)
|
||||
- return retval;
|
||||
+ goto out;
|
||||
|
||||
/*
|
||||
* Initialize the device.
|
||||
*/
|
||||
retval = rt2x00lib_initialize(rt2x00dev);
|
||||
if (retval)
|
||||
- return retval;
|
||||
+ goto out;
|
||||
|
||||
rt2x00dev->intf_ap_count = 0;
|
||||
rt2x00dev->intf_sta_count = 0;
|
||||
@@ -1300,11 +1301,13 @@ int rt2x00lib_start(struct rt2x00_dev *r
|
||||
/* Enable the radio */
|
||||
retval = rt2x00lib_enable_radio(rt2x00dev);
|
||||
if (retval)
|
||||
- return retval;
|
||||
+ goto out;
|
||||
|
||||
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
|
||||
|
||||
- return 0;
|
||||
+out:
|
||||
+ clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
|
||||
@@ -0,0 +1,40 @@
|
||||
From 567a9b766b47caffe4b1bf74823e7bc18532d875 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Fri, 23 Aug 2019 09:09:56 +0200
|
||||
Subject: [PATCH 13/15] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on
|
||||
tx status
|
||||
|
||||
According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
|
||||
to be used when we do not recive BA (BlockAck). However on rt2x00 we
|
||||
use it when remote station fail to decode one or more subframes within
|
||||
AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
|
||||
in sent of BAR (BlockAck Request) frame and this might result of abuse
|
||||
of BA session, since remote station can sent BA with incorrect
|
||||
sequence numbers after receiving BAR. This problem is visible especially
|
||||
when connecting two rt2800 devices.
|
||||
|
||||
Previously I observed some performance benefits when using the flag
|
||||
when connecting with iwlwifi devices. But currently possibly due
|
||||
to reacent changes in rt2x00 removing the flag has no effect on
|
||||
those test cases.
|
||||
|
||||
So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -382,9 +382,6 @@ static void rt2x00lib_fill_tx_status(str
|
||||
IEEE80211_TX_CTL_AMPDU;
|
||||
tx_info->status.ampdu_len = 1;
|
||||
tx_info->status.ampdu_ack_len = success ? 1 : 0;
|
||||
-
|
||||
- if (!success)
|
||||
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
}
|
||||
|
||||
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
@@ -0,0 +1,46 @@
|
||||
From 14d5e14c8a6c257eb322ddeb294ac4c243a7d2e1 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Fri, 23 Aug 2019 14:48:03 +0200
|
||||
Subject: [PATCH 14/15] rt2x00: clear up IV's on key removal
|
||||
|
||||
After looking at code I realized that my previous fix
|
||||
95844124385e ("rt2x00: clear IV's on start to fix AP mode regression")
|
||||
was incomplete. We can still have wrong IV's after re-keyring.
|
||||
To fix that, clear up IV's also on key removal.
|
||||
|
||||
Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data")
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
tested-by: Emil Karlson <jekarl@iki.fi>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 19 ++++++++++++-------
|
||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -1665,13 +1665,18 @@ static void rt2800_config_wcid_attr_ciph
|
||||
|
||||
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
|
||||
|
||||
- rt2800_register_multiread(rt2x00dev, offset,
|
||||
- &iveiv_entry, sizeof(iveiv_entry));
|
||||
- if ((crypto->cipher == CIPHER_TKIP) ||
|
||||
- (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
|
||||
- (crypto->cipher == CIPHER_AES))
|
||||
- iveiv_entry.iv[3] |= 0x20;
|
||||
- iveiv_entry.iv[3] |= key->keyidx << 6;
|
||||
+ if (crypto->cmd == SET_KEY) {
|
||||
+ rt2800_register_multiread(rt2x00dev, offset,
|
||||
+ &iveiv_entry, sizeof(iveiv_entry));
|
||||
+ if ((crypto->cipher == CIPHER_TKIP) ||
|
||||
+ (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
|
||||
+ (crypto->cipher == CIPHER_AES))
|
||||
+ iveiv_entry.iv[3] |= 0x20;
|
||||
+ iveiv_entry.iv[3] |= key->keyidx << 6;
|
||||
+ } else {
|
||||
+ memset(&iveiv_entry, 0, sizeof(iveiv_entry));
|
||||
+ }
|
||||
+
|
||||
rt2800_register_multiwrite(rt2x00dev, offset,
|
||||
&iveiv_entry, sizeof(iveiv_entry));
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
From 13fa451568ab9e8b3074ef741477c7938c713c42 Mon Sep 17 00:00:00 2001
|
||||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Thu, 29 Aug 2019 13:29:59 +0200
|
||||
Subject: [PATCH 15/15] Revert "rt2800: enable TX_PIN_CFG_LNA_PE_ bits per
|
||||
band"
|
||||
|
||||
This reverts commit 9ad3b55654455258a9463384edb40077439d879f.
|
||||
|
||||
As reported by Sergey:
|
||||
|
||||
"I got some problem after upgrade kernel to 5.2 version (debian testing
|
||||
linux-image-5.2.0-2-amd64). 5Ghz client stopped to see AP.
|
||||
Some tests with 1metre distance between client-AP: 2.4Ghz -22dBm, for
|
||||
5Ghz - 53dBm !, for longer distance (8m + walls) 2.4 - 61dBm, 5Ghz not
|
||||
visible."
|
||||
|
||||
It was identified that rx signal level degradation was caused by
|
||||
9ad3b5565445 ("rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band").
|
||||
So revert this commit.
|
||||
|
||||
Cc: <stable@vger.kernel.org> # v5.1+
|
||||
Reported-and-tested-by: Sergey Maranchuk <slav0nic0@gmail.com>
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 18 ++++++------------
|
||||
1 file changed, 6 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -4253,24 +4253,18 @@ static void rt2800_config_channel(struct
|
||||
switch (rt2x00dev->default_ant.rx_chain_num) {
|
||||
case 3:
|
||||
/* Turn on tertiary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
|
||||
- rf->channel > 14);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
|
||||
- rf->channel <= 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
|
||||
/* fall-through */
|
||||
case 2:
|
||||
/* Turn on secondary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
|
||||
- rf->channel > 14);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
|
||||
- rf->channel <= 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
|
||||
/* fall-through */
|
||||
case 1:
|
||||
/* Turn on primary LNAs */
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
|
||||
- rf->channel > 14);
|
||||
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
|
||||
- rf->channel <= 14);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
|
||||
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
From patchwork Sat Nov 2 17:47:01 2019
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 11224189
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <SRS0=CgQo=Y2=vger.kernel.org=linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 2 Nov 2019 18:47:01 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Cc: linux-wireless@vger.kernel.org, Roman Yeryomin <roman@advem.lv>,
|
||||
wbob <wbob@jify.de>
|
||||
Subject: [PATCH v2] rt2800: remove errornous duplicate condition
|
||||
Message-ID: <20191102174701.GA1489@makrotopia.org>
|
||||
References: <20191102154639.GA4589@redhat.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <20191102154639.GA4589@redhat.com>
|
||||
User-Agent: Mutt/1.12.2 (2019-09-21)
|
||||
Sender: linux-wireless-owner@vger.kernel.org
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
On 2019-10-28 06:07, wbob wrote:
|
||||
> Hello Roman,
|
||||
>
|
||||
> while reading around drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
> I stumbled on what I think is an edit of yours made in error in march
|
||||
> 2017:
|
||||
>
|
||||
> https://github.com/torvalds/linux/commit/41977e86#diff-dae5dc10da180f3b055809a48118e18aR5281
|
||||
>
|
||||
> RT6352 in line 5281 should not have been introduced as the "else if"
|
||||
> below line 5291 can then not take effect for a RT6352 device. Another
|
||||
> possibility is for line 5291 to be not for RT6352, but this seems
|
||||
> very unlikely. Are you able to clarify still after this substantial time?
|
||||
>
|
||||
> 5277: static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
> ...
|
||||
> 5279: } else if (rt2x00_rt(rt2x00dev, RT5390) ||
|
||||
> 5280: rt2x00_rt(rt2x00dev, RT5392) ||
|
||||
> 5281: rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
> ...
|
||||
> 5291: } else if (rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
> ...
|
||||
|
||||
Hence remove errornous line 5281 to make the driver actually
|
||||
execute the correct initialization routine for MT7620 chips.
|
||||
|
||||
As it was requested by Stanislaw Gruszka remove setting values of
|
||||
MIMO_PS_CFG and TX_PIN_CFG. MIMO_PS_CFG is responsible for MIMO
|
||||
power-safe mode (which is disabled), hence we can drop setting it.
|
||||
TX_PIN_CFG is set correctly in other functions, and as setting this
|
||||
value breaks some devices, rather don't set it here during init, but
|
||||
only modify it later on.
|
||||
|
||||
Fixes: 41977e86c984 ("rt2x00: add support for MT7620")
|
||||
Reported-by: wbob <wbob@jify.de>
|
||||
Reported-by: Roman Yeryomin <roman@advem.lv>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -5850,8 +5850,7 @@ static int rt2800_init_registers(struct
|
||||
rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
|
||||
rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
|
||||
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
|
||||
- rt2x00_rt(rt2x00dev, RT5392) ||
|
||||
- rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
+ rt2x00_rt(rt2x00dev, RT5392)) {
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
|
||||
@@ -5865,8 +5864,6 @@ static int rt2800_init_registers(struct
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
|
||||
- rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002);
|
||||
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F);
|
||||
rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
|
||||
rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
|
||||
rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
|
||||
@@ -0,0 +1,47 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
@@ -225,36 +225,37 @@ config RT2800SOC
|
||||
|
||||
|
||||
config RT2800_LIB
|
||||
- tristate
|
||||
+ tristate "RT2800 USB/PCI support"
|
||||
depends on m
|
||||
|
||||
config RT2800_LIB_MMIO
|
||||
- tristate
|
||||
+ tristate "RT2800 MMIO support"
|
||||
depends on m
|
||||
select RT2X00_LIB_MMIO
|
||||
select RT2800_LIB
|
||||
|
||||
config RT2X00_LIB_MMIO
|
||||
- tristate
|
||||
+ tristate "RT2x00 MMIO support"
|
||||
depends on m
|
||||
|
||||
config RT2X00_LIB_PCI
|
||||
- tristate
|
||||
+ tristate "RT2x00 PCI support"
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_SOC
|
||||
- tristate
|
||||
+ tristate "RT2x00 SoC support"
|
||||
+ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_USB
|
||||
- tristate
|
||||
+ tristate "RT2x00 USB support"
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB
|
||||
- tristate
|
||||
+ tristate "RT2x00 support"
|
||||
depends on m
|
||||
|
||||
config RT2X00_LIB_FIRMWARE
|
||||
@@ -0,0 +1,30 @@
|
||||
From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001
|
||||
From: Gabor Juhos <juhosg@openwrt.org>
|
||||
Date: Sun, 24 Mar 2013 19:26:26 +0100
|
||||
Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
@@ -210,7 +210,7 @@ endif
|
||||
config RT2800SOC
|
||||
tristate "Ralink WiSoC support"
|
||||
depends on m
|
||||
- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
|
||||
+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
|
||||
select RT2X00_LIB_SOC
|
||||
select RT2X00_LIB_MMIO
|
||||
select RT2X00_LIB_CRYPTO
|
||||
@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI
|
||||
|
||||
config RT2X00_LIB_SOC
|
||||
tristate "RT2x00 SoC support"
|
||||
- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
|
||||
+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
|
||||
depends on m
|
||||
select RT2X00_LIB
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
--- /dev/null
|
||||
+++ b/include/linux/rt2x00_platform.h
|
||||
@@ -0,0 +1,19 @@
|
||||
+/*
|
||||
+ * Platform data definition for the rt2x00 driver
|
||||
+ *
|
||||
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 as published
|
||||
+ * by the Free Software Foundation.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef _RT2X00_PLATFORM_H
|
||||
+#define _RT2X00_PLATFORM_H
|
||||
+
|
||||
+struct rt2x00_platform_data {
|
||||
+ char *eeprom_file_name;
|
||||
+};
|
||||
+
|
||||
+#endif /* _RT2X00_PLATFORM_H */
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/average.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/rt2x00_platform.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -305,6 +305,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
RT2X00_LIB_CRYPTO=
|
||||
RT2X00_LIB_LEDS=
|
||||
RT2X00_LIB_DEBUGFS=
|
||||
+RT2X00_LIB_EEPROM=
|
||||
RT2X00_DEBUG=
|
||||
WLAN_VENDOR_REALTEK=
|
||||
RTL8180=
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
@@ -69,6 +69,7 @@ config RT2800PCI
|
||||
select RT2X00_LIB_MMIO
|
||||
select RT2X00_LIB_PCI
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
+ select RT2X00_LIB_EEPROM
|
||||
select RT2X00_LIB_CRYPTO
|
||||
depends on CRC_CCITT
|
||||
depends on EEPROM_93CX6
|
||||
@@ -215,6 +216,7 @@ config RT2800SOC
|
||||
select RT2X00_LIB_MMIO
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
+ select RT2X00_LIB_EEPROM
|
||||
select RT2800_LIB
|
||||
select RT2800_LIB_MMIO
|
||||
---help---
|
||||
@@ -265,6 +267,9 @@ config RT2X00_LIB_FIRMWARE
|
||||
config RT2X00_LIB_CRYPTO
|
||||
bool
|
||||
|
||||
+config RT2X00_LIB_EEPROM
|
||||
+ boolean
|
||||
+
|
||||
config RT2X00_LIB_LEDS
|
||||
bool
|
||||
default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Makefile
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Makefile
|
||||
@@ -8,6 +8,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
|
||||
rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
|
||||
rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
|
||||
rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o
|
||||
+rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
|
||||
|
||||
obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o
|
||||
obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -48,6 +48,8 @@ struct rt2800_drv_data {
|
||||
struct ieee80211_sta *wcid_to_sta[STA_IDS_SIZE];
|
||||
};
|
||||
|
||||
+#include "rt2800.h"
|
||||
+
|
||||
struct rt2800_ops {
|
||||
u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int offset);
|
||||
@@ -146,6 +148,15 @@ static inline int rt2800_read_eeprom(str
|
||||
{
|
||||
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
|
||||
|
||||
+ if (rt2x00dev->eeprom_file) {
|
||||
+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data,
|
||||
+ EEPROM_SIZE);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (!rt2800ops->read_eeprom)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
return rt2800ops->read_eeprom(rt2x00dev);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st
|
||||
return retval;
|
||||
}
|
||||
|
||||
-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
|
||||
-
|
||||
- if (!base_addr)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
|
||||
-
|
||||
- iounmap(base_addr);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
/* Firmware functions */
|
||||
static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc
|
||||
.register_multiread = rt2x00mmio_register_multiread,
|
||||
.register_multiwrite = rt2x00mmio_register_multiwrite,
|
||||
.regbusy_read = rt2x00mmio_regbusy_read,
|
||||
- .read_eeprom = rt2800soc_read_eeprom,
|
||||
.hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
|
||||
.drv_write_firmware = rt2800soc_write_firmware,
|
||||
.drv_init_registers = rt2800mmio_init_registers,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -706,6 +706,7 @@ enum rt2x00_capability_flags {
|
||||
REQUIRE_HT_TX_DESC,
|
||||
REQUIRE_PS_AUTOWAKE,
|
||||
REQUIRE_DELAYED_RFKILL,
|
||||
+ REQUIRE_EEPROM_FILE,
|
||||
|
||||
/*
|
||||
* Capabilities
|
||||
@@ -982,6 +983,11 @@ struct rt2x00_dev {
|
||||
const struct firmware *fw;
|
||||
|
||||
/*
|
||||
+ * EEPROM image.
|
||||
+ */
|
||||
+ const struct firmware *eeprom_file;
|
||||
+
|
||||
+ /*
|
||||
* FIFO for storing tx status reports between isr and tasklet.
|
||||
*/
|
||||
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1429,6 +1429,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
|
||||
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
|
||||
INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
|
||||
|
||||
+ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
|
||||
+ if (retval)
|
||||
+ goto exit;
|
||||
+
|
||||
/*
|
||||
* Let the driver probe the device to detect the capabilities.
|
||||
*/
|
||||
@@ -1572,6 +1576,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
|
||||
* Free the driver data.
|
||||
*/
|
||||
kfree(rt2x00dev->drv_data);
|
||||
+
|
||||
+ /*
|
||||
+ * Free EEPROM image.
|
||||
+ */
|
||||
+ rt2x00lib_free_eeprom_file(rt2x00dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
|
||||
@@ -0,0 +1,106 @@
|
||||
+/*
|
||||
+ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||
+ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||
+ <http://rt2x00.serialmonkey.com>
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program; if not, write to the
|
||||
+ Free Software Foundation, Inc.,
|
||||
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ Module: rt2x00lib
|
||||
+ Abstract: rt2x00 eeprom file loading routines.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include "rt2x00.h"
|
||||
+#include "rt2x00lib.h"
|
||||
+
|
||||
+static const char *
|
||||
+rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
|
||||
+
|
||||
+ if (pdata && pdata->eeprom_file_name)
|
||||
+ return pdata->eeprom_file_name;
|
||||
+
|
||||
+ return NULL
|
||||
+}
|
||||
+
|
||||
+static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ const struct firmware *ee;
|
||||
+ const char *ee_name;
|
||||
+ int retval;
|
||||
+
|
||||
+ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
|
||||
+ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
|
||||
+ rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!ee_name)
|
||||
+ return 0;
|
||||
+
|
||||
+ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
|
||||
+
|
||||
+ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
|
||||
+ if (retval) {
|
||||
+ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
|
||||
+ return retval;
|
||||
+ }
|
||||
+
|
||||
+ if (!ee || !ee->size || !ee->data) {
|
||||
+ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
|
||||
+ retval = -ENOENT;
|
||||
+ goto err_exit;
|
||||
+ }
|
||||
+
|
||||
+ if (ee->size != rt2x00dev->ops->eeprom_size) {
|
||||
+ rt2x00_err(rt2x00dev,
|
||||
+ "EEPROM file size is invalid, it should be %d bytes\n",
|
||||
+ rt2x00dev->ops->eeprom_size);
|
||||
+ retval = -EINVAL;
|
||||
+ goto err_release_ee;
|
||||
+ }
|
||||
+
|
||||
+ rt2x00dev->eeprom_file = ee;
|
||||
+ return 0;
|
||||
+
|
||||
+err_release_ee:
|
||||
+ release_firmware(ee);
|
||||
+err_exit:
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ int retval;
|
||||
+
|
||||
+ retval = rt2x00lib_request_eeprom_file(rt2x00dev);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ if (rt2x00dev->eeprom_file && rt2x00dev->eeprom_file->size)
|
||||
+ release_firmware(rt2x00dev->eeprom_file);
|
||||
+ rt2x00dev->eeprom_file = NULL;
|
||||
+}
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
|
||||
@@ -297,6 +297,22 @@ static inline void rt2x00lib_free_firmwa
|
||||
#endif /* CPTCFG_RT2X00_LIB_FIRMWARE */
|
||||
|
||||
/*
|
||||
+ * EEPROM file handlers.
|
||||
+ */
|
||||
+#ifdef CPTCFG_RT2X00_LIB_EEPROM
|
||||
+int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev);
|
||||
+#else
|
||||
+static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+}
|
||||
+#endif /* CPTCFG_RT2X00_LIB_EEPROM */
|
||||
+
|
||||
+/*
|
||||
* Debugfs handlers.
|
||||
*/
|
||||
#ifdef CPTCFG_RT2X00_LIB_DEBUGFS
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
|
||||
@@ -97,6 +97,7 @@ int rt2x00soc_probe(struct platform_devi
|
||||
if (IS_ERR(rt2x00dev->clk))
|
||||
rt2x00dev->clk = NULL;
|
||||
|
||||
+ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
|
||||
|
||||
retval = rt2x00soc_alloc_reg(rt2x00dev);
|
||||
@@ -0,0 +1,33 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
@@ -34,11 +35,21 @@ static const char *
|
||||
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
|
||||
+#ifdef CONFIG_OF
|
||||
+ struct device_node *np;
|
||||
+ const char *eep;
|
||||
+#endif
|
||||
|
||||
if (pdata && pdata->eeprom_file_name)
|
||||
return pdata->eeprom_file_name;
|
||||
|
||||
- return NULL
|
||||
+#ifdef CONFIG_OF
|
||||
+ np = rt2x00dev->dev->of_node;
|
||||
+ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0)
|
||||
+ return eep;
|
||||
+#endif
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
|
||||
@@ -0,0 +1,107 @@
|
||||
From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
|
||||
From: John Crispin <blogic@openwrt.org>
|
||||
Date: Sun, 17 Mar 2013 00:55:04 +0100
|
||||
Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
|
||||
OF
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/Kconfig | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 65 +++++++++++++++++++++++
|
||||
2 files changed, 66 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
|
||||
@@ -219,6 +219,7 @@ config RT2800SOC
|
||||
select RT2X00_LIB_EEPROM
|
||||
select RT2800_LIB
|
||||
select RT2800_LIB_MMIO
|
||||
+ select MTD if SOC_RT288X || SOC_RT305X
|
||||
---help---
|
||||
This adds support for Ralink WiSoC devices.
|
||||
Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
|
||||
@@ -26,11 +26,72 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
|
||||
+static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ int ret = -EINVAL;
|
||||
+#ifdef CONFIG_OF
|
||||
+ static struct firmware mtd_fw;
|
||||
+ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
|
||||
+ size_t retlen, len = rt2x00dev->ops->eeprom_size;
|
||||
+ int i, size, offset = 0;
|
||||
+ struct mtd_info *mtd;
|
||||
+ const char *part;
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+
|
||||
+ list = of_get_property(np, "ralink,mtd-eeprom", &size);
|
||||
+ if (!list)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+ if (!mtd_np) {
|
||||
+ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
+ part = mtd_np->name;
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd)) {
|
||||
+ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
|
||||
+ return PTR_ERR(mtd);
|
||||
+ }
|
||||
+
|
||||
+ if (size > sizeof(*list))
|
||||
+ offset = be32_to_cpup(list);
|
||||
+
|
||||
+ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if ((retlen != rt2x00dev->ops->eeprom_size) || ret) {
|
||||
+ dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (of_find_property(np, "ralink,mtd-eeprom-swap", NULL))
|
||||
+ for (i = 0; i < len/sizeof(u16); i++)
|
||||
+ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
|
||||
+
|
||||
+ rt2x00dev->eeprom_file = &mtd_fw;
|
||||
+ mtd_fw.data = (const u8 *) rt2x00dev->eeprom;
|
||||
+
|
||||
+ dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part);
|
||||
+#endif
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static const char *
|
||||
rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
@@ -58,6 +119,9 @@ static int rt2x00lib_request_eeprom_file
|
||||
const char *ee_name;
|
||||
int retval;
|
||||
|
||||
+ if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
|
||||
+ return 0;
|
||||
+
|
||||
ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
|
||||
if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
|
||||
rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
|
||||
@@ -0,0 +1,47 @@
|
||||
--- a/include/linux/rt2x00_platform.h
|
||||
+++ b/include/linux/rt2x00_platform.h
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
struct rt2x00_platform_data {
|
||||
char *eeprom_file_name;
|
||||
+
|
||||
+ int disable_2ghz;
|
||||
+ int disable_5ghz;
|
||||
};
|
||||
|
||||
#endif /* _RT2X00_PLATFORM_H */
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1023,6 +1023,22 @@ static int rt2x00lib_probe_hw_modes(stru
|
||||
unsigned int num_rates;
|
||||
unsigned int i;
|
||||
|
||||
+ if (rt2x00dev->dev->platform_data) {
|
||||
+ struct rt2x00_platform_data *pdata;
|
||||
+
|
||||
+ pdata = rt2x00dev->dev->platform_data;
|
||||
+ if (pdata->disable_2ghz)
|
||||
+ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
|
||||
+ if (pdata->disable_5ghz)
|
||||
+ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
|
||||
+ }
|
||||
+
|
||||
+ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
|
||||
+ rt2x00_err(rt2x00dev, "No supported bands\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
num_rates = 0;
|
||||
if (spec->supported_rates & SUPPORT_RATE_CCK)
|
||||
num_rates += 4;
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -411,6 +411,7 @@ struct hw_mode_spec {
|
||||
unsigned int supported_bands;
|
||||
#define SUPPORT_BAND_2GHZ 0x00000001
|
||||
#define SUPPORT_BAND_5GHZ 0x00000002
|
||||
+#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
|
||||
|
||||
unsigned int supported_rates;
|
||||
#define SUPPORT_RATE_CCK 0x00000001
|
||||
@@ -0,0 +1,26 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1001,8 +1001,13 @@ static void rt2x00lib_rate(struct ieee80
|
||||
|
||||
void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
|
||||
{
|
||||
+ struct rt2x00_platform_data *pdata;
|
||||
const char *mac_addr;
|
||||
|
||||
+ pdata = rt2x00dev->dev->platform_data;
|
||||
+ if (pdata && pdata->mac_address)
|
||||
+ ether_addr_copy(eeprom_mac_addr, pdata->mac_address);
|
||||
+
|
||||
mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
|
||||
if (mac_addr)
|
||||
ether_addr_copy(eeprom_mac_addr, mac_addr);
|
||||
--- a/include/linux/rt2x00_platform.h
|
||||
+++ b/include/linux/rt2x00_platform.h
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
struct rt2x00_platform_data {
|
||||
char *eeprom_file_name;
|
||||
+ const u8 *mac_address;
|
||||
|
||||
int disable_2ghz;
|
||||
int disable_5ghz;
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1027,6 +1027,16 @@ static int rt2x00lib_probe_hw_modes(stru
|
||||
struct ieee80211_rate *rates;
|
||||
unsigned int num_rates;
|
||||
unsigned int i;
|
||||
+#ifdef CONFIG_OF
|
||||
+ struct device_node *np = rt2x00dev->dev->of_node;
|
||||
+ unsigned int enabled;
|
||||
+ if (!of_property_read_u32(np, "ralink,2ghz",
|
||||
+ &enabled) && !enabled)
|
||||
+ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
|
||||
+ if (!of_property_read_u32(np, "ralink,5ghz",
|
||||
+ &enabled) && !enabled)
|
||||
+ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
|
||||
+#endif /* CONFIG_OF */
|
||||
|
||||
if (rt2x00dev->dev->platform_data) {
|
||||
struct rt2x00_platform_data *pdata;
|
||||
@@ -0,0 +1,33 @@
|
||||
From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001
|
||||
From: John Crispin <blogic@openwrt.org>
|
||||
Date: Sun, 17 Mar 2013 00:03:31 +0100
|
||||
Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC
|
||||
|
||||
This patch ads the match table to allow loading the wmac support from a
|
||||
devicetree.
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -235,10 +235,17 @@ static int rt2800soc_probe(struct platfo
|
||||
return rt2x00soc_probe(pdev, &rt2800soc_ops);
|
||||
}
|
||||
|
||||
+static const struct of_device_id rt2880_wmac_match[] = {
|
||||
+ { .compatible = "ralink,rt2880-wmac" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
|
||||
+
|
||||
static struct platform_driver rt2800soc_driver = {
|
||||
.driver = {
|
||||
.name = "rt2800_wmac",
|
||||
.mod_name = KBUILD_MODNAME,
|
||||
+ .of_match_table = rt2880_wmac_match,
|
||||
},
|
||||
.probe = rt2800soc_probe,
|
||||
.remove = rt2x00soc_remove,
|
||||
@@ -0,0 +1,40 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/of.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2800lib.h"
|
||||
@@ -9542,6 +9543,17 @@ static int rt2800_init_eeprom(struct rt2
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
|
||||
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
|
||||
|
||||
+ {
|
||||
+ struct device_node *np = rt2x00dev->dev->of_node;
|
||||
+ unsigned int led_polarity;
|
||||
+
|
||||
+ /* Allow overriding polarity from OF */
|
||||
+ if (!of_property_read_u32(np, "ralink,led-polarity",
|
||||
+ &led_polarity))
|
||||
+ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
|
||||
+ led_polarity);
|
||||
+ }
|
||||
+
|
||||
rt2x00dev->led_mcu_reg = eeprom;
|
||||
#endif /* CPTCFG_RT2X00_LIB_LEDS */
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
|
||||
@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc
|
||||
led->led_dev.name = name;
|
||||
led->led_dev.brightness = LED_OFF;
|
||||
|
||||
+ if (rt2x00_is_soc(rt2x00dev))
|
||||
+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
|
||||
+
|
||||
retval = led_classdev_register(device, &led->led_dev);
|
||||
if (retval) {
|
||||
rt2x00_err(rt2x00dev, "Failed to register led handler\n");
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1367,7 +1367,7 @@ static inline void rt2x00lib_set_if_comb
|
||||
*/
|
||||
if_limit = &rt2x00dev->if_limits_ap;
|
||||
if_limit->max = rt2x00dev->ops->max_ap_intf;
|
||||
- if_limit->types = BIT(NL80211_IFTYPE_AP);
|
||||
+ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
|
||||
#ifdef CPTCFG_MAC80211_MESH
|
||||
if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Mon, 16 Dec 2019 20:47:06 +0100
|
||||
Subject: [PATCH] rt2x00: add throughput LED trigger
|
||||
|
||||
This adds a (currently missing) throughput LED trigger for the rt2x00
|
||||
driver. Previously, LED triggers had to be assigned to the netdev, which
|
||||
was limited to a single VAP.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
Tested-by: Christoph Krapp <achterin@googlemail.com>
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1140,6 +1140,19 @@ static void rt2x00lib_remove_hw(struct r
|
||||
kfree(rt2x00dev->spec.channels_info);
|
||||
}
|
||||
|
||||
+static const struct ieee80211_tpt_blink rt2x00_tpt_blink[] = {
|
||||
+ { .throughput = 0 * 1024, .blink_time = 334 },
|
||||
+ { .throughput = 1 * 1024, .blink_time = 260 },
|
||||
+ { .throughput = 2 * 1024, .blink_time = 220 },
|
||||
+ { .throughput = 5 * 1024, .blink_time = 190 },
|
||||
+ { .throughput = 10 * 1024, .blink_time = 170 },
|
||||
+ { .throughput = 25 * 1024, .blink_time = 150 },
|
||||
+ { .throughput = 54 * 1024, .blink_time = 130 },
|
||||
+ { .throughput = 120 * 1024, .blink_time = 110 },
|
||||
+ { .throughput = 265 * 1024, .blink_time = 80 },
|
||||
+ { .throughput = 586 * 1024, .blink_time = 50 },
|
||||
+};
|
||||
+
|
||||
static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
@@ -1222,6 +1235,10 @@ static int rt2x00lib_probe_hw(struct rt2
|
||||
|
||||
#undef RT2X00_TASKLET_INIT
|
||||
|
||||
+ ieee80211_create_tpt_led_trigger(rt2x00dev->hw,
|
||||
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, rt2x00_tpt_blink,
|
||||
+ ARRAY_SIZE(rt2x00_tpt_blink));
|
||||
+
|
||||
/*
|
||||
* Register HW.
|
||||
*/
|
||||
@@ -0,0 +1,107 @@
|
||||
From 9782a7f7488443568fa4d6088b73c9aff7eb8510 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Wed, 19 Apr 2017 16:14:53 +0200
|
||||
Subject: [PATCH] rt2x00: add support for external PA on MT7620
|
||||
To: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Cc: Helmut Schaa <helmut.schaa@googlemail.com>,
|
||||
linux-wireless@vger.kernel.org,
|
||||
Kalle Valo <kvalo@codeaurora.org>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Signed-off-by: Tomislav Po=C5=BEega <pozega.tomislav@gmail.com>
|
||||
[pozega.tomislav@gmail.com: use chanreg and dccal helpers.]
|
||||
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++-
|
||||
2 files changed, 70 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
@@ -2750,6 +2750,7 @@ enum rt2800_eeprom_word {
|
||||
#define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f)
|
||||
#define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0)
|
||||
#define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600)
|
||||
+#define EEPROM_NIC_CONF2_EXTERNAL_PA FIELD16(0xc000)
|
||||
|
||||
/*
|
||||
* EEPROM LNA
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -4370,6 +4370,45 @@ static void rt2800_config_channel(struct
|
||||
rt2800_iq_calibrate(rt2x00dev, rf->channel);
|
||||
}
|
||||
|
||||
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
+ &rt2x00dev->cap_flags)) {
|
||||
+ rt2x00_warn(rt2x00dev, "Using incomplete support for " \
|
||||
+ "external PA\n");
|
||||
+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ reg |= 0x00000101;
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
|
||||
+
|
||||
+ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+ reg |= 0x00000101;
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
|
||||
+
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
|
||||
+ 0x36303636);
|
||||
+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
|
||||
+ 0x6C6C6B6C);
|
||||
+ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
|
||||
+ 0x6C6C6B6C);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
bbp = rt2800_bbp_read(rt2x00dev, 4);
|
||||
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
|
||||
rt2800_bbp_write(rt2x00dev, 4, bbp);
|
||||
@@ -9571,7 +9610,8 @@ static int rt2800_init_eeprom(struct rt2
|
||||
*/
|
||||
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3352)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3352) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
if (rt2x00_get_field16(eeprom,
|
||||
EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
|
||||
__set_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
@@ -9582,6 +9622,18 @@ static int rt2800_init_eeprom(struct rt2
|
||||
&rt2x00dev->cap_flags);
|
||||
}
|
||||
|
||||
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2);
|
||||
+
|
||||
+ if (rt2x00_rt(rt2x00dev, RT6352) && eeprom != 0 && eeprom != 0xffff) {
|
||||
+ if (rt2x00_get_field16(eeprom,
|
||||
+ EEPROM_NIC_CONF2_EXTERNAL_PA)) {
|
||||
+ __set_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
+ &rt2x00dev->cap_flags);
|
||||
+ __set_bit(CAPABILITY_EXTERNAL_PA_TX1,
|
||||
+ &rt2x00dev->cap_flags);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8433,6 +8433,58 @@ static void rt2800_init_rfcsr_5592(struc
|
||||
rt2800_led_open_drain_enable(rt2x00dev);
|
||||
}
|
||||
|
||||
+void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 rfb5r1_org, rfb7r1_org, rfvalue;
|
||||
+ u32 mac0518, mac051c, mac0528, mac052c;
|
||||
+ u8 i;
|
||||
+
|
||||
+ rt2x00_info(rt2x00dev, "RF Tx self calibration start\n");
|
||||
+ mac0518 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ mac051c = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ mac0528 = rt2800_register_read(rt2x00dev, RF_CONTROL2);
|
||||
+ mac052c = rt2800_register_read(rt2x00dev, RF_BYPASS2);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0xC);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x3306);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL2, 0x3330);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0xfffff);
|
||||
+ rfb5r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
|
||||
+ rfb7r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, 0x4);
|
||||
+ for (i = 0; i < 100; i = i + 1) {
|
||||
+ udelay(50);
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
|
||||
+ if((rfvalue & 0x04) != 0x4)
|
||||
+ break;
|
||||
+ }
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, rfb5r1_org);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, 0x4);
|
||||
+ for (i = 0; i < 100; i = i + 1) {
|
||||
+ udelay(50);
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1);
|
||||
+ if((rfvalue & 0x04) != 0x4)
|
||||
+ break;
|
||||
+ }
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, rfb7r1_org);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, mac0518);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, mac051c);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL2, mac0528);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, mac052c);
|
||||
+
|
||||
+ rt2x00_info(rt2x00dev, "RF Tx self calibration end\n");
|
||||
+
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_rf_self_txdc_cal);
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9040,6 +9092,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
+ rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
}
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -253,6 +253,7 @@ void rt2800_link_tuner(struct rt2x00_dev
|
||||
const u32 count);
|
||||
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -574,6 +574,7 @@ struct rt2x00lib_ops {
|
||||
struct link_qual *qual, const u32 count);
|
||||
void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
+ void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* Data queue handlers.
|
||||
@@ -0,0 +1,193 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8485,6 +8485,160 @@ void rt2800_rf_self_txdc_cal(struct rt2x
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_rf_self_txdc_cal);
|
||||
|
||||
+int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2)
|
||||
+{
|
||||
+ int calcode;
|
||||
+ calcode = ((d2 - d1) * 1000) / 43;
|
||||
+ if ((calcode%10) >= 5)
|
||||
+ calcode += 10;
|
||||
+ calcode = (calcode / 10);
|
||||
+
|
||||
+ return calcode;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_calcrcalibrationcode);
|
||||
+
|
||||
+void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u32 savemacsysctrl;
|
||||
+ u8 saverfb0r1, saverfb0r34, saverfb0r35;
|
||||
+ u8 saverfb5r4, saverfb5r17, saverfb5r18;
|
||||
+ u8 saverfb5r19, saverfb5r20;
|
||||
+ u8 savebbpr22, savebbpr47, savebbpr49;
|
||||
+ u8 bytevalue = 0;
|
||||
+ int rcalcode;
|
||||
+ u8 r_cal_code = 0;
|
||||
+ char d1 = 0, d2 = 0;
|
||||
+ u8 rfvalue;
|
||||
+ u32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG;
|
||||
+
|
||||
+ saverfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ saverfb0r34 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 34);
|
||||
+ saverfb0r35 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35);
|
||||
+ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ saverfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
|
||||
+ saverfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
|
||||
+ saverfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
|
||||
+ saverfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
|
||||
+
|
||||
+ savebbpr22 = rt2800_bbp_read(rt2x00dev, 22);
|
||||
+ savebbpr47 = rt2800_bbp_read(rt2x00dev, 47);
|
||||
+ savebbpr49 = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ MAC_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ MAC_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ MAC_PWR_PIN_CFG = rt2800_register_read(rt2x00dev, PWR_PIN_CFG);
|
||||
+
|
||||
+ {
|
||||
+ u32 maccfg, macstatus;
|
||||
+ int i;
|
||||
+
|
||||
+ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ maccfg &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
+ if (macstatus & 0x1)
|
||||
+ udelay(50);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i == 10000)
|
||||
+ rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n");
|
||||
+
|
||||
+ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ maccfg &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
+ if (macstatus & 0x2)
|
||||
+ udelay(50);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i == 10000)
|
||||
+ rt2x00_warn(rt2x00dev, "Wait MAC Rx Status to MAX !!!\n");
|
||||
+ }
|
||||
+
|
||||
+ rfvalue = (MAC_RF_BYPASS0 | 0x3004);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, rfvalue);
|
||||
+ rfvalue = (MAC_RF_CONTROL0 | (~0x3002));
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, rfvalue);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, 0x27);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0x83);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, 0x13);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x1);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 47, 0x04);
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x80);
|
||||
+ udelay(100);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+ if (bytevalue > 128)
|
||||
+ d1 = bytevalue - 256;
|
||||
+ else
|
||||
+ d1 = (char)bytevalue;
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x01);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x80);
|
||||
+ udelay(100);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+ if (bytevalue > 128)
|
||||
+ d2 = bytevalue - 256;
|
||||
+ else
|
||||
+ d2 = (char)bytevalue;
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+
|
||||
+ rcalcode = rt2800_calcrcalibrationcode(rt2x00dev, d1, d2);
|
||||
+ if (rcalcode < 0)
|
||||
+ r_cal_code = 256 + rcalcode;
|
||||
+ else
|
||||
+ r_cal_code = (u8)rcalcode;
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 7, r_cal_code);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bytevalue |= 0x1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bytevalue);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bytevalue &= (~0x1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bytevalue);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, saverfb0r1);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, saverfb0r34);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, saverfb0r35);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, saverfb5r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, saverfb5r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, saverfb5r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, saverfb5r20);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, savebbpr22);
|
||||
+ rt2800_bbp_write(rt2x00dev, 47, savebbpr47);
|
||||
+ rt2800_bbp_write(rt2x00dev, 49, savebbpr49);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, MAC_RF_BYPASS0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, MAC_RF_CONTROL0);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_r_calibration);
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9092,6 +9246,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
+ rt2800_r_calibration(rt2x00dev);
|
||||
rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -254,6 +254,8 @@ void rt2800_link_tuner(struct rt2x00_dev
|
||||
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
|
||||
+int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
+void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -575,6 +575,8 @@ struct rt2x00lib_ops {
|
||||
void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
|
||||
+ int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
+ void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* Data queue handlers.
|
||||
@@ -0,0 +1,102 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8639,6 +8639,71 @@ void rt2800_r_calibration(struct rt2x00_
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_r_calibration);
|
||||
|
||||
+void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 bbpreg = 0;
|
||||
+ u32 macvalue = 0, macvalue1 = 0;
|
||||
+ u8 saverfb0r2, saverfb5r4, saverfb7r4, rfvalue;
|
||||
+ int i;
|
||||
+
|
||||
+ saverfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rfvalue = saverfb0r2;
|
||||
+ rfvalue |= 0x03;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfvalue);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg |= 0x10;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x8);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ macvalue1 = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
+ if (macvalue1 & 0x1)
|
||||
+ udelay(50);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
|
||||
+ saverfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
|
||||
+ saverfb5r4 = saverfb5r4 & (~0x40);
|
||||
+ saverfb7r4 = saverfb7r4 & (~0x40);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x64);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, saverfb7r4);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg = bbpreg & (~0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+ bbpreg |= 0x48;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ if ((bbpreg & 0x40)==0)
|
||||
+ break;
|
||||
+ udelay(50);
|
||||
+ }
|
||||
+
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg = bbpreg & (~0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg &= (~0x10);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_rxdcoc_calibration);
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9248,6 +9313,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
|
||||
rt2800_r_calibration(rt2x00dev);
|
||||
rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
+ rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
}
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -256,6 +256,7 @@ void rt2800_vco_calibration(struct rt2x0
|
||||
void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
|
||||
int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -577,6 +577,7 @@ struct rt2x00lib_ops {
|
||||
void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
|
||||
int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
+ void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* Data queue handlers.
|
||||
@@ -0,0 +1,417 @@
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8704,6 +8704,386 @@ void rt2800_rxdcoc_calibration(struct rt
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_rxdcoc_calibration);
|
||||
|
||||
+static u32 rt2800_do_sqrt_accumulation(u32 si) {
|
||||
+ u32 root, root_pre, bit;
|
||||
+ char i;
|
||||
+ bit = 1 << 15;
|
||||
+ root = 0;
|
||||
+ for (i = 15; i >= 0; i = i - 1) {
|
||||
+ root_pre = root + bit;
|
||||
+ if ((root_pre*root_pre) <= si)
|
||||
+ root = root_pre;
|
||||
+ bit = bit >> 1;
|
||||
+ }
|
||||
+
|
||||
+ return root;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_do_sqrt_accumulation);
|
||||
+
|
||||
+void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev) {
|
||||
+ u8 rfb0r1, rfb0r2, rfb0r42;
|
||||
+ u8 rfb4r0, rfb4r19;
|
||||
+ u8 rfb5r3, rfb5r4, rfb5r17, rfb5r18, rfb5r19, rfb5r20;
|
||||
+ u8 rfb6r0, rfb6r19;
|
||||
+ u8 rfb7r3, rfb7r4, rfb7r17, rfb7r18, rfb7r19, rfb7r20;
|
||||
+
|
||||
+ u8 bbp1, bbp4;
|
||||
+ u8 bbpr241, bbpr242;
|
||||
+ u32 i;
|
||||
+ u8 ch_idx;
|
||||
+ u8 bbpval;
|
||||
+ u8 rfval, vga_idx = 0;
|
||||
+ int mi = 0, mq = 0, si = 0, sq = 0, riq = 0;
|
||||
+ int sigma_i, sigma_q, r_iq, g_rx;
|
||||
+ int g_imb;
|
||||
+ int ph_rx;
|
||||
+ u32 savemacsysctrl = 0;
|
||||
+ u32 orig_RF_CONTROL0 = 0;
|
||||
+ u32 orig_RF_BYPASS0 = 0;
|
||||
+ u32 orig_RF_CONTROL1 = 0;
|
||||
+ u32 orig_RF_BYPASS1 = 0;
|
||||
+ u32 orig_RF_CONTROL3 = 0;
|
||||
+ u32 orig_RF_BYPASS3 = 0;
|
||||
+ u32 macstatus, bbpval1 = 0;
|
||||
+ u8 rf_vga_table[] = {0x20, 0x21, 0x22, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f};
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ orig_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ orig_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ orig_RF_CONTROL1 = rt2800_register_read(rt2x00dev, RF_CONTROL1);
|
||||
+ orig_RF_BYPASS1 = rt2800_register_read(rt2x00dev, RF_BYPASS1);
|
||||
+ orig_RF_CONTROL3 = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ orig_RF_BYPASS3 = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+
|
||||
+ bbp1 = rt2800_bbp_read(rt2x00dev, 1);
|
||||
+ bbp4 = rt2800_bbp_read(rt2x00dev, 4);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x0);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
+ if (macstatus & 0x3)
|
||||
+ udelay(50);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i == 10000)
|
||||
+ rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n");
|
||||
+
|
||||
+ bbpval = bbp4 & (~0x18);
|
||||
+ bbpval = bbp4 | 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbpval);
|
||||
+
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bbpval = bbpval | 1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+ bbpval = bbpval & 0xfe;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL1, 0x00000202);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS1, 0x00000303);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0101);
|
||||
+ } else {
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0000);
|
||||
+ }
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0xf1f1);
|
||||
+
|
||||
+ rfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ rfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rfb0r42 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42);
|
||||
+ rfb4r0 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 0);
|
||||
+ rfb4r19 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 19);
|
||||
+ rfb5r3 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
|
||||
+ rfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ rfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
|
||||
+ rfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
|
||||
+ rfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
|
||||
+ rfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
|
||||
+
|
||||
+ rfb6r0 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 0);
|
||||
+ rfb6r19 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 19);
|
||||
+ rfb7r3 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 3);
|
||||
+ rfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
|
||||
+ rfb7r17 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 17);
|
||||
+ rfb7r18 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 18);
|
||||
+ rfb7r19 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 19);
|
||||
+ rfb7r20 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x87);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0x27);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x38);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x38);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 18, 0xC1);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 19, 0x60);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 20, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x0);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 5, 0x0);
|
||||
+
|
||||
+ bbpr241 = rt2800_bbp_read(rt2x00dev, 241);
|
||||
+ bbpr242 = rt2800_bbp_read(rt2x00dev, 242);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, 0x10);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, 0x84);
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x31);
|
||||
+
|
||||
+ bbpval = rt2800_bbp_dcoc_read(rt2x00dev, 3);
|
||||
+ bbpval = bbpval & (~0x7);
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 3, bbpval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006);
|
||||
+ usleep_range(1, 200);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003376);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006);
|
||||
+ udelay(1);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x06);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x06);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x02);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x02);
|
||||
+ }
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx = ch_idx + 1) {
|
||||
+ if (ch_idx == 0) {
|
||||
+ rfval = rfb0r1 & (~0x3);
|
||||
+ rfval = rfb0r1 | 0x1;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval);
|
||||
+ rfval = rfb0r2 & (~0x33);
|
||||
+ rfval = rfb0r2 | 0x11;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval);
|
||||
+ rfval = rfb0r42 & (~0x50);
|
||||
+ rfval = rfb0r42 | 0x10;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ bbpval = bbp1 & (~ 0x18);
|
||||
+ bbpval = bbpval | 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbpval);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x00);
|
||||
+ } else {
|
||||
+ rfval = rfb0r1 & (~0x3);
|
||||
+ rfval = rfb0r1 | 0x2;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval);
|
||||
+ rfval = rfb0r2 & (~0x33);
|
||||
+ rfval = rfb0r2 | 0x22;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval);
|
||||
+ rfval = rfb0r42 & (~0x50);
|
||||
+ rfval = rfb0r42 | 0x40;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002006);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ bbpval = bbp1 & (~ 0x18);
|
||||
+ bbpval = bbpval | 0x08;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbpval);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x01);
|
||||
+ }
|
||||
+ udelay(500);
|
||||
+
|
||||
+ vga_idx = 0;
|
||||
+ while (vga_idx < 11) {
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rf_vga_table[vga_idx]);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rf_vga_table[vga_idx]);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 0, 0x93);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ if ((bbpval & 0xff) == 0x93)
|
||||
+ udelay(50);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((bbpval & 0xff) == 0x93) {
|
||||
+ rt2x00_warn(rt2x00dev, "Fatal Error: Calibration doesn't finish");
|
||||
+ goto restore_value;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ u32 bbptemp = 0;
|
||||
+ u8 value = 0;
|
||||
+ int result = 0;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x1e);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, i);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x22);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 24);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x21);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 16);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x20);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 8);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x1f);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + value;
|
||||
+
|
||||
+ if ((i < 2) && (bbptemp & 0x800000))
|
||||
+ result = (bbptemp & 0xffffff) - 0x1000000;
|
||||
+ else if (i == 4)
|
||||
+ result = bbptemp;
|
||||
+ else
|
||||
+ result = bbptemp;
|
||||
+
|
||||
+ if (i == 0)
|
||||
+ mi = result/4096;
|
||||
+ else if (i == 1)
|
||||
+ mq = result/4096;
|
||||
+ else if (i == 2)
|
||||
+ si = bbptemp/4096;
|
||||
+ else if (i == 3)
|
||||
+ sq = bbptemp/4096;
|
||||
+ else
|
||||
+ riq = result/4096;
|
||||
+ }
|
||||
+
|
||||
+ bbpval1 = si - mi*mi;
|
||||
+ rt2x00_dbg(rt2x00dev, "RXIQ si=%d, sq=%d, riq=%d, bbpval %d, vga_idx %d", si, sq, riq, bbpval1, vga_idx);
|
||||
+
|
||||
+ if (bbpval1 >= (100*100))
|
||||
+ break;
|
||||
+
|
||||
+ if (bbpval1 <= 100)
|
||||
+ vga_idx = vga_idx + 9;
|
||||
+ else if (bbpval1 <= 158)
|
||||
+ vga_idx = vga_idx + 8;
|
||||
+ else if (bbpval1 <= 251)
|
||||
+ vga_idx = vga_idx + 7;
|
||||
+ else if (bbpval1 <= 398)
|
||||
+ vga_idx = vga_idx + 6;
|
||||
+ else if (bbpval1 <= 630)
|
||||
+ vga_idx = vga_idx + 5;
|
||||
+ else if (bbpval1 <= 1000)
|
||||
+ vga_idx = vga_idx + 4;
|
||||
+ else if (bbpval1 <= 1584)
|
||||
+ vga_idx = vga_idx + 3;
|
||||
+ else if (bbpval1 <= 2511)
|
||||
+ vga_idx = vga_idx + 2;
|
||||
+ else
|
||||
+ vga_idx = vga_idx + 1;
|
||||
+ }
|
||||
+
|
||||
+ sigma_i = rt2800_do_sqrt_accumulation(100*(si - mi*mi));
|
||||
+ sigma_q = rt2800_do_sqrt_accumulation(100*(sq - mq*mq));
|
||||
+ r_iq = 10*(riq-(mi*mq));
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "Sigma_i=%d, Sigma_q=%d, R_iq=%d", sigma_i, sigma_q, r_iq);
|
||||
+
|
||||
+ if (((sigma_i <= 1400 ) && (sigma_i >= 1000))
|
||||
+ && ((sigma_i - sigma_q) <= 112)
|
||||
+ && ((sigma_i - sigma_q) >= -112)
|
||||
+ && ((mi <= 32) && (mi >= -32))
|
||||
+ && ((mq <= 32) && (mq >= -32))) {
|
||||
+ r_iq = 10*(riq-(mi*mq));
|
||||
+ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", sigma_i, sigma_q, r_iq);
|
||||
+
|
||||
+ g_rx = (1000 * sigma_q) / sigma_i;
|
||||
+ g_imb = ((-2) * 128 * (1000 - g_rx)) / (1000 + g_rx);
|
||||
+ ph_rx = (r_iq * 2292) / (sigma_i * sigma_q);
|
||||
+ rt2x00_info(rt2x00dev, "RXIQ G_imb=%d, Ph_rx=%d\n", g_imb, ph_rx);
|
||||
+
|
||||
+ if ((ph_rx > 20) || (ph_rx < -20)) {
|
||||
+ ph_rx = 0;
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+
|
||||
+ if ((g_imb > 12) || (g_imb < -12)) {
|
||||
+ g_imb = 0;
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ g_imb = 0;
|
||||
+ ph_rx = 0;
|
||||
+ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", sigma_i, sigma_q, r_iq);
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+
|
||||
+ if (ch_idx == 0) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x37);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x35);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x55);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x53);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+restore_value:
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x3);
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, (bbpval | 0x07));
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbp1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbp4);
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, bbpr241);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, bbpr242);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x00);
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bbpval = (bbpval | 0x1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+ usleep_range(10, 200);
|
||||
+ bbpval = (bbpval & 0xfe);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfb0r1);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfb0r2);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfb0r42);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 0, rfb4r0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 19, rfb4r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rfb5r3);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, rfb5r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, rfb5r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, rfb5r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, rfb5r20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 0, rfb6r0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 19, rfb6r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 3, rfb7r3);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, rfb7r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 17, rfb7r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 18, rfb7r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, rfb7r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, rfb7r20);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, orig_RF_CONTROL0);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, orig_RF_BYPASS0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL1, orig_RF_CONTROL1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS1, orig_RF_BYPASS1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, orig_RF_CONTROL3);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, orig_RF_BYPASS3);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rt2800_rxiq_calibration);
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9316,6 +9696,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
+ rt2800_rxiq_calibration(rt2x00dev);
|
||||
}
|
||||
|
||||
static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -257,6 +257,7 @@ void rt2800_rf_self_txdc_cal(struct rt2x
|
||||
int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
+void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
|
||||
@@ -578,6 +578,7 @@ struct rt2x00lib_ops {
|
||||
int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
|
||||
void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
+ void (*rxiq_calibration) (struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* Data queue handlers.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user