[PATCH v2 14/17] net: dm9000: Receive one packet per recv call

Marek Vasut marex at denx.de
Wed Apr 13 04:15:36 CEST 2022


Instead of reading out the entire FIFO and possibly overwriting U-Boot
memory, read out one packet per recv call, pass it to U-Boot network
stack, and repeat.

Reviewed-by: Ramon Fried <rfried.dev at gmail.com>
Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Joe Hershberger <joe.hershberger at ni.com>
Cc: Ramon Fried <rfried.dev at gmail.com>
---
V2: Add RB from Ramon
---
 drivers/net/dm9000x.c | 102 +++++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 52 deletions(-)

diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c
index 639977ad6e6..6552079748a 100644
--- a/drivers/net/dm9000x.c
+++ b/drivers/net/dm9000x.c
@@ -481,10 +481,9 @@ static void dm9000_halt_common(struct dm9000_priv *db)
 /*
  * Received a packet and pass to upper layer
  */
-static int dm9000_recv_common(struct dm9000_priv *db)
+static int dm9000_recv_common(struct dm9000_priv *db, uchar *rdptr)
 {
 	u8 rxbyte;
-	u8 *rdptr = (u8 *)net_rx_packets[0];
 	u16 rxstatus, rxlen = 0;
 
 	/*
@@ -497,58 +496,52 @@ static int dm9000_recv_common(struct dm9000_priv *db)
 	dm9000_iow(db, DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
 
 	/* There is _at least_ 1 package in the fifo, read them all */
-	for (;;) {
-		dm9000_ior(db, DM9000_MRCMDX);	/* Dummy read */
-
-		/*
-		 * Get most updated data,
-		 * only look at bits 0:1, See application notes DM9000
-		 */
-		rxbyte = dm9000_inb(db->base_data) & 0x03;
-
-		/* Status check: this byte must be 0 or 1 */
-		if (rxbyte > DM9000_PKT_RDY) {
-			dm9000_iow(db, DM9000_RCR, 0x00);	/* Stop Device */
-			dm9000_iow(db, DM9000_ISR, 0x80);	/* Stop INT request */
-			printf("DM9000 error: status check fail: 0x%x\n",
-			       rxbyte);
-			return 0;
-		}
+	dm9000_ior(db, DM9000_MRCMDX);	/* Dummy read */
+
+	/*
+	 * Get most updated data,
+	 * only look at bits 0:1, See application notes DM9000
+	 */
+	rxbyte = dm9000_inb(db->base_data) & 0x03;
+
+	/* Status check: this byte must be 0 or 1 */
+	if (rxbyte > DM9000_PKT_RDY) {
+		dm9000_iow(db, DM9000_RCR, 0x00);	/* Stop Device */
+		dm9000_iow(db, DM9000_ISR, 0x80);	/* Stop INT request */
+		printf("DM9000 error: status check fail: 0x%x\n",
+		       rxbyte);
+		return -EINVAL;
+	}
+
+	if (rxbyte != DM9000_PKT_RDY)
+		return 0; /* No packet received, ignore */
 
-		if (rxbyte != DM9000_PKT_RDY)
-			return 0; /* No packet received, ignore */
-
-		debug("receiving packet\n");
-
-		/* A packet ready now  & Get status/length */
-		db->rx_status(db, &rxstatus, &rxlen);
-
-		debug("rx status: 0x%04x rx len: %d\n", rxstatus, rxlen);
-
-		/* Move data from DM9000 */
-		/* Read received packet from RX SRAM */
-		db->inblk(db, rdptr, rxlen);
-
-		if (rxstatus & 0xbf00 || rxlen < 0x40 ||
-		    rxlen > DM9000_PKT_MAX) {
-			if (rxstatus & 0x100)
-				printf("rx fifo error\n");
-			if (rxstatus & 0x200)
-				printf("rx crc error\n");
-			if (rxstatus & 0x8000)
-				printf("rx length error\n");
-			if (rxlen > DM9000_PKT_MAX) {
-				printf("rx length too big\n");
-				dm9000_reset(db);
-			}
-		} else {
-			dm9000_dump_packet(__func__, rdptr, rxlen);
-
-			debug("passing packet to upper layer\n");
-			net_process_received_packet(net_rx_packets[0], rxlen);
+	debug("receiving packet\n");
+
+	/* A packet ready now  & Get status/length */
+	db->rx_status(db, &rxstatus, &rxlen);
+
+	debug("rx status: 0x%04x rx len: %d\n", rxstatus, rxlen);
+
+	/* Move data from DM9000 */
+	/* Read received packet from RX SRAM */
+	db->inblk(db, rdptr, rxlen);
+
+	if (rxstatus & 0xbf00 || rxlen < 0x40 || rxlen > DM9000_PKT_MAX) {
+		if (rxstatus & 0x100)
+			printf("rx fifo error\n");
+		if (rxstatus & 0x200)
+			printf("rx crc error\n");
+		if (rxstatus & 0x8000)
+			printf("rx length error\n");
+		if (rxlen > DM9000_PKT_MAX) {
+			printf("rx length too big\n");
+			dm9000_reset(db);
 		}
+		return -EINVAL;
 	}
-	return 0;
+
+	return rxlen;
 }
 
 /*
@@ -600,8 +593,13 @@ static int dm9000_send(struct eth_device *dev, void *packet, int length)
 static int dm9000_recv(struct eth_device *dev)
 {
 	struct dm9000_priv *db = container_of(dev, struct dm9000_priv, dev);
+	int ret;
+
+	ret = dm9000_recv_common(db, net_rx_packets[0]);
+	if (ret > 0)
+		net_process_received_packet(net_rx_packets[0], ret);
 
-	return dm9000_recv_common(db);
+	return ret;
 }
 
 int dm9000_initialize(struct bd_info *bis)
-- 
2.35.1



More information about the U-Boot mailing list