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>
This commit is contained in:
parent
31de198b4d
commit
5a5efed481
@ -854,8 +854,7 @@ static void free_skb_resources(struct gfar_private *priv)
|
|||||||
priv->rx_skbuff[i] = NULL;
|
priv->rx_skbuff[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rxbdp->status = 0;
|
rxbdp->lstatus = 0;
|
||||||
rxbdp->length = 0;
|
|
||||||
rxbdp->bufPtr = 0;
|
rxbdp->bufPtr = 0;
|
||||||
|
|
||||||
rxbdp++;
|
rxbdp++;
|
||||||
@ -976,8 +975,7 @@ int startup_gfar(struct net_device *dev)
|
|||||||
/* Initialize Transmit Descriptor Ring */
|
/* Initialize Transmit Descriptor Ring */
|
||||||
txbdp = priv->tx_bd_base;
|
txbdp = priv->tx_bd_base;
|
||||||
for (i = 0; i < priv->tx_ring_size; i++) {
|
for (i = 0; i < priv->tx_ring_size; i++) {
|
||||||
txbdp->status = 0;
|
txbdp->lstatus = 0;
|
||||||
txbdp->length = 0;
|
|
||||||
txbdp->bufPtr = 0;
|
txbdp->bufPtr = 0;
|
||||||
txbdp++;
|
txbdp++;
|
||||||
}
|
}
|
||||||
@ -1216,7 +1214,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
struct gfar_private *priv = netdev_priv(dev);
|
struct gfar_private *priv = netdev_priv(dev);
|
||||||
struct txfcb *fcb = NULL;
|
struct txfcb *fcb = NULL;
|
||||||
struct txbd8 *txbdp, *base;
|
struct txbd8 *txbdp, *base;
|
||||||
u16 status;
|
u32 lstatus;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/* Update transmit stats */
|
/* Update transmit stats */
|
||||||
@ -1230,26 +1228,25 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
base = priv->tx_bd_base;
|
base = priv->tx_bd_base;
|
||||||
|
|
||||||
/* Clear all but the WRAP status flags */
|
/* Clear all but the WRAP status flags */
|
||||||
status = txbdp->status & TXBD_WRAP;
|
lstatus = txbdp->lstatus & BD_LFLAG(TXBD_WRAP);
|
||||||
|
|
||||||
/* Set up checksumming */
|
/* Set up checksumming */
|
||||||
if (CHECKSUM_PARTIAL == skb->ip_summed) {
|
if (CHECKSUM_PARTIAL == skb->ip_summed) {
|
||||||
fcb = gfar_add_fcb(skb);
|
fcb = gfar_add_fcb(skb);
|
||||||
status |= TXBD_TOE;
|
lstatus |= BD_LFLAG(TXBD_TOE);
|
||||||
gfar_tx_checksum(skb, fcb);
|
gfar_tx_checksum(skb, fcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->vlgrp && vlan_tx_tag_present(skb)) {
|
if (priv->vlgrp && vlan_tx_tag_present(skb)) {
|
||||||
if (unlikely(NULL == fcb)) {
|
if (unlikely(NULL == fcb)) {
|
||||||
fcb = gfar_add_fcb(skb);
|
fcb = gfar_add_fcb(skb);
|
||||||
status |= TXBD_TOE;
|
lstatus |= BD_LFLAG(TXBD_TOE);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfar_tx_vlan(skb, fcb);
|
gfar_tx_vlan(skb, fcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set buffer length and pointer */
|
/* Set buffer length and pointer */
|
||||||
txbdp->length = skb->len;
|
|
||||||
txbdp->bufPtr = dma_map_single(&dev->dev, skb->data,
|
txbdp->bufPtr = dma_map_single(&dev->dev, skb->data,
|
||||||
skb->len, DMA_TO_DEVICE);
|
skb->len, DMA_TO_DEVICE);
|
||||||
|
|
||||||
@ -1260,12 +1257,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
priv->skb_curtx =
|
priv->skb_curtx =
|
||||||
(priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
|
(priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
|
||||||
|
|
||||||
/* Flag the BD as interrupt-causing */
|
/* Flag the BD as ready, interrupt-causing, last, and in need of CRC */
|
||||||
status |= TXBD_INTERRUPT;
|
lstatus |=
|
||||||
|
BD_LFLAG(TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT) |
|
||||||
/* Flag the BD as ready to go, last in frame, and */
|
skb->len;
|
||||||
/* in need of CRC */
|
|
||||||
status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
|
|
||||||
|
|
||||||
dev->trans_start = jiffies;
|
dev->trans_start = jiffies;
|
||||||
|
|
||||||
@ -1278,7 +1273,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
eieio();
|
eieio();
|
||||||
txbdp->status = status;
|
txbdp->lstatus = lstatus;
|
||||||
|
|
||||||
txbdp = next_bd(txbdp, base, priv->tx_ring_size);
|
txbdp = next_bd(txbdp, base, priv->tx_ring_size);
|
||||||
|
|
||||||
@ -1546,20 +1541,19 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
|
|||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct gfar_private *priv = netdev_priv(dev);
|
struct gfar_private *priv = netdev_priv(dev);
|
||||||
u32 * status_len = (u32 *)bdp;
|
u32 lstatus;
|
||||||
u16 flags;
|
|
||||||
|
|
||||||
bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
|
bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
|
||||||
priv->rx_buffer_size, DMA_FROM_DEVICE);
|
priv->rx_buffer_size, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
flags = RXBD_EMPTY | RXBD_INTERRUPT;
|
lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
|
||||||
|
|
||||||
if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
|
if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
|
||||||
flags |= RXBD_WRAP;
|
lstatus |= BD_LFLAG(RXBD_WRAP);
|
||||||
|
|
||||||
eieio();
|
eieio();
|
||||||
|
|
||||||
*status_len = (u32)flags << 16;
|
bdp->lstatus = lstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -311,6 +311,8 @@ extern const char gfar_driver_version[];
|
|||||||
#define ATTRELI_EI_MASK 0x00003fff
|
#define ATTRELI_EI_MASK 0x00003fff
|
||||||
#define ATTRELI_EI(x) (x)
|
#define ATTRELI_EI(x) (x)
|
||||||
|
|
||||||
|
#define BD_LFLAG(flags) ((flags) << 16)
|
||||||
|
#define BD_LENGTH_MASK 0x00ff
|
||||||
|
|
||||||
/* TxBD status field bits */
|
/* TxBD status field bits */
|
||||||
#define TXBD_READY 0x8000
|
#define TXBD_READY 0x8000
|
||||||
@ -374,8 +376,13 @@ extern const char gfar_driver_version[];
|
|||||||
|
|
||||||
struct txbd8
|
struct txbd8
|
||||||
{
|
{
|
||||||
u16 status; /* Status Fields */
|
union {
|
||||||
u16 length; /* Buffer length */
|
struct {
|
||||||
|
u16 status; /* Status Fields */
|
||||||
|
u16 length; /* Buffer length */
|
||||||
|
};
|
||||||
|
u32 lstatus;
|
||||||
|
};
|
||||||
u32 bufPtr; /* Buffer Pointer */
|
u32 bufPtr; /* Buffer Pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -390,8 +397,13 @@ struct txfcb {
|
|||||||
|
|
||||||
struct rxbd8
|
struct rxbd8
|
||||||
{
|
{
|
||||||
u16 status; /* Status Fields */
|
union {
|
||||||
u16 length; /* Buffer Length */
|
struct {
|
||||||
|
u16 status; /* Status Fields */
|
||||||
|
u16 length; /* Buffer Length */
|
||||||
|
};
|
||||||
|
u32 lstatus;
|
||||||
|
};
|
||||||
u32 bufPtr; /* Buffer Pointer */
|
u32 bufPtr; /* Buffer Pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user