/*
* TX descriptor initialization
*/
-static int rt2800pci_write_tx_data(struct queue_entry* entry,
- struct txentry_desc *txdesc)
+static void rt2800pci_write_tx_datadesc(struct queue_entry* entry,
+ struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct sk_buff *skb = entry->skb;
- struct skb_frame_desc *skbdesc;
- int ret;
- __le32 *txwi;
- u32 word;
-
- ret = rt2x00pci_write_tx_data(entry, txdesc);
- if (ret)
- return ret;
-
- skbdesc = get_skb_frame_desc(skb);
- txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom);
-
- /*
- * Initialize TX Info descriptor
- */
- rt2x00_desc_read(txwi, 0, &word);
- rt2x00_set_field32(&word, TXWI_W0_FRAG,
- test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
- rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
- rt2x00_set_field32(&word, TXWI_W0_TS,
- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_AMPDU,
- test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
- rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
- rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
- rt2x00_set_field32(&word, TXWI_W0_BW,
- test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
- test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
- rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
- rt2x00_desc_write(txwi, 0, word);
-
- rt2x00_desc_read(txwi, 1, &word);
- rt2x00_set_field32(&word, TXWI_W1_ACK,
- test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W1_NSEQ,
- 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);
- rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
- txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID,
- 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 TXD_W3_WIV is set to 0.
- * When TXD_W3_WIV is set to 1 it will use the IV data
- * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
- * crypto entry in the registers should be used to encrypt the frame.
- */
- _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
- _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
-
- return 0;
+ rt2800_write_txwi(entry->skb, txdesc);
}
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
+ struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+ __le32 *txd = entry_priv->desc;
u32 word;
/*
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W1_BURST,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W1_SD_LEN0,
- rt2x00dev->ops->extra_tx_headroom);
+ rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
- skbdesc->skb_dma + rt2x00dev->ops->extra_tx_headroom);
+ skbdesc->skb_dma + TXWI_DESC_SIZE);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 3, &word);
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
rt2x00_desc_write(txd, 3, word);
+
+ /*
+ * Register descriptor details in skb frame descriptor.
+ */
+ skbdesc->desc = txd;
+ skbdesc->desc_len = TXD_DESC_SIZE;
}
/*
* TX data initialization
*/
-static void rt2800pci_write_beacon(struct queue_entry *entry)
+static void rt2800pci_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
/*
- * Write entire beacon with descriptor to register.
+ * Register descriptor details in skb frame descriptor.
+ */
+ skbdesc->desc = entry->skb->data - TXWI_DESC_SIZE;
+ skbdesc->desc_len = TXWI_DESC_SIZE;
+
+ /*
+ * Add the TXWI for the beacon to the skb.
+ */
+ rt2800_write_txwi(entry->skb, txdesc);
+
+ /*
+ * Dump beacon to userspace through debugfs.
+ */
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
+ /*
+ * Adjust skb to take TXWI into account.
+ */
+ skb_push(entry->skb, TXWI_DESC_SIZE);
+
+ /*
+ * Write entire beacon with TXWI to register.
*/
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
- rt2800_register_multiwrite(rt2x00dev,
- beacon_base,
- skbdesc->desc, skbdesc->desc_len);
- rt2800_register_multiwrite(rt2x00dev,
- beacon_base + skbdesc->desc_len,
- entry->skb->data, entry->skb->len);
+ rt2800_register_multiwrite(rt2x00dev, beacon_base,
+ entry->skb->data, entry->skb->len);
+
+ /*
+ * Enable beaconing again.
+ */
+ rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);
+ rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1);
+ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
/*
* Clean up beacon skb.
{
struct data_queue *queue;
unsigned int idx, qidx = 0;
- u32 reg;
-
- if (queue_idx == QID_BEACON) {
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);
- if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
- rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);
- rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1);
- rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- }
- return;
- }
if (queue_idx > QID_HCCA && queue_idx != QID_MGMT)
return;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
- __le32 *rxwi = (__le32 *)entry->skb->data;
- u32 rxd3;
- u32 rxwi0;
- u32 rxwi1;
- u32 rxwi2;
- u32 rxwi3;
-
- rt2x00_desc_read(rxd, 3, &rxd3);
- rt2x00_desc_read(rxwi, 0, &rxwi0);
- rt2x00_desc_read(rxwi, 1, &rxwi1);
- rt2x00_desc_read(rxwi, 2, &rxwi2);
- rt2x00_desc_read(rxwi, 3, &rxwi3);
-
- if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR))
+ u32 word;
+
+ rt2x00_desc_read(rxd, 3, &word);
+
+ if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
/*
* decryption. This prevents us from correct providing
* correct statistics through debugfs.
*/
- rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
- rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR);
+ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
- if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) {
+ if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
* decryption. Unfortunately the descriptor doesn't contain
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
}
- if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS))
+ if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
- if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD))
+ if (rt2x00_get_field32(word, RXD_W3_L2PAD))
rxdesc->dev_flags |= RXDONE_L2PAD;
- if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
- rxdesc->flags |= RX_FLAG_SHORT_GI;
-
- if (rt2x00_get_field32(rxwi1, RXWI_W1_BW))
- rxdesc->flags |= RX_FLAG_40MHZ;
-
/*
- * Detect RX rate, always use MCS as signal type.
+ * Process the RXWI structure that is at the start of the buffer.
*/
- rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
- rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE);
- rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS);
-
- /*
- * Mask of 0x8 bit to remove the short preamble flag.
- */
- if (rxdesc->rate_mode == RATE_MODE_CCK)
- rxdesc->signal &= ~0x8;
-
- rxdesc->rssi =
- (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
- rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
-
- rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+ rt2800_process_rxwi(entry->skb, rxdesc);
/*
* Set RX IDX in register to inform hardware that we have handled
* this entry and it is available for reuse again.
*/
rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
-
- /*
- * Remove TXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, RXWI_DESC_SIZE);
}
/*
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800pci_write_tx_desc,
- .write_tx_data = rt2800pci_write_tx_data,
+ .write_tx_data = rt2x00pci_write_tx_data,
+ .write_tx_datadesc = rt2800pci_write_tx_datadesc,
.write_beacon = rt2800pci_write_beacon,
.kick_tx_queue = rt2800pci_kick_tx_queue,
.kill_tx_queue = rt2800pci_kill_tx_queue,