From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1k6DVV-0003mA-3L for barebox@lists.infradead.org; Thu, 13 Aug 2020 13:43:04 +0000 From: Sascha Hauer Date: Thu, 13 Aug 2020 15:42:41 +0200 Message-Id: <20200813134257.24627-5-s.hauer@pengutronix.de> In-Reply-To: <20200813134257.24627-1-s.hauer@pengutronix.de> References: <20200813134257.24627-1-s.hauer@pengutronix.de> MIME-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH 04/20] net: Add a slice to struct eth_device To: Barebox List Cc: Edmund Henniges , =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Add ethernet code safe for being called from a poller. Signed-off-by: Sascha Hauer --- include/net.h | 8 +++++ net/eth.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/include/net.h b/include/net.h index 54db8a179a..8d2b4923de 100644 --- a/include/net.h +++ b/include/net.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include /* memcpy */ @@ -63,6 +64,8 @@ struct eth_device { char *bootarg; char *linuxdevname; + struct slice slice; + bool ifup; #define ETH_MODE_DHCP 0 #define ETH_MODE_STATIC 1 @@ -72,6 +75,11 @@ struct eth_device { #define dev_to_edev(d) container_of(d, struct eth_device, dev) +static inline struct slice *eth_device_slice(struct eth_device *edev) +{ + return &edev->slice; +} + static inline const char *eth_name(struct eth_device *edev) { return edev->devname; diff --git a/net/eth.c b/net/eth.c index e3d0d06efe..e67cc306c2 100644 --- a/net/eth.c +++ b/net/eth.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,56 @@ static int eth_carrier_check(struct eth_device *edev, int force) return edev->phydev->link ? 0 : -ENETDOWN; } +struct eth_q { + struct eth_device *edev; + int length; + struct list_head list; + void *data; +}; + +static int eth_queue(struct list_head *list, struct eth_device *edev, + void *packet, int length) +{ + struct eth_q *q; + + q = xzalloc(sizeof(*q)); + if (!q) + return -ENOMEM; + + q->data = dma_alloc(length); + if (!q->data) { + free(q); + return -ENOMEM; + } + + q->length = length; + q->edev = edev; + + memcpy(q->data, packet, length); + list_add_tail(&q->list, list); + + return 0; +} + +static LIST_HEAD(eth_send_list); + +static void eth_send_queue(void) +{ + struct eth_q *q, *tmp; + + list_for_each_entry_safe(q, tmp, ð_send_list, list) { + if (slice_acquired(eth_device_slice(q->edev))) + continue; + + if (q->edev->active) + eth_send(q->edev, q->data, q->length); + + list_del(&q->list); + free(q->data); + free(q); + } +} + int eth_send(struct eth_device *edev, void *packet, int length) { int ret; @@ -215,24 +266,39 @@ int eth_send(struct eth_device *edev, void *packet, int length) if (!edev->active) return -ENETDOWN; + if (slice_acquired(eth_device_slice(edev))) + return eth_queue(ð_send_list, edev, packet, length); + ret = eth_carrier_check(edev, 0); if (ret) return ret; + slice_acquire(eth_device_slice(edev)); + led_trigger_network(LED_TRIGGER_NET_TX); - return edev->send(edev, packet, length); + ret = edev->send(edev, packet, length); + + slice_release(eth_device_slice(edev)); + + return ret; } static int __eth_rx(struct eth_device *edev) { int ret; + slice_acquire(eth_device_slice(edev)); + ret = eth_carrier_check(edev, 0); if (ret) - return ret; + goto out; - return edev->recv(edev); + ret = edev->recv(edev); +out: + slice_release(eth_device_slice(edev)); + + return ret; } int eth_rx(void) @@ -244,6 +310,8 @@ int eth_rx(void) __eth_rx(edev); } + eth_send_queue(); + return 0; } @@ -353,6 +421,8 @@ int eth_register(struct eth_device *edev) if (ret) return ret; + slice_init(&edev->slice, dev_name(dev)); + edev->devname = xstrdup(dev_name(&edev->dev)); dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev); @@ -422,15 +492,27 @@ void eth_close(struct eth_device *edev) void eth_unregister(struct eth_device *edev) { + struct eth_q *q, *tmp; + if (edev->active) edev->halt(edev); + list_for_each_entry_safe(q, tmp, ð_send_list, list) { + if (q->edev != edev) + continue; + + list_del(&q->list); + free(q->data); + free(q); + } + if (IS_ENABLED(CONFIG_OFDEVICE)) free(edev->nodepath); free(edev->devname); unregister_device(&edev->dev); + slice_exit(&edev->slice); list_del(&edev->list); } -- 2.28.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox