#define TX_BW_MTU(p) (0x0458 + ((p) << 10))
#define TX_BW_BURST(p) (0x045c + ((p) << 10))
#define INT_CAUSE(p) (0x0460 + ((p) << 10))
+#define INT_TX_END 0x07f80000
#define INT_RX 0x0007fbfc
#define INT_EXT 0x00000002
#define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10))
netif_rx_complete(mp->dev, napi);
wrl(mp, INT_CAUSE(mp->port_num), 0);
wrl(mp, INT_CAUSE_EXT(mp->port_num), 0);
- wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_EXT);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
}
return rx;
struct mv643xx_eth_private *mp = netdev_priv(dev);
u32 int_cause;
u32 int_cause_ext;
+ u32 txq_active;
- int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & (INT_RX | INT_EXT);
+ int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
+ (INT_TX_END | INT_RX | INT_EXT);
if (int_cause == 0)
return IRQ_NONE;
}
#endif
+ txq_active = rdl(mp, TXQ_COMMAND(mp->port_num));
+
/*
* TxBuffer or TxError set for any of the 8 queues?
*/
for (i = 0; i < 8; i++)
if (mp->txq_mask & (1 << i))
txq_reclaim(mp->txq + i, 0);
+ }
- __txq_maybe_wake(mp->txq + mp->txq_primary);
+ /*
+ * Any TxEnd interrupts?
+ */
+ if (int_cause & INT_TX_END) {
+ int i;
+
+ wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END));
+ for (i = 0; i < 8; i++) {
+ struct tx_queue *txq = mp->txq + i;
+ if (txq->tx_desc_count && !((txq_active >> i) & 1))
+ txq_enable(txq);
+ }
+ }
+
+ /*
+ * Enough space again in the primary TX queue for a full packet?
+ */
+ if (int_cause_ext & INT_EXT_TX) {
+ struct tx_queue *txq = mp->txq + mp->txq_primary;
+ __txq_maybe_wake(txq);
}
return IRQ_HANDLED;
wrl(mp, INT_MASK_EXT(mp->port_num),
INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX);
- wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_EXT);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
return 0;
mv643xx_eth_irq(dev->irq, dev);
- wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_CAUSE_EXT);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_CAUSE_EXT);
}
#endif