summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-03-06 15:07:20 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-08-19 07:36:14 +0200
commit2cecc865ae9b9819ea7f56553847451c5e19e2f1 (patch)
treeeedfe5d5ce62be1d9671084906cb8f71c50360d6 /net
parent5eb56c4e482937d2e01eb79fcc0086787084ba5a (diff)
downloadbarebox-2cecc865ae9b9819ea7f56553847451c5e19e2f1.tar.gz
barebox-2cecc865ae9b9819ea7f56553847451c5e19e2f1.tar.xz
net: Call net_poll() in a poller
This adds calling of net_poll() in a poller. With this we can react to incoming packets like ping requests or fastboot requests. We could change to call net_poll() from a poller exclusively, but this would significantly slow down USB network controllers. As described in the patch these take a long time in the packet receive path. To work around this we keep the networking users call net_poll() at a high rate when they are waiting for incoming packets and only every 10ms we call net_poll() from a poller to get incoming traffic when no networking protocol is actively calling net_poll(). Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/eth.c14
-rw-r--r--net/net.c50
3 files changed, 60 insertions, 5 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 12b6bdb56d..dc32f6a2cb 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -1,5 +1,6 @@
menuconfig NET
bool "Networking Support"
+ select POLLER
if NET
diff --git a/net/eth.c b/net/eth.c
index 4cd7d6119e..85110ef695 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -269,11 +269,16 @@ static void eth_do_work(struct eth_device *edev)
struct eth_q *q, *tmp;
int ret;
- slice_acquire(eth_device_slice(edev));
+ if (!phy_acquired(edev->phydev)) {
+ ret = eth_carrier_check(edev, 0);
+ if (ret)
+ return;
+ }
- ret = eth_carrier_check(edev, 0);
- if (ret)
- goto out;
+ if (slice_acquired(eth_device_slice(edev)))
+ return;
+
+ slice_acquire(eth_device_slice(edev));
edev->recv(edev);
@@ -285,7 +290,6 @@ static void eth_do_work(struct eth_device *edev)
free(q);
}
-out:
slice_release(eth_device_slice(edev));
}
diff --git a/net/net.c b/net/net.c
index 5fd6246ab2..69c1bc6222 100644
--- a/net/net.c
+++ b/net/net.c
@@ -251,8 +251,58 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et
void net_poll(void)
{
+ static bool in_net_poll;
+
+ if (in_net_poll)
+ return;
+
+ in_net_poll = true;
+
eth_rx();
+
+ in_net_poll = false;
+}
+
+static void __net_poll(struct poller_struct *poller)
+{
+ static uint64_t last;
+
+ /*
+ * USB network controllers take a long time in the receive path,
+ * so limit the polling rate to once per 10ms. This is due to
+ * deficiencies in the barebox USB stack: We can't queue URBs and
+ * receive a callback when they are done. Instead, we always
+ * synchronously queue an URB and wait for its completion. In case
+ * of USB network adapters the only way to detect if packets have
+ * been received is to queue a RX URB and see if it completes (in
+ * which case we have received data) or if it timeouts (no data
+ * available). The timeout can't be arbitrarily small, 2ms is the
+ * smallest we can do with the 1ms USB frame size.
+ *
+ * Given that we do a mixture of polling-as-fast-as-possible when
+ * we are waiting for network traffic (tftp, nfs and other users
+ * actively calling net_poll()) and doing a low frequency polling
+ * here to still get packets when no user is actively waiting for
+ * incoming packets. This is used to receive incoming ping packets
+ * and to get fastboot over ethernet going.
+ */
+ if (!is_timeout(last, 10 * MSECOND))
+ return;
+
+ net_poll();
+
+ last = get_time_ns();
+}
+
+static struct poller_struct net_poller = {
+ .func = __net_poll,
+};
+
+static int init_net_poll(void)
+{
+ return poller_register(&net_poller, "net");
}
+device_initcall(init_net_poll);
static uint16_t net_udp_new_localport(void)
{