]> git.baikalelectronics.ru Git - uboot.git/commitdiff
net: dm9000: Receive one packet per recv call
authorMarek Vasut <marex@denx.de>
Wed, 13 Apr 2022 02:15:36 +0000 (04:15 +0200)
committerRamon Fried <ramon@neureality.ai>
Wed, 13 Apr 2022 12:13:54 +0000 (15:13 +0300)
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@gmail.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
drivers/net/dm9000x.c

index 639977ad6e68106ffd9a5b3afe95c619958c31bd..6552079748a6a819ad2ffbcf7a606930ef249d97 100644 (file)
@@ -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)