mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-17 12:41:32 +00:00
dm: eth: Avoid blocking on packet reception
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>
This commit is contained in:
parent
69559093f6
commit
a1ca92eaaf
6 changed files with 17 additions and 6 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue