aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDai Haruki <dai.haruki@freescale.com>2008-04-09 20:37:51 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-16 20:06:50 -0400
commitd080cd6301e107e79c6a0fc654319f8979f70549 (patch)
tree263b443368033c49c8b4345288677ac58cb68533 /drivers/net
parent0b50d753874ad4843d305bf841ba5e28fc0f0ce7 (diff)
gianfar: Support NAPI for TX Frames
Poll the completed TX frames in gfar_poll(). This prevents the tx completion interrupt from interfering with processing of received frames. We also disable hardware rx coalescing when NAPI is enabled. Signed-off-by: Dai Haruki <dai.haruki@freescale.com> Signed-off-by: Andy Fleming <afleming@freescale.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/gianfar.c56
-rw-r--r--drivers/net/gianfar.h13
2 files changed, 53 insertions, 16 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 601f93e482c6..c8c3df737d73 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1250,17 +1250,12 @@ static void gfar_timeout(struct net_device *dev)
1250} 1250}
1251 1251
1252/* Interrupt Handler for Transmit complete */ 1252/* Interrupt Handler for Transmit complete */
1253static irqreturn_t gfar_transmit(int irq, void *dev_id) 1253int gfar_clean_tx_ring(struct net_device *dev)
1254{ 1254{
1255 struct net_device *dev = (struct net_device *) dev_id;
1256 struct gfar_private *priv = netdev_priv(dev);
1257 struct txbd8 *bdp; 1255 struct txbd8 *bdp;
1256 struct gfar_private *priv = netdev_priv(dev);
1257 int howmany = 0;
1258 1258
1259 /* Clear IEVENT */
1260 gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
1261
1262 /* Lock priv */
1263 spin_lock(&priv->txlock);
1264 bdp = priv->dirty_tx; 1259 bdp = priv->dirty_tx;
1265 while ((bdp->status & TXBD_READY) == 0) { 1260 while ((bdp->status & TXBD_READY) == 0) {
1266 /* If dirty_tx and cur_tx are the same, then either the */ 1261 /* If dirty_tx and cur_tx are the same, then either the */
@@ -1269,7 +1264,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
1269 if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0)) 1264 if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
1270 break; 1265 break;
1271 1266
1272 dev->stats.tx_packets++; 1267 howmany++;
1273 1268
1274 /* Deferred means some collisions occurred during transmit, */ 1269 /* Deferred means some collisions occurred during transmit, */
1275 /* but we eventually sent the packet. */ 1270 /* but we eventually sent the packet. */
@@ -1278,11 +1273,15 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
1278 1273
1279 /* Free the sk buffer associated with this TxBD */ 1274 /* Free the sk buffer associated with this TxBD */
1280 dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); 1275 dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
1276
1281 priv->tx_skbuff[priv->skb_dirtytx] = NULL; 1277 priv->tx_skbuff[priv->skb_dirtytx] = NULL;
1282 priv->skb_dirtytx = 1278 priv->skb_dirtytx =
1283 (priv->skb_dirtytx + 1279 (priv->skb_dirtytx +
1284 1) & TX_RING_MOD_MASK(priv->tx_ring_size); 1280 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
1285 1281
1282 /* Clean BD length for empty detection */
1283 bdp->length = 0;
1284
1286 /* update bdp to point at next bd in the ring (wrapping if necessary) */ 1285 /* update bdp to point at next bd in the ring (wrapping if necessary) */
1287 if (bdp->status & TXBD_WRAP) 1286 if (bdp->status & TXBD_WRAP)
1288 bdp = priv->tx_bd_base; 1287 bdp = priv->tx_bd_base;
@@ -1297,6 +1296,25 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
1297 netif_wake_queue(dev); 1296 netif_wake_queue(dev);
1298 } /* while ((bdp->status & TXBD_READY) == 0) */ 1297 } /* while ((bdp->status & TXBD_READY) == 0) */
1299 1298
1299 dev->stats.tx_packets += howmany;
1300
1301 return howmany;
1302}
1303
1304/* Interrupt Handler for Transmit complete */
1305static irqreturn_t gfar_transmit(int irq, void *dev_id)
1306{
1307 struct net_device *dev = (struct net_device *) dev_id;
1308 struct gfar_private *priv = netdev_priv(dev);
1309
1310 /* Clear IEVENT */
1311 gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
1312
1313 /* Lock priv */
1314 spin_lock(&priv->txlock);
1315
1316 gfar_clean_tx_ring(dev);
1317
1300 /* If we are coalescing the interrupts, reset the timer */ 1318 /* If we are coalescing the interrupts, reset the timer */
1301 /* Otherwise, clear it */ 1319 /* Otherwise, clear it */
1302 if (likely(priv->txcoalescing)) { 1320 if (likely(priv->txcoalescing)) {
@@ -1392,15 +1410,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
1392 unsigned long flags; 1410 unsigned long flags;
1393#endif 1411#endif
1394 1412
1395 /* Clear IEVENT, so rx interrupt isn't called again
1396 * because of this interrupt */
1397 gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
1398
1399 /* support NAPI */ 1413 /* support NAPI */
1400#ifdef CONFIG_GFAR_NAPI 1414#ifdef CONFIG_GFAR_NAPI
1415 /* Clear IEVENT, so interrupts aren't called again
1416 * because of the packets that have already arrived */
1417 gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
1418
1401 if (netif_rx_schedule_prep(dev, &priv->napi)) { 1419 if (netif_rx_schedule_prep(dev, &priv->napi)) {
1402 tempval = gfar_read(&priv->regs->imask); 1420 tempval = gfar_read(&priv->regs->imask);
1403 tempval &= IMASK_RX_DISABLED; 1421 tempval &= IMASK_RTX_DISABLED;
1404 gfar_write(&priv->regs->imask, tempval); 1422 gfar_write(&priv->regs->imask, tempval);
1405 1423
1406 __netif_rx_schedule(dev, &priv->napi); 1424 __netif_rx_schedule(dev, &priv->napi);
@@ -1411,6 +1429,9 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
1411 gfar_read(&priv->regs->imask)); 1429 gfar_read(&priv->regs->imask));
1412 } 1430 }
1413#else 1431#else
1432 /* Clear IEVENT, so rx interrupt isn't called again
1433 * because of this interrupt */
1434 gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
1414 1435
1415 spin_lock_irqsave(&priv->rxlock, flags); 1436 spin_lock_irqsave(&priv->rxlock, flags);
1416 gfar_clean_rx_ring(dev, priv->rx_ring_size); 1437 gfar_clean_rx_ring(dev, priv->rx_ring_size);
@@ -1580,6 +1601,13 @@ static int gfar_poll(struct napi_struct *napi, int budget)
1580 struct gfar_private *priv = container_of(napi, struct gfar_private, napi); 1601 struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
1581 struct net_device *dev = priv->dev; 1602 struct net_device *dev = priv->dev;
1582 int howmany; 1603 int howmany;
1604 unsigned long flags;
1605
1606 /* If we fail to get the lock, don't bother with the TX BDs */
1607 if (spin_trylock_irqsave(&priv->txlock, flags)) {
1608 gfar_clean_tx_ring(dev);
1609 spin_unlock_irqrestore(&priv->txlock, flags);
1610 }
1583 1611
1584 howmany = gfar_clean_rx_ring(dev, budget); 1612 howmany = gfar_clean_rx_ring(dev, budget);
1585 1613
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index ea8671f87bce..0d0883609469 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -126,9 +126,16 @@ extern const char gfar_driver_version[];
126#define DEFAULT_TXCOUNT 16 126#define DEFAULT_TXCOUNT 16
127#define DEFAULT_TXTIME 21 127#define DEFAULT_TXTIME 21
128 128
129#define DEFAULT_RXTIME 21
130
131/* Non NAPI Case */
132#ifndef CONFIG_GFAR_NAPI
129#define DEFAULT_RX_COALESCE 1 133#define DEFAULT_RX_COALESCE 1
130#define DEFAULT_RXCOUNT 16 134#define DEFAULT_RXCOUNT 16
131#define DEFAULT_RXTIME 21 135#else
136#define DEFAULT_RX_COALESCE 0
137#define DEFAULT_RXCOUNT 0
138#endif /* CONFIG_GFAR_NAPI */
132 139
133#define TBIPA_VALUE 0x1f 140#define TBIPA_VALUE 0x1f
134#define MIIMCFG_INIT_VALUE 0x00000007 141#define MIIMCFG_INIT_VALUE 0x00000007
@@ -242,6 +249,7 @@ extern const char gfar_driver_version[];
242#define IEVENT_PERR 0x00000001 249#define IEVENT_PERR 0x00000001
243#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) 250#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
244#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) 251#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
252#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK)
245#define IEVENT_ERR_MASK \ 253#define IEVENT_ERR_MASK \
246(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ 254(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
247 IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ 255 IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
@@ -269,11 +277,12 @@ extern const char gfar_driver_version[];
269#define IMASK_FIQ 0x00000004 277#define IMASK_FIQ 0x00000004
270#define IMASK_DPE 0x00000002 278#define IMASK_DPE 0x00000002
271#define IMASK_PERR 0x00000001 279#define IMASK_PERR 0x00000001
272#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
273#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ 280#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
274 IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ 281 IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
275 IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ 282 IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
276 | IMASK_PERR) 283 | IMASK_PERR)
284#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
285 & IMASK_DEFAULT)
277 286
278/* Fifo management */ 287/* Fifo management */
279#define FIFO_TX_THR_MASK 0x01ff 288#define FIFO_TX_THR_MASK 0x01ff