aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/gianfar.c
diff options
context:
space:
mode:
authorDai Haruki <dai.haruki@freescale.com>2008-12-16 18:34:50 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 18:34:50 -0500
commit5a5efed4817ef931f648b118aeb9222e53122d2b (patch)
tree592f3dbe3bf47035e8738b1c4bbe48fc3be973fc /drivers/net/gianfar.c
parent31de198b4d2732028f4c5bff04b0103b1d8c1d8c (diff)
gianfar: Make all BD status writes 32-bit
Whenever we want to update the status field in a BD, we usually want to update the length field, too. By combining them into one 32-bit field, we reduce the number of stores to memory shared with the controller, and we eliminate the need for order-enforcement, as the length and "READY" bit are now updated atomically at the same time. Signed-off-by: Dai Haruki <Dai.Haruki@freescale.com> 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.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index e7e8201283a3..3e611a69df13 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -854,8 +854,7 @@ static void free_skb_resources(struct gfar_private *priv)
854 priv->rx_skbuff[i] = NULL; 854 priv->rx_skbuff[i] = NULL;
855 } 855 }
856 856
857 rxbdp->status = 0; 857 rxbdp->lstatus = 0;
858 rxbdp->length = 0;
859 rxbdp->bufPtr = 0; 858 rxbdp->bufPtr = 0;
860 859
861 rxbdp++; 860 rxbdp++;
@@ -976,8 +975,7 @@ int startup_gfar(struct net_device *dev)
976 /* Initialize Transmit Descriptor Ring */ 975 /* Initialize Transmit Descriptor Ring */
977 txbdp = priv->tx_bd_base; 976 txbdp = priv->tx_bd_base;
978 for (i = 0; i < priv->tx_ring_size; i++) { 977 for (i = 0; i < priv->tx_ring_size; i++) {
979 txbdp->status = 0; 978 txbdp->lstatus = 0;
980 txbdp->length = 0;
981 txbdp->bufPtr = 0; 979 txbdp->bufPtr = 0;
982 txbdp++; 980 txbdp++;
983 } 981 }
@@ -1216,7 +1214,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1216 struct gfar_private *priv = netdev_priv(dev); 1214 struct gfar_private *priv = netdev_priv(dev);
1217 struct txfcb *fcb = NULL; 1215 struct txfcb *fcb = NULL;
1218 struct txbd8 *txbdp, *base; 1216 struct txbd8 *txbdp, *base;
1219 u16 status; 1217 u32 lstatus;
1220 unsigned long flags; 1218 unsigned long flags;
1221 1219
1222 /* Update transmit stats */ 1220 /* Update transmit stats */
@@ -1230,26 +1228,25 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1230 base = priv->tx_bd_base; 1228 base = priv->tx_bd_base;
1231 1229
1232 /* Clear all but the WRAP status flags */ 1230 /* Clear all but the WRAP status flags */
1233 status = txbdp->status & TXBD_WRAP; 1231 lstatus = txbdp->lstatus & BD_LFLAG(TXBD_WRAP);
1234 1232
1235 /* Set up checksumming */ 1233 /* Set up checksumming */
1236 if (CHECKSUM_PARTIAL == skb->ip_summed) { 1234 if (CHECKSUM_PARTIAL == skb->ip_summed) {
1237 fcb = gfar_add_fcb(skb); 1235 fcb = gfar_add_fcb(skb);
1238 status |= TXBD_TOE; 1236 lstatus |= BD_LFLAG(TXBD_TOE);
1239 gfar_tx_checksum(skb, fcb); 1237 gfar_tx_checksum(skb, fcb);
1240 } 1238 }
1241 1239
1242 if (priv->vlgrp && vlan_tx_tag_present(skb)) { 1240 if (priv->vlgrp && vlan_tx_tag_present(skb)) {
1243 if (unlikely(NULL == fcb)) { 1241 if (unlikely(NULL == fcb)) {
1244 fcb = gfar_add_fcb(skb); 1242 fcb = gfar_add_fcb(skb);
1245 status |= TXBD_TOE; 1243 lstatus |= BD_LFLAG(TXBD_TOE);
1246 } 1244 }
1247 1245
1248 gfar_tx_vlan(skb, fcb); 1246 gfar_tx_vlan(skb, fcb);
1249 } 1247 }
1250 1248
1251 /* Set buffer length and pointer */ 1249 /* Set buffer length and pointer */
1252 txbdp->length = skb->len;
1253 txbdp->bufPtr = dma_map_single(&dev->dev, skb->data, 1250 txbdp->bufPtr = dma_map_single(&dev->dev, skb->data,
1254 skb->len, DMA_TO_DEVICE); 1251 skb->len, DMA_TO_DEVICE);
1255 1252
@@ -1260,12 +1257,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1260 priv->skb_curtx = 1257 priv->skb_curtx =
1261 (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size); 1258 (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
1262 1259
1263 /* Flag the BD as interrupt-causing */ 1260 /* Flag the BD as ready, interrupt-causing, last, and in need of CRC */
1264 status |= TXBD_INTERRUPT; 1261 lstatus |=
1265 1262 BD_LFLAG(TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT) |
1266 /* Flag the BD as ready to go, last in frame, and */ 1263 skb->len;
1267 /* in need of CRC */
1268 status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
1269 1264
1270 dev->trans_start = jiffies; 1265 dev->trans_start = jiffies;
1271 1266
@@ -1278,7 +1273,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
1278 */ 1273 */
1279 1274
1280 eieio(); 1275 eieio();
1281 txbdp->status = status; 1276 txbdp->lstatus = lstatus;
1282 1277
1283 txbdp = next_bd(txbdp, base, priv->tx_ring_size); 1278 txbdp = next_bd(txbdp, base, priv->tx_ring_size);
1284 1279
@@ -1546,20 +1541,19 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
1546 struct sk_buff *skb) 1541 struct sk_buff *skb)
1547{ 1542{
1548 struct gfar_private *priv = netdev_priv(dev); 1543 struct gfar_private *priv = netdev_priv(dev);
1549 u32 * status_len = (u32 *)bdp; 1544 u32 lstatus;
1550 u16 flags;
1551 1545
1552 bdp->bufPtr = dma_map_single(&dev->dev, skb->data, 1546 bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
1553 priv->rx_buffer_size, DMA_FROM_DEVICE); 1547 priv->rx_buffer_size, DMA_FROM_DEVICE);
1554 1548
1555 flags = RXBD_EMPTY | RXBD_INTERRUPT; 1549 lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
1556 1550
1557 if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1) 1551 if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
1558 flags |= RXBD_WRAP; 1552 lstatus |= BD_LFLAG(RXBD_WRAP);
1559 1553
1560 eieio(); 1554 eieio();
1561 1555
1562 *status_len = (u32)flags << 16; 1556 bdp->lstatus = lstatus;
1563} 1557}
1564 1558
1565 1559