aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/gianfar.c
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2008-12-16 18:33:40 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 18:33:40 -0500
commit31de198b4d2732028f4c5bff04b0103b1d8c1d8c (patch)
tree63b971edc7f662d402769cfaf3c50465f3aab48d /drivers/net/gianfar.c
parenta22823e72a4821ce1d4a248fbd8f5a81795af339 (diff)
gianfar: Add macros for stepping through BDs
This code is based strongly on code from Dai Haruki <Dai.Haruki@freescale.com>. The gianfar Buffer Descriptors are arranged in a circular array, the end of which is denoted by setting the "WRAP" bit in the descriptor. However, the software knows the end of the ring because it knows how many descriptors are there. Rather than check each descriptor for whether the WRAP bit is set, use pointer math to determine where the next BD is. This is also useful for when we want to look at BDs other than the very next one (for Scatter-Gather). Signed-off-by: Andy Fleming <afleming@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r--drivers/net/gianfar.c27
1 files changed, 9 insertions, 18 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 40756dc68a10..e7e8201283a3 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1215,7 +1215,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1215{ 1215{
1216 struct gfar_private *priv = netdev_priv(dev); 1216 struct gfar_private *priv = netdev_priv(dev);
1217 struct txfcb *fcb = NULL; 1217 struct txfcb *fcb = NULL;
1218 struct txbd8 *txbdp; 1218 struct txbd8 *txbdp, *base;
1219 u16 status; 1219 u16 status;
1220 unsigned long flags; 1220 unsigned long flags;
1221 1221
@@ -1227,6 +1227,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1227 1227
1228 /* Point at the first free tx descriptor */ 1228 /* Point at the first free tx descriptor */
1229 txbdp = priv->cur_tx; 1229 txbdp = priv->cur_tx;
1230 base = priv->tx_bd_base;
1230 1231
1231 /* Clear all but the WRAP status flags */ 1232 /* Clear all but the WRAP status flags */
1232 status = txbdp->status & TXBD_WRAP; 1233 status = txbdp->status & TXBD_WRAP;
@@ -1279,12 +1280,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1279 eieio(); 1280 eieio();
1280 txbdp->status = status; 1281 txbdp->status = status;
1281 1282
1282 /* If this was the last BD in the ring, the next one */ 1283 txbdp = next_bd(txbdp, base, priv->tx_ring_size);
1283 /* is at the beginning of the ring */
1284 if (txbdp->status & TXBD_WRAP)
1285 txbdp = priv->tx_bd_base;
1286 else
1287 txbdp++;
1288 1284
1289 /* If the next BD still needs to be cleaned up, then the bds 1285 /* If the next BD still needs to be cleaned up, then the bds
1290 are full. We need to tell the kernel to stop sending us stuff. */ 1286 are full. We need to tell the kernel to stop sending us stuff. */
@@ -1470,11 +1466,12 @@ static void gfar_timeout(struct net_device *dev)
1470/* Interrupt Handler for Transmit complete */ 1466/* Interrupt Handler for Transmit complete */
1471static int gfar_clean_tx_ring(struct net_device *dev) 1467static int gfar_clean_tx_ring(struct net_device *dev)
1472{ 1468{
1473 struct txbd8 *bdp; 1469 struct txbd8 *bdp, *base;
1474 struct gfar_private *priv = netdev_priv(dev); 1470 struct gfar_private *priv = netdev_priv(dev);
1475 int howmany = 0; 1471 int howmany = 0;
1476 1472
1477 bdp = priv->dirty_tx; 1473 bdp = priv->dirty_tx;
1474 base = priv->tx_bd_base;
1478 while ((bdp->status & TXBD_READY) == 0) { 1475 while ((bdp->status & TXBD_READY) == 0) {
1479 /* If dirty_tx and cur_tx are the same, then either the */ 1476 /* If dirty_tx and cur_tx are the same, then either the */
1480 /* ring is empty or full now (it could only be full in the beginning, */ 1477 /* ring is empty or full now (it could only be full in the beginning, */
@@ -1504,11 +1501,7 @@ static int gfar_clean_tx_ring(struct net_device *dev)
1504 /* Clean BD length for empty detection */ 1501 /* Clean BD length for empty detection */
1505 bdp->length = 0; 1502 bdp->length = 0;
1506 1503
1507 /* update bdp to point at next bd in the ring (wrapping if necessary) */ 1504 bdp = next_bd(bdp, base, priv->tx_ring_size);
1508 if (bdp->status & TXBD_WRAP)
1509 bdp = priv->tx_bd_base;
1510 else
1511 bdp++;
1512 1505
1513 /* Move dirty_tx to be the next bd */ 1506 /* Move dirty_tx to be the next bd */
1514 priv->dirty_tx = bdp; 1507 priv->dirty_tx = bdp;
@@ -1712,7 +1705,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
1712 */ 1705 */
1713int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) 1706int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
1714{ 1707{
1715 struct rxbd8 *bdp; 1708 struct rxbd8 *bdp, *base;
1716 struct sk_buff *skb; 1709 struct sk_buff *skb;
1717 int pkt_len; 1710 int pkt_len;
1718 int amount_pull; 1711 int amount_pull;
@@ -1721,6 +1714,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
1721 1714
1722 /* Get the first full descriptor */ 1715 /* Get the first full descriptor */
1723 bdp = priv->cur_rx; 1716 bdp = priv->cur_rx;
1717 base = priv->rx_bd_base;
1724 1718
1725 amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0) + 1719 amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0) +
1726 priv->padding; 1720 priv->padding;
@@ -1776,10 +1770,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
1776 gfar_new_rxbdp(dev, bdp, newskb); 1770 gfar_new_rxbdp(dev, bdp, newskb);
1777 1771
1778 /* Update to the next pointer */ 1772 /* Update to the next pointer */
1779 if (bdp->status & RXBD_WRAP) 1773 bdp = next_bd(bdp, base, priv->rx_ring_size);
1780 bdp = priv->rx_bd_base;
1781 else
1782 bdp++;
1783 1774
1784 /* update to point at the next skb */ 1775 /* update to point at the next skb */
1785 priv->skb_currx = 1776 priv->skb_currx =