dm: eth: Avoid blocking on packet reception
authorSimon Glass <sjg@chromium.org>
Mon, 6 Jul 2015 22:47:49 +0000 (16:47 -0600)
committerSimon Glass <sjg@chromium.org>
Tue, 21 Jul 2015 23:39:40 +0000 (17:39 -0600)
Some devices can take a long time to work out whether they have a new packet
or now. For example the ASIX USB Ethernet dongle can take 5 seconds to do
this, since it waits until it gets a new packet on the wire before allowing
the USB bulk read packet to be submitted.

At present with driver mode the Ethernet receive code reads 32 packets. This
can take a very long time if we must wait for all 32 packets. The old code
(before driver model) worked by reading a single set of packets from the USB
device, then processing all the packets with in. It would be nice to use
the same behaviour with driver model.

Add a flag to the receive method which indicates that the driver should try
to find a packet if available, by consulting the hardware. When the flag is
not set, it should just return any packet data it has already received. If
there is none, it should return -EAGAIN so that the loop will terminate.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/net/designware.c
drivers/net/sandbox-raw.c
drivers/net/sandbox.c
drivers/net/sunxi_emac.c
include/net.h
net/eth.c

index 645ca6427cf41843f90a8fdcf3c941ae144e83c9..bcae842389aae9de0f2f8e0425c6f9b27dba2775 100644 (file)
@@ -528,7 +528,7 @@ static int designware_eth_send(struct udevice *dev, void *packet, int length)
        return _dw_eth_send(priv, packet, length);
 }
 
-static int designware_eth_recv(struct udevice *dev, uchar **packetp)
+static int designware_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct dw_eth_dev *priv = dev_get_priv(dev);
 
index 45c3b18bdf33ccfe8d4f224e5d6e10f6c2e385ab..591242797e26dfff301888f1022f62ce8fa5f88d 100644 (file)
@@ -65,7 +65,7 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
        return sandbox_eth_raw_os_send(packet, length, priv);
 }
 
-static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
+static int sb_eth_raw_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
index 4e083d32ae6fe7aad839b84c5875ed98bbc4d627..6763a248f28d0b327c8b14ff757206cf10a26432 100644 (file)
@@ -152,7 +152,7 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
        return 0;
 }
 
-static int sb_eth_recv(struct udevice *dev, uchar **packetp)
+static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct eth_sandbox_priv *priv = dev_get_priv(dev);
 
index e939bf2108a3fbde2c23cd01bdb09f815a4be53c..11cd0ea06888ba8e271b0c10376306df5291a3e2 100644 (file)
@@ -527,7 +527,7 @@ static int sunxi_emac_eth_send(struct udevice *dev, void *packet, int length)
        return _sunxi_emac_eth_send(priv, packet, length);
 }
 
-static int sunxi_emac_eth_recv(struct udevice *dev, uchar **packetp)
+static int sunxi_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct emac_eth_dev *priv = dev_get_priv(dev);
        int rx_len;
index d17173d818a4fb9160aa8fed65a6f56ab263c457..b9c13f282cd347df2e2346f2c32267e90a5a64d4 100644 (file)
@@ -93,6 +93,14 @@ struct eth_pdata {
        int phy_interface;
 };
 
+enum eth_recv_flags {
+       /*
+        * Check hardware device for new packets (otherwise only return those
+        * which are already in the memory buffer ready to process)
+        */
+       ETH_RECV_CHECK_DEVICE           = 1 << 0,
+};
+
 /**
  * struct eth_ops - functions of Ethernet MAC controllers
  *
@@ -120,7 +128,7 @@ struct eth_pdata {
 struct eth_ops {
        int (*start)(struct udevice *dev);
        int (*send)(struct udevice *dev, void *packet, int length);
-       int (*recv)(struct udevice *dev, uchar **packetp);
+       int (*recv)(struct udevice *dev, int flags, uchar **packetp);
        int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
        void (*stop)(struct udevice *dev);
 #ifdef CONFIG_MCAST_TFTP
index 953b7310bd5cf66362bf04534a552b08eaa3c830..72ce91c9d0bbb546c7d8b50098b161ca8cf124ea 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -404,6 +404,7 @@ int eth_rx(void)
 {
        struct udevice *current;
        uchar *packet;
+       int flags;
        int ret;
        int i;
 
@@ -415,8 +416,10 @@ int eth_rx(void)
                return -EINVAL;
 
        /* Process up to 32 packets at one time */
+       flags = ETH_RECV_CHECK_DEVICE;
        for (i = 0; i < 32; i++) {
-               ret = eth_get_ops(current)->recv(current, &packet);
+               ret = eth_get_ops(current)->recv(current, flags, &packet);
+               flags = 0;
                if (ret > 0)
                        net_process_received_packet(packet, ret);
                if (ret >= 0 && eth_get_ops(current)->free_pkt)