[U-Boot] [PATCH 10/12] net: emaclite: Use indirect access in emaclite_recv

Michal Simek michal.simek at xilinx.com
Fri Dec 11 13:03:41 CET 2015


When IP is configured with pong buffers, IP is receiving packets to ping
and then to pong buffer and than ping again.
Origin logic in the driver remains there that when ping buffer is
free, pong buffer is checked too and return if both are free.

Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

Do you know macros which I could use for addressing certain fields in
ethernet and IP packet? The code is there because copying huge amount of
data is causing performance penalty.

---
 drivers/net/xilinx_emaclite.c | 90 ++++++++++++++++++++++++-------------------
 1 file changed, 51 insertions(+), 39 deletions(-)

diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index e97ce2ce31f3..b5ff4f099251 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -22,11 +22,6 @@
 
 #define ENET_ADDR_LENGTH	6
 
-/* EmacLite constants */
-#define XEL_BUFFER_OFFSET	0x0800	/* Next buffer's offset */
-#define XEL_RSR_OFFSET		0x17FC	/* Rx status */
-#define XEL_RXBUFF_OFFSET	0x1000	/* Receive Buffer */
-
 /* Xmit complete */
 #define XEL_TSR_XMIT_BUSY_MASK		0x00000001UL
 /* Xmit interrupt enable bit */
@@ -86,7 +81,7 @@ struct emaclite_regs {
 };
 
 struct xemaclite {
-	u32 nextrxbuffertouse;	/* Next RX buffer to read from */
+	bool nextrxbuffertouse;	/* Next RX buffer to read from */
 	u32 txpp;		/* TX ping pong buffer */
 	u32 rxpp;		/* RX ping pong buffer */
 	int phyaddr;
@@ -455,45 +450,63 @@ static int emaclite_recv(struct eth_device *dev)
 {
 	u32 length;
 	u32 reg;
-	u32 baseaddress;
+	u32 *addr, *ack;
 	struct xemaclite *emaclite = dev->priv;
-
-	baseaddress = dev->iobase + emaclite->nextrxbuffertouse;
-	reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
-	debug("Testing data at address 0x%x\n", baseaddress);
-	if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
-		if (emaclite->rxpp)
-			emaclite->nextrxbuffertouse ^= XEL_BUFFER_OFFSET;
+	struct emaclite_regs *regs = emaclite->regs;
+	u32 attempt = 0;
+
+try_again:
+	if (!emaclite->nextrxbuffertouse) {
+		reg = in_be32(&regs->rx_ping_rsr);
+		debug("Testing data at rx_ping\n");
+		if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
+			debug("Data found in rx_ping buffer\n");
+			addr = &regs->rx_ping;
+			ack = &regs->rx_ping_rsr;
+		} else {
+			debug("Data not found in rx_ping buffer\n");
+			/* Pong buffer is not available - return immediatelly */
+			if (!emaclite->rxpp)
+				return -1;
+
+			/* Try pong buffer if this is first attempt */
+			if (attempt++)
+				return -1;
+			emaclite->nextrxbuffertouse =
+						  !emaclite->nextrxbuffertouse;
+			goto try_again;
+		}
 	} else {
-
-		if (!emaclite->rxpp) {
-			debug("No data was available - address 0x%x\n",
-								baseaddress);
-			return 0;
+		reg = in_be32(&regs->rx_pong_rsr);
+		debug("Testing data at rx_pong\n");
+		if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
+			debug("Data found in rx_pong buffer\n");
+			addr = &regs->rx_pong;
+			ack = &regs->rx_pong_rsr;
 		} else {
-			baseaddress ^= XEL_BUFFER_OFFSET;
-			reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
-			if ((reg & XEL_RSR_RECV_DONE_MASK) !=
-						XEL_RSR_RECV_DONE_MASK) {
-				debug("No data was available - address 0x%x\n",
-						baseaddress);
-				return 0;
-			}
+			debug("Data not found in rx_pong buffer\n");
+			/* Try ping buffer if this is first attempt */
+			if (attempt++)
+				return -1;
+			emaclite->nextrxbuffertouse =
+						  !emaclite->nextrxbuffertouse;
+			goto try_again;
 		}
 	}
+
+#define	ETH_TYPE_OFFSET		3
+#define	IP_LENGTH_OFFSET	4
 	/* Get the length of the frame that arrived */
-	switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) &
-			0xFFFF0000 ) >> 16) {
+	switch (((ntohl(in_be32(addr + ETH_TYPE_OFFSET))) & 0xFFFF0000) >> 16) {
 		case 0x806:
 			length = 42 + 20; /* FIXME size of ARP */
-			debug("ARP Packet\n");
+			debug("ARP Packet %x\n", length);
 			break;
 		case 0x800:
 			length = 14 + 14 +
-			(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET +
-						0x10))) & 0xFFFF0000) >> 16);
-			/* FIXME size of IP packet */
-			debug ("IP Packet\n");
+			      (((ntohl(in_be32(addr + IP_LENGTH_OFFSET))) &
+			       0xFFFF0000) >> 16);
+			debug("IP Packet %x\n", length);
 			break;
 		default:
 			debug("Other Packet\n");
@@ -501,15 +514,14 @@ static int emaclite_recv(struct eth_device *dev)
 			break;
 	}
 
-	xemaclite_alignedread((u32 *) (baseaddress + XEL_RXBUFF_OFFSET),
-			etherrxbuff, length);
+	xemaclite_alignedread(addr, etherrxbuff, length);
 
 	/* Acknowledge the frame */
-	reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
+	reg = in_be32(ack);
 	reg &= ~XEL_RSR_RECV_DONE_MASK;
-	out_be32 (baseaddress + XEL_RSR_OFFSET, reg);
+	out_be32(ack, reg);
 
-	debug("Packet receive from 0x%x, length %dB\n", baseaddress, length);
+	debug("Packet receive from 0x%p, length %dB\n", addr, length);
 	net_process_received_packet((uchar *)etherrxbuff, length);
 	return length;
 
-- 
1.9.1



More information about the U-Boot mailing list