aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
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
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')
-rw-r--r--drivers/net/gianfar.c36
-rw-r--r--drivers/net/gianfar.h20
2 files changed, 31 insertions, 25 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index e7e8201283a..3e611a69df1 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
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 1ebf7ac27a3..9c8974dc8dd 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -311,6 +311,8 @@ extern const char gfar_driver_version[];
311#define ATTRELI_EI_MASK 0x00003fff 311#define ATTRELI_EI_MASK 0x00003fff
312#define ATTRELI_EI(x) (x) 312#define ATTRELI_EI(x) (x)
313 313
314#define BD_LFLAG(flags) ((flags) << 16)
315#define BD_LENGTH_MASK 0x00ff
314 316
315/* TxBD status field bits */ 317/* TxBD status field bits */
316#define TXBD_READY 0x8000 318#define TXBD_READY 0x8000
@@ -374,8 +376,13 @@ extern const char gfar_driver_version[];
374 376
375struct txbd8 377struct txbd8
376{ 378{
377 u16 status; /* Status Fields */ 379 union {
378 u16 length; /* Buffer length */ 380 struct {
381 u16 status; /* Status Fields */
382 u16 length; /* Buffer length */
383 };
384 u32 lstatus;
385 };
379 u32 bufPtr; /* Buffer Pointer */ 386 u32 bufPtr; /* Buffer Pointer */
380}; 387};
381 388
@@ -390,8 +397,13 @@ struct txfcb {
390 397
391struct rxbd8 398struct rxbd8
392{ 399{
393 u16 status; /* Status Fields */ 400 union {
394 u16 length; /* Buffer Length */ 401 struct {
402 u16 status; /* Status Fields */
403 u16 length; /* Buffer Length */
404 };
405 u32 lstatus;
406 };
395 u32 bufPtr; /* Buffer Pointer */ 407 u32 bufPtr; /* Buffer Pointer */
396}; 408};
397 409