Commit 30b3a23c authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville

rt2x00: Fix Descriptor DMA initialization

As Adam Baker reported the DMA address for the
descriptor base was incorrectly initialized in
the PCI drivers.

Instead of the DMA base for the descriptor, the
DMA base for the data was passed resulting in a
broken TX/RX state for PCI drivers.
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e542239f
...@@ -597,11 +597,12 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, ...@@ -597,11 +597,12 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
u32 word; u32 word;
rt2x00_desc_read(priv_rx->desc, 2, &word); rt2x00_desc_read(priv_rx->desc, 2, &word);
rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->queue->data_size); rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
entry->queue->data_size);
rt2x00_desc_write(priv_rx->desc, 2, word); rt2x00_desc_write(priv_rx->desc, 2, word);
rt2x00_desc_read(priv_rx->desc, 1, &word); rt2x00_desc_read(priv_rx->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
rt2x00_desc_write(priv_rx->desc, 1, word); rt2x00_desc_write(priv_rx->desc, 1, word);
rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_desc_read(priv_rx->desc, 0, &word);
...@@ -616,7 +617,7 @@ static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, ...@@ -616,7 +617,7 @@ static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
u32 word; u32 word;
rt2x00_desc_read(priv_tx->desc, 1, &word); rt2x00_desc_read(priv_tx->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
rt2x00_desc_write(priv_tx->desc, 1, word); rt2x00_desc_write(priv_tx->desc, 1, word);
rt2x00_desc_read(priv_tx->desc, 2, &word); rt2x00_desc_read(priv_tx->desc, 2, &word);
...@@ -648,22 +649,26 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -648,22 +649,26 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_tx = rt2x00dev->tx[1].entries[0].priv_data; priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
priv_tx = rt2x00dev->tx[0].entries[0].priv_data; priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
...@@ -673,7 +678,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -673,7 +678,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_rx = rt2x00dev->rx->entries[0].priv_data; priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg); rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
return 0; return 0;
......
...@@ -691,7 +691,7 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, ...@@ -691,7 +691,7 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
u32 word; u32 word;
rt2x00_desc_read(priv_rx->desc, 1, &word); rt2x00_desc_read(priv_rx->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
rt2x00_desc_write(priv_rx->desc, 1, word); rt2x00_desc_write(priv_rx->desc, 1, word);
rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_desc_read(priv_rx->desc, 0, &word);
...@@ -706,7 +706,7 @@ static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, ...@@ -706,7 +706,7 @@ static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
u32 word; u32 word;
rt2x00_desc_read(priv_tx->desc, 1, &word); rt2x00_desc_read(priv_tx->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
rt2x00_desc_write(priv_tx->desc, 1, word); rt2x00_desc_write(priv_tx->desc, 1, word);
rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_desc_read(priv_tx->desc, 0, &word);
...@@ -733,22 +733,26 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -733,22 +733,26 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_tx = rt2x00dev->tx[1].entries[0].priv_data; priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
priv_tx = rt2x00dev->tx[0].entries[0].priv_data; priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg); rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
...@@ -758,7 +762,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -758,7 +762,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_rx = rt2x00dev->rx->entries[0].priv_data; priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg); rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
return 0; return 0;
......
...@@ -218,40 +218,44 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, ...@@ -218,40 +218,44 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
struct queue_entry_priv_pci_rx *priv_rx; struct queue_entry_priv_pci_rx *priv_rx;
struct queue_entry_priv_pci_tx *priv_tx; struct queue_entry_priv_pci_tx *priv_tx;
void *desc; void *addr;
dma_addr_t dma;
void *desc_addr;
dma_addr_t desc_dma;
void *data_addr; void *data_addr;
void *data;
dma_addr_t data_dma; dma_addr_t data_dma;
dma_addr_t dma;
unsigned int i; unsigned int i;
/* /*
* Allocate DMA memory for descriptor and buffer. * Allocate DMA memory for descriptor and buffer.
*/ */
data_addr = pci_alloc_consistent(pci_dev, dma_size(queue), &data_dma); addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma);
if (!data_addr) if (!addr)
return -ENOMEM; return -ENOMEM;
memset(data_addr, 0, dma_size(queue)); memset(addr, 0, dma_size(queue));
/* /*
* Initialize all queue entries to contain valid addresses. * Initialize all queue entries to contain valid addresses.
*/ */
for (i = 0; i < queue->limit; i++) { for (i = 0; i < queue->limit; i++) {
desc = desc_offset(queue, data_addr, i); desc_addr = desc_offset(queue, addr, i);
data = data_offset(queue, data_addr, i); desc_dma = desc_offset(queue, dma, i);
dma = data_offset(queue, data_dma, i); data_addr = data_offset(queue, addr, i);
data_dma = data_offset(queue, dma, i);
if (queue->qid == QID_RX) { if (queue->qid == QID_RX) {
priv_rx = queue->entries[i].priv_data; priv_rx = queue->entries[i].priv_data;
priv_rx->desc = desc; priv_rx->desc = desc_addr;
priv_rx->data = data; priv_rx->desc_dma = desc_dma;
priv_rx->dma = dma; priv_rx->data = data_addr;
priv_rx->data_dma = data_dma;
} else { } else {
priv_tx = queue->entries[i].priv_data; priv_tx = queue->entries[i].priv_data;
priv_tx->desc = desc; priv_tx->desc = desc_addr;
priv_tx->data = data; priv_tx->desc_dma = desc_dma;
priv_tx->dma = dma; priv_tx->data = data_addr;
priv_tx->data_dma = data_dma;
} }
} }
...@@ -270,13 +274,13 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, ...@@ -270,13 +274,13 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
if (queue->qid == QID_RX) { if (queue->qid == QID_RX) {
priv_rx = queue->entries[0].priv_data; priv_rx = queue->entries[0].priv_data;
data_addr = priv_rx->data; data_addr = priv_rx->data;
data_dma = priv_rx->dma; data_dma = priv_rx->data_dma;
priv_rx->data = NULL; priv_rx->data = NULL;
} else { } else {
priv_tx = queue->entries[0].priv_data; priv_tx = queue->entries[0].priv_data;
data_addr = priv_tx->data; data_addr = priv_tx->data;
data_dma = priv_tx->dma; data_dma = priv_tx->data_dma;
priv_tx->data = NULL; priv_tx->data = NULL;
} }
......
...@@ -103,9 +103,10 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, ...@@ -103,9 +103,10 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
*/ */
struct queue_entry_priv_pci_rx { struct queue_entry_priv_pci_rx {
__le32 *desc; __le32 *desc;
dma_addr_t desc_dma;
void *data; void *data;
dma_addr_t dma; dma_addr_t data_dma;
}; };
/** /**
...@@ -118,9 +119,10 @@ struct queue_entry_priv_pci_rx { ...@@ -118,9 +119,10 @@ struct queue_entry_priv_pci_rx {
*/ */
struct queue_entry_priv_pci_tx { struct queue_entry_priv_pci_tx {
__le32 *desc; __le32 *desc;
dma_addr_t desc_dma;
void *data; void *data;
dma_addr_t dma; dma_addr_t data_dma;
struct ieee80211_tx_control control; struct ieee80211_tx_control control;
}; };
......
...@@ -975,7 +975,8 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, ...@@ -975,7 +975,8 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
u32 word; u32 word;
rt2x00_desc_read(priv_rx->desc, 5, &word); rt2x00_desc_read(priv_rx->desc, 5, &word);
rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, priv_rx->dma); rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
priv_rx->data_dma);
rt2x00_desc_write(priv_rx->desc, 5, word); rt2x00_desc_write(priv_rx->desc, 5, word);
rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_desc_read(priv_rx->desc, 0, &word);
...@@ -999,7 +1000,8 @@ static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, ...@@ -999,7 +1000,8 @@ static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(priv_tx->desc, 5, word); rt2x00_desc_write(priv_tx->desc, 5, word);
rt2x00_desc_read(priv_tx->desc, 6, &word); rt2x00_desc_read(priv_tx->desc, 6, &word);
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, priv_tx->dma); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
priv_tx->data_dma);
rt2x00_desc_write(priv_tx->desc, 6, word); rt2x00_desc_write(priv_tx->desc, 6, word);
rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_desc_read(priv_tx->desc, 0, &word);
...@@ -1035,22 +1037,26 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -1035,22 +1037,26 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_tx = rt2x00dev->tx[0].entries[0].priv_data; priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg); rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
priv_tx = rt2x00dev->tx[1].entries[0].priv_data; priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg); rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
priv_tx = rt2x00dev->tx[2].entries[0].priv_data; priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg); rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
priv_tx = rt2x00dev->tx[3].entries[0].priv_data; priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg); rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg); rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
...@@ -1062,7 +1068,8 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) ...@@ -1062,7 +1068,8 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
priv_rx = rt2x00dev->rx->entries[0].priv_data; priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg); rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER, priv_rx->dma); rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
priv_rx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg); rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment