From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 09 Dec 2023 07:24:11 +0000 Subject: [PATCH] add stmac read mac form eeprom --- kernel/arch/um/drivers/vector_kern.c | 183 ++++++++++++++++++++++++++++++++++++++------- 1 files changed, 154 insertions(+), 29 deletions(-) diff --git a/kernel/arch/um/drivers/vector_kern.c b/kernel/arch/um/drivers/vector_kern.c index 50ee3bb..555203e 100644 --- a/kernel/arch/um/drivers/vector_kern.c +++ b/kernel/arch/um/drivers/vector_kern.c @@ -1,15 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2017 - Cambridge Greys Limited + * Copyright (C) 2017 - 2019 Cambridge Greys Limited * Copyright (C) 2011 - 2014 Cisco Systems Inc * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. - * Licensed under the GPL. */ #include <linux/version.h> -#include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/inetdevice.h> @@ -21,6 +21,9 @@ #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/firmware.h> +#include <linux/fs.h> +#include <uapi/linux/filter.h> #include <init.h> #include <irq_kern.h> #include <irq_user.h> @@ -43,7 +46,6 @@ #define DRIVER_NAME "uml-vector" -#define DRIVER_VERSION "01" struct vector_cmd_line_arg { struct list_head list; int unit; @@ -76,6 +78,7 @@ #define DEFAULT_VECTOR_SIZE 64 #define TX_SMALL_PACKET 128 #define MAX_IOV_SIZE (MAX_SKB_FRAGS + 1) +#define MAX_ITERATIONS 64 static const struct { const char string[ETH_GSTRING_LEN]; @@ -121,9 +124,27 @@ if (mtu != NULL) { if (kstrtoul(mtu, 10, &result) == 0) - return result; + if ((result < (1 << 16) - 1) && (result >= 576)) + return result; } return ETH_MAX_PACKET; +} + +static char *get_bpf_file(struct arglist *def) +{ + return uml_vector_fetch_arg(def, "bpffile"); +} + +static bool get_bpf_flash(struct arglist *def) +{ + char *allow = uml_vector_fetch_arg(def, "bpfflash"); + long result; + + if (allow != NULL) { + if (kstrtoul(allow, 10, &result) == 0) + return (allow > 0); + } + return false; } static int get_depth(struct arglist *def) @@ -174,6 +195,10 @@ int vec_rx = VECTOR_RX; int vec_tx = VECTOR_TX; long parsed; + int result = 0; + + if (transport == NULL) + return -EINVAL; if (vector != NULL) { if (kstrtoul(vector, 10, &parsed) == 0) { @@ -184,12 +209,16 @@ } } + if (get_bpf_flash(def)) + result = VECTOR_BPF_FLASH; if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0) - return (vec_rx | VECTOR_BPF); + return result; + if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0) + return (result | vec_rx | VECTOR_BPF); if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0) - return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS); - return (vec_rx | vec_tx); + return (result | vec_rx | vec_tx | VECTOR_QDISC_BYPASS); + return (result | vec_rx | vec_tx); } @@ -415,6 +444,7 @@ if (net_ratelimit()) netdev_err(vp->dev, "sendmmsg err=%i\n", result); + vp->in_error = true; result = send_len; } if (result > 0) { @@ -842,6 +872,10 @@ } pkt_len = uml_vector_recvmsg(vp->fds->rx_fd, &hdr, 0); + if (pkt_len < 0) { + vp->in_error = true; + return pkt_len; + } if (skb != NULL) { if (pkt_len > vp->header_size) { @@ -888,11 +922,15 @@ if (iov_count < 1) goto drop; + pkt_len = uml_vector_writev( vp->fds->tx_fd, (struct iovec *) &iov, iov_count ); + + if (pkt_len < 0) + goto drop; netif_trans_update(vp->dev); netif_wake_queue(vp->dev); @@ -908,6 +946,8 @@ drop: vp->dev->stats.tx_dropped++; consume_skb(skb); + if (pkt_len < 0) + vp->in_error = true; return pkt_len; } @@ -935,6 +975,9 @@ packet_count = uml_vector_recvmmsg( vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0); + + if (packet_count < 0) + vp->in_error = true; if (packet_count <= 0) return packet_count; @@ -1005,21 +1048,31 @@ static void vector_rx(struct vector_private *vp) { int err; + int iter = 0; if ((vp->options & VECTOR_RX) > 0) - while ((err = vector_mmsg_rx(vp)) > 0) - ; + while (((err = vector_mmsg_rx(vp)) > 0) && (iter < MAX_ITERATIONS)) + iter++; else - while ((err = vector_legacy_rx(vp)) > 0) - ; + while (((err = vector_legacy_rx(vp)) > 0) && (iter < MAX_ITERATIONS)) + iter++; if ((err != 0) && net_ratelimit()) netdev_err(vp->dev, "vector_rx: error(%d)\n", err); + if (iter == MAX_ITERATIONS) + netdev_err(vp->dev, "vector_rx: device stuck, remote end may have closed the connection\n"); } static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vector_private *vp = netdev_priv(dev); int queue_depth = 0; + + if (vp->in_error) { + deactivate_fd(vp->fds->rx_fd, vp->rx_irq); + if ((vp->fds->rx_fd != vp->fds->tx_fd) && (vp->tx_irq != 0)) + deactivate_fd(vp->fds->tx_fd, vp->tx_irq); + return NETDEV_TX_BUSY; + } if ((vp->options & VECTOR_TX) == 0) { writev_tx(vp, skb); @@ -1043,7 +1096,7 @@ vector_send(vp->tx_queue); return NETDEV_TX_OK; } - if (skb->xmit_more) { + if (netdev_xmit_more()) { mod_timer(&vp->tl, vp->coalesce); return NETDEV_TX_OK; } @@ -1111,6 +1164,8 @@ } tasklet_kill(&vp->tx_poll); if (vp->fds->rx_fd > 0) { + if (vp->bpf) + uml_vector_detach_bpf(vp->fds->rx_fd, vp->bpf); os_close_file(vp->fds->rx_fd); vp->fds->rx_fd = -1; } @@ -1119,15 +1174,13 @@ vp->fds->tx_fd = -1; } if (vp->bpf != NULL) - kfree(vp->bpf); - if (vp->fds->remote_addr != NULL) - kfree(vp->fds->remote_addr); - if (vp->transport_data != NULL) - kfree(vp->transport_data); - if (vp->header_rxbuffer != NULL) - kfree(vp->header_rxbuffer); - if (vp->header_txbuffer != NULL) - kfree(vp->header_txbuffer); + kfree(vp->bpf->filter); + kfree(vp->bpf); + vp->bpf = NULL; + kfree(vp->fds->remote_addr); + kfree(vp->transport_data); + kfree(vp->header_rxbuffer); + kfree(vp->header_txbuffer); if (vp->rx_queue != NULL) destroy_queue(vp->rx_queue); if (vp->tx_queue != NULL) @@ -1136,6 +1189,7 @@ vp->fds = NULL; spin_lock_irqsave(&vp->lock, flags); vp->opened = false; + vp->in_error = false; spin_unlock_irqrestore(&vp->lock, flags); return 0; } @@ -1157,6 +1211,7 @@ netif_start_queue(vp->dev); netif_wake_queue(vp->dev); } + static int vector_net_open(struct net_device *dev) { struct vector_private *vp = netdev_priv(dev); @@ -1171,6 +1226,8 @@ } vp->opened = true; spin_unlock_irqrestore(&vp->lock, flags); + + vp->bpf = uml_vector_user_bpf(get_bpf_file(vp->parsed)); vp->fds = uml_vector_user_open(vp->unit, vp->parsed); @@ -1243,8 +1300,11 @@ if (!uml_raw_enable_qdisc_bypass(vp->fds->rx_fd)) vp->options |= VECTOR_BPF; } - if ((vp->options & VECTOR_BPF) != 0) - vp->bpf = uml_vector_default_bpf(vp->fds->rx_fd, dev->dev_addr); + if (((vp->options & VECTOR_BPF) != 0) && (vp->bpf == NULL)) + vp->bpf = uml_vector_default_bpf(dev->dev_addr); + + if (vp->bpf != NULL) + uml_vector_attach_bpf(vp->fds->rx_fd, vp->bpf); netif_start_queue(dev); @@ -1274,7 +1334,7 @@ return; } -static void vector_net_tx_timeout(struct net_device *dev) +static void vector_net_tx_timeout(struct net_device *dev, unsigned int txqueue) { struct vector_private *vp = netdev_priv(dev); @@ -1320,7 +1380,65 @@ struct ethtool_drvinfo *info) { strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); - strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); +} + +static int vector_net_load_bpf_flash(struct net_device *dev, + struct ethtool_flash *efl) +{ + struct vector_private *vp = netdev_priv(dev); + struct vector_device *vdevice; + const struct firmware *fw; + int result = 0; + + if (!(vp->options & VECTOR_BPF_FLASH)) { + netdev_err(dev, "loading firmware not permitted: %s\n", efl->data); + return -1; + } + + spin_lock(&vp->lock); + + if (vp->bpf != NULL) { + if (vp->opened) + uml_vector_detach_bpf(vp->fds->rx_fd, vp->bpf); + kfree(vp->bpf->filter); + vp->bpf->filter = NULL; + } else { + vp->bpf = kmalloc(sizeof(struct sock_fprog), GFP_ATOMIC); + if (vp->bpf == NULL) { + netdev_err(dev, "failed to allocate memory for firmware\n"); + goto flash_fail; + } + } + + vdevice = find_device(vp->unit); + + if (request_firmware(&fw, efl->data, &vdevice->pdev.dev)) + goto flash_fail; + + vp->bpf->filter = kmemdup(fw->data, fw->size, GFP_ATOMIC); + if (!vp->bpf->filter) + goto free_buffer; + + vp->bpf->len = fw->size / sizeof(struct sock_filter); + release_firmware(fw); + + if (vp->opened) + result = uml_vector_attach_bpf(vp->fds->rx_fd, vp->bpf); + + spin_unlock(&vp->lock); + + return result; + +free_buffer: + release_firmware(fw); + +flash_fail: + spin_unlock(&vp->lock); + if (vp->bpf != NULL) + kfree(vp->bpf->filter); + kfree(vp->bpf); + vp->bpf = NULL; + return -1; } static void vector_get_ringparam(struct net_device *netdev, @@ -1391,6 +1509,7 @@ } static const struct ethtool_ops vector_net_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_TX_USECS, .get_drvinfo = vector_net_get_drvinfo, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, @@ -1400,6 +1519,7 @@ .get_ethtool_stats = vector_get_ethtool_stats, .get_coalesce = vector_get_coalesce, .set_coalesce = vector_set_coalesce, + .flash_device = vector_net_load_bpf_flash, }; @@ -1503,8 +1623,10 @@ .transport_data = NULL, .in_write_poll = false, .coalesce = 2, - .req_size = get_req_size(def) - }); + .req_size = get_req_size(def), + .in_error = false, + .bpf = NULL + }); dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST); tasklet_init(&vp->tx_poll, vector_tx_poll, (unsigned long)vp); @@ -1580,7 +1702,10 @@ str, error); return 1; } - new = alloc_bootmem(sizeof(*new)); + new = memblock_alloc(sizeof(*new), SMP_CACHE_BYTES); + if (!new) + panic("%s: Failed to allocate %zu bytes\n", __func__, + sizeof(*new)); INIT_LIST_HEAD(&new->list); new->unit = n; new->arguments = str; -- Gitblit v1.6.2