|
@@ -541,6 +541,14 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t addr)
|
|
|
+{
|
|
|
+ desc->addr = (u32)addr;
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ desc->addrh = (u32)(addr >> 32);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
static void macb_tx_error_task(struct work_struct *work)
|
|
|
{
|
|
|
struct macb_queue *queue = container_of(work, struct macb_queue,
|
|
@@ -621,14 +629,17 @@ static void macb_tx_error_task(struct work_struct *work)
|
|
|
|
|
|
/* Set end of TX queue */
|
|
|
desc = macb_tx_desc(queue, 0);
|
|
|
- desc->addr = 0;
|
|
|
+ macb_set_addr(desc, 0);
|
|
|
desc->ctrl = MACB_BIT(TX_USED);
|
|
|
|
|
|
/* Make descriptor updates visible to hardware */
|
|
|
wmb();
|
|
|
|
|
|
/* Reinitialize the TX desc queue */
|
|
|
- queue_writel(queue, TBQP, queue->tx_ring_dma);
|
|
|
+ queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
|
|
|
+#endif
|
|
|
/* Make TX ring reflect state of hardware */
|
|
|
queue->tx_head = 0;
|
|
|
queue->tx_tail = 0;
|
|
@@ -750,7 +761,7 @@ static void gem_rx_refill(struct macb *bp)
|
|
|
|
|
|
if (entry == RX_RING_SIZE - 1)
|
|
|
paddr |= MACB_BIT(RX_WRAP);
|
|
|
- bp->rx_ring[entry].addr = paddr;
|
|
|
+ macb_set_addr(&(bp->rx_ring[entry]), paddr);
|
|
|
bp->rx_ring[entry].ctrl = 0;
|
|
|
|
|
|
/* properly align Ethernet header */
|
|
@@ -798,7 +809,9 @@ static int gem_rx(struct macb *bp, int budget)
|
|
|
int count = 0;
|
|
|
|
|
|
while (count < budget) {
|
|
|
- u32 addr, ctrl;
|
|
|
+ u32 ctrl;
|
|
|
+ dma_addr_t addr;
|
|
|
+ bool rxused;
|
|
|
|
|
|
entry = macb_rx_ring_wrap(bp->rx_tail);
|
|
|
desc = &bp->rx_ring[entry];
|
|
@@ -806,10 +819,14 @@ static int gem_rx(struct macb *bp, int budget)
|
|
|
/* Make hw descriptor updates visible to CPU */
|
|
|
rmb();
|
|
|
|
|
|
- addr = desc->addr;
|
|
|
+ rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
|
|
|
+ addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ addr |= ((u64)(desc->addrh) << 32);
|
|
|
+#endif
|
|
|
ctrl = desc->ctrl;
|
|
|
|
|
|
- if (!(addr & MACB_BIT(RX_USED)))
|
|
|
+ if (!rxused)
|
|
|
break;
|
|
|
|
|
|
bp->rx_tail++;
|
|
@@ -835,7 +852,6 @@ static int gem_rx(struct macb *bp, int budget)
|
|
|
netdev_vdbg(bp->dev, "gem_rx %u (len %u)\n", entry, len);
|
|
|
|
|
|
skb_put(skb, len);
|
|
|
- addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, addr));
|
|
|
dma_unmap_single(&bp->pdev->dev, addr,
|
|
|
bp->rx_buffer_size, DMA_FROM_DEVICE);
|
|
|
|
|
@@ -1299,7 +1315,7 @@ static unsigned int macb_tx_map(struct macb *bp,
|
|
|
ctrl |= MACB_BIT(TX_WRAP);
|
|
|
|
|
|
/* Set TX buffer descriptor */
|
|
|
- desc->addr = tx_skb->mapping;
|
|
|
+ macb_set_addr(desc, tx_skb->mapping);
|
|
|
/* desc->addr must be visible to hardware before clearing
|
|
|
* 'TX_USED' bit in desc->ctrl.
|
|
|
*/
|
|
@@ -1422,6 +1438,9 @@ static void gem_free_rx_buffers(struct macb *bp)
|
|
|
|
|
|
desc = &bp->rx_ring[i];
|
|
|
addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ addr |= ((u64)(desc->addrh) << 32);
|
|
|
+#endif
|
|
|
dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
|
|
|
DMA_FROM_DEVICE);
|
|
|
dev_kfree_skb_any(skb);
|
|
@@ -1547,7 +1566,7 @@ static void gem_init_rings(struct macb *bp)
|
|
|
|
|
|
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
|
|
for (i = 0; i < TX_RING_SIZE; i++) {
|
|
|
- queue->tx_ring[i].addr = 0;
|
|
|
+ macb_set_addr(&(queue->tx_ring[i]), 0);
|
|
|
queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
|
|
|
}
|
|
|
queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
|
|
@@ -1694,6 +1713,10 @@ static void macb_configure_dma(struct macb *bp)
|
|
|
dmacfg |= GEM_BIT(TXCOEN);
|
|
|
else
|
|
|
dmacfg &= ~GEM_BIT(TXCOEN);
|
|
|
+
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ dmacfg |= GEM_BIT(ADDR64);
|
|
|
+#endif
|
|
|
netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
|
|
|
dmacfg);
|
|
|
gem_writel(bp, DMACFG, dmacfg);
|
|
@@ -1739,9 +1762,15 @@ static void macb_init_hw(struct macb *bp)
|
|
|
macb_configure_dma(bp);
|
|
|
|
|
|
/* Initialize TX and RX buffers */
|
|
|
- macb_writel(bp, RBQP, bp->rx_ring_dma);
|
|
|
+ macb_writel(bp, RBQP, (u32)(bp->rx_ring_dma));
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
|
|
|
+#endif
|
|
|
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
|
|
- queue_writel(queue, TBQP, queue->tx_ring_dma);
|
|
|
+ queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
|
|
|
+#endif
|
|
|
|
|
|
/* Enable interrupts */
|
|
|
queue_writel(queue, IER,
|
|
@@ -2379,6 +2408,9 @@ static int macb_init(struct platform_device *pdev)
|
|
|
queue->IDR = GEM_IDR(hw_q - 1);
|
|
|
queue->IMR = GEM_IMR(hw_q - 1);
|
|
|
queue->TBQP = GEM_TBQP(hw_q - 1);
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ queue->TBQPH = GEM_TBQPH(hw_q -1);
|
|
|
+#endif
|
|
|
} else {
|
|
|
/* queue0 uses legacy registers */
|
|
|
queue->ISR = MACB_ISR;
|
|
@@ -2386,6 +2418,9 @@ static int macb_init(struct platform_device *pdev)
|
|
|
queue->IDR = MACB_IDR;
|
|
|
queue->IMR = MACB_IMR;
|
|
|
queue->TBQP = MACB_TBQP;
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ queue->TBQPH = MACB_TBQPH;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
/* get irq: here we use the linux queue index, not the hardware
|
|
@@ -2935,6 +2970,11 @@ static int macb_probe(struct platform_device *pdev)
|
|
|
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
|
|
|
device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
|
|
|
|
|
|
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
|
+ if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
|
|
|
+ dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
|
|
|
+#endif
|
|
|
+
|
|
|
spin_lock_init(&bp->lock);
|
|
|
|
|
|
/* setup capabilities */
|