[rt2x00-users] [PATCH] rt2x00 : rt2800pci tx and rx take 3 .
Alban Browaeys
prahal at yahoo.com
Fri Jul 17 01:36:08 EST 2009
This one add another hack but get the thing working against hostap
(which has header_length 26 instead of 24 for freebox wpa).
This was tested against hostap in wpa personal and open.
And also against freebox wpa (based on linux but internals not disclosed).
I would really appreciate a better solution or an explanation as to why ALIGN_SIZE
was what it was (that is check for the position in memory of the header end).
This change make it a diff on a roundup of header length around 4.
Otherwise I always get 0 for align size be the header_length 24 or 26.
change from the previous patch also include a fix in txdone to check for ">" queue_limit
instead of ">=" (as I add 1 beforehand to the entry idx and only remove this 1 after this check).
I ll check against WEP 'orange' livebox as soon as possible though the issue was the same as with hostap (auth and assoc
where working as of they had header_length 24 while data packets afterwards were corrupted as of with header_length 26.
By the way I check again in rt2860 and bHwRadio is true when gpio is (& 4) == 1 ... and I tried reverting the hack on rt2800pci_rfkill
with no working setup resulting (mac80211 always stop the interface asap when using the opposite value). So I ll need confirmation and
more inputs from another tester using rt2800pci to find out what should be done to get the interface staying up while at the same time
sending rfkill block when gpio is 1.
NB: I found out that if I load rt2860sta and unload it then load rt2800pci the tx are not working (gpio is 1). Thus I though I found this test case to find out about rfkill but it turned out using the platform driver (eeepc_laptop) rfkill switch off then on everything is back to normal (tx are transmitted). One may have to unload rt2800pci and reload it to free the queue which are full though to see tx working.
I still have not tested again without adding 1 to entry_idx and queue->qid in write_tx_desc . I first planned to do it today but found this
align size issue and it took me a while to find at least a hack to get an idea on what was at stake. I hope a well done answer can be found
for this peculiar issue. Because mine looks harsh and looks like it could break other drivers (I have not checked which ones are using txdesc l2pad.
Best regards
Alban
Signed-off-by: Alban Browaeys <prahal at yahoo.com>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 98 ++++++++++++++++++++----------
drivers/net/wireless/rt2x00/rt2x00.h | 3 +-
2 files changed, 67 insertions(+), 34 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 372c632..7523866 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -380,7 +380,7 @@ static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg;
rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®);
- return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+ return !rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
}
#ifdef CONFIG_RT2X00_LIB_LEDS
@@ -1389,19 +1389,6 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
u32 reg;
unsigned int i;
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1);
- rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
-
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
-
rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®);
@@ -1647,6 +1634,9 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_read(rt2x00dev, TX_STA_CNT1, ®);
rt2x00pci_register_read(rt2x00dev, TX_STA_CNT2, ®);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+
return 0;
}
@@ -1957,6 +1947,21 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
u32 reg;
u16 word;
+
+ // pbf hardware reset : force write of wpdma updated value
+ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1);
+ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+
/*
* Initialize all registers.
*/
@@ -2030,6 +2035,17 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
/* Wait for DMA, ignore error */
+ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1);
+ rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1);
+ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
rt2800pci_wait_wpdma_ready(rt2x00dev);
}
@@ -2145,14 +2161,17 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
- test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- txdesc->key_idx : 0xff);
+ skbdesc->entry->entry_idx + 1);
+ //test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
+ // txdesc->key_idx : 0xff);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
skb->len - txdesc->l2pad);
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
- skbdesc->entry->queue->qid);
+ //skbdesc->entry->entry_idx);
+ skbdesc->entry->queue->qid+1);
rt2x00_desc_write(txwi, 1, word);
+
/*
* Always write 0 to IV/EIV fields, hardware will insert the IV
* from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0.
@@ -2176,7 +2195,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W1_BURST,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W1_SD_LEN0,
- rt2x00dev->hw->extra_tx_headroom);
+ rt2x00dev->hw->extra_tx_headroom + skb->len);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC0,
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
@@ -2236,7 +2255,8 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue_idx)
{
struct data_queue *queue;
- unsigned int idx, qidx = 0;
+ unsigned int index, index_back, qidx = 0;
+ struct queue_entry *entry;
u32 reg;
if (queue_idx == QID_BEACON) {
@@ -2254,14 +2274,21 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
return;
queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
- idx = queue->index[Q_INDEX];
if (queue_idx == QID_MGMT)
qidx = 5;
else
qidx = queue_idx;
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx);
+
+ index = queue->index[Q_INDEX];
+ index_back = index;
+ if(index_back == 0) index_back = queue->limit;
+ index_back -= 1;
+ entry = &queue->entries[index_back];
+
+ if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), index);
}
static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
@@ -2289,8 +2316,8 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
- __le32 *rxd = entry_priv->desc;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ __le32 *rxd = (__le32 *)skbdesc;
__le32 *rxwi = (__le32 *)entry->skb->data;
u32 rxd3;
u32 rxwi0;
@@ -2375,15 +2402,12 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
/*
- * Remove TXWI descriptor from start of buffer.
+ * Remove RX descriptor from start of buffer.
*/
- skb_pull(entry->skb, RXWI_DESC_SIZE);
+ skb_pull(entry->skb, skbdesc->desc_len);
skb_trim(entry->skb, rxdesc->size);
}
-/*
- * Interrupt functions.
- */
static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
@@ -2420,7 +2444,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* Skip this entry when it contains an invalid
* queue identication number.
*/
- type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+ type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1;
queue = rt2x00queue_get_queue(rt2x00dev, type);
if (unlikely(!queue))
continue;
@@ -2430,11 +2454,19 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* index number.
*/
index = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- if (unlikely(index >= queue->limit))
+ if (unlikely(index > queue->limit))
continue;
- entry = &queue->entries[index];
- entry_priv = entry->priv_data;
+ if(index == 0) index = queue->limit;
+ entry = &queue->entries[index - 1];
+
+
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
+ !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ break;
+
+ entry_priv = entry->priv_data;
+
rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
@@ -3111,7 +3143,7 @@ static const struct data_queue_desc rt2800pci_queue_tx = {
static const struct data_queue_desc rt2800pci_queue_bcn = {
.entry_num = 8 * BEACON_ENTRIES,
.data_size = 0, /* No DMA required for beacons */
- .desc_size = TXWI_DESC_SIZE,
+ .desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index de3f13a..d9e75eb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -109,7 +109,8 @@
* amount of bytes needed to move the data.
*/
#define ALIGN_SIZE(__skb, __header) \
- ( ((unsigned long)((__skb)->data + (__header))) & 3 )
+ ( ((unsigned long)(roundup((__header), 4)- (__header))) & 3 )
+ //( ((unsigned long)((__skb)->data + (__header))) & 3 )
/*
* Standard timing and size defines.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-rt2x00-rt2800pci-tx-and-rx-take-3.patch
Type: text/x-patch
Size: 8860 bytes
Desc: not available
URL: <http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/attachments/20090716/1b48b84a/attachment-0001.bin>
More information about the users
mailing list