lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 16 Dec 2008 17:21:03 -0600
From:	Andy Fleming <afleming@...escale.com>
To:	jeff@...zik.org
Cc:	galak@...nel.crashing.org, netdev@...r.kernel.org,
	Andy Fleming <afleming@...escale.com>,
	Dai Haruki <Dai.Haruki@...escale.com>
Subject: [PATCH v2.6.29 10/14] 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@...escale.com>
Signed-off-by: Andy Fleming <afleming@...escale.com>
---
 drivers/net/gianfar.c |   36 +++++++++++++++---------------------
 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 2c88701..27dbe5a 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -854,8 +854,7 @@ static void free_skb_resources(struct gfar_private *priv)
 				priv->rx_skbuff[i] = NULL;
 			}
 
-			rxbdp->status = 0;
-			rxbdp->length = 0;
+			rxbdp->lstatus = 0;
 			rxbdp->bufPtr = 0;
 
 			rxbdp++;
@@ -976,8 +975,7 @@ int startup_gfar(struct net_device *dev)
 	/* Initialize Transmit Descriptor Ring */
 	txbdp = priv->tx_bd_base;
 	for (i = 0; i < priv->tx_ring_size; i++) {
-		txbdp->status = 0;
-		txbdp->length = 0;
+		txbdp->lstatus = 0;
 		txbdp->bufPtr = 0;
 		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 txfcb *fcb = NULL;
 	struct txbd8 *txbdp, *base;
-	u16 status;
+	u32 lstatus;
 	unsigned long flags;
 
 	/* 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;
 
 	/* Clear all but the WRAP status flags */
-	status = txbdp->status & TXBD_WRAP;
+	lstatus = txbdp->lstatus & BD_LFLAG(TXBD_WRAP);
 
 	/* Set up checksumming */
 	if (CHECKSUM_PARTIAL == skb->ip_summed) {
 		fcb = gfar_add_fcb(skb);
-		status |= TXBD_TOE;
+		lstatus |= BD_LFLAG(TXBD_TOE);
 		gfar_tx_checksum(skb, fcb);
 	}
 
 	if (priv->vlgrp && vlan_tx_tag_present(skb)) {
 		if (unlikely(NULL == fcb)) {
 			fcb = gfar_add_fcb(skb);
-			status |= TXBD_TOE;
+			lstatus |= BD_LFLAG(TXBD_TOE);
 		}
 
 		gfar_tx_vlan(skb, fcb);
 	}
 
 	/* Set buffer length and pointer */
-	txbdp->length = skb->len;
 	txbdp->bufPtr = dma_map_single(&dev->dev, skb->data,
 			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 + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
 
-	/* Flag the BD as interrupt-causing */
-	status |= TXBD_INTERRUPT;
-
-	/* Flag the BD as ready to go, last in frame, and  */
-	/* in need of CRC */
-	status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
+	/* Flag the BD as ready, interrupt-causing, last, and in need of CRC */
+	lstatus |= 
+		BD_LFLAG(TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT) |
+		skb->len;
 
 	dev->trans_start = jiffies;
 
@@ -1278,7 +1273,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	 */
 
 	eieio();
-	txbdp->status = status;
+	txbdp->lstatus = lstatus;
 
 	txbdp = next_bd(txbdp, base, priv->tx_ring_size);
 
@@ -1542,20 +1537,19 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
 		struct sk_buff *skb)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	u32 * status_len = (u32 *)bdp;
-	u16 flags;
+	u32 lstatus;
 
 	bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
 			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)
-		flags |= RXBD_WRAP;
+		lstatus |= BD_LFLAG(RXBD_WRAP);
 
 	eieio();
 
-	*status_len = (u32)flags << 16;
+	bdp->lstatus = lstatus;
 }
 
 
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 1ebf7ac..9c8974d 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -311,6 +311,8 @@ extern const char gfar_driver_version[];
 #define ATTRELI_EI_MASK		0x00003fff
 #define ATTRELI_EI(x) (x)
 
+#define BD_LFLAG(flags) ((flags) << 16)
+#define BD_LENGTH_MASK		0x00ff
 
 /* TxBD status field bits */
 #define TXBD_READY		0x8000
@@ -374,8 +376,13 @@ extern const char gfar_driver_version[];
 
 struct txbd8
 {
-	u16	status;	/* Status Fields */
-	u16	length;	/* Buffer length */
+	union {
+		struct {
+			u16	status;	/* Status Fields */
+			u16	length;	/* Buffer length */
+		};
+		u32 lstatus;
+	};
 	u32	bufPtr;	/* Buffer Pointer */
 };
 
@@ -390,8 +397,13 @@ struct txfcb {
 
 struct rxbd8
 {
-	u16	status;	/* Status Fields */
-	u16	length;	/* Buffer Length */
+	union {
+		struct {
+			u16	status;	/* Status Fields */
+			u16	length;	/* Buffer Length */
+		};
+		u32 lstatus;
+	};
 	u32	bufPtr;	/* Buffer Pointer */
 };
 
-- 
1.5.4.GIT

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists