diff options
author | Dai Haruki <dai.haruki@freescale.com> | 2008-12-16 18:34:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-16 18:34:50 -0500 |
commit | 5a5efed4817ef931f648b118aeb9222e53122d2b (patch) | |
tree | 592f3dbe3bf47035e8738b1c4bbe48fc3be973fc /drivers/net | |
parent | 31de198b4d2732028f4c5bff04b0103b1d8c1d8c (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.c | 36 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 20 |
2 files changed, 31 insertions, 25 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 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 1ebf7ac27a3d..9c8974dc8dd5 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 | ||
375 | struct txbd8 | 377 | struct 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 | ||
391 | struct rxbd8 | 398 | struct 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 | ||