forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
....@@ -1,17 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
23 *
3
- * This program is free software; you can redistribute it and/or modify
4
- * it under the terms of the GNU General Public License version 2 and
5
- * only version 2 as published by the Free Software Foundation.
6
- *
7
- * This program is distributed in the hope that it will be useful,
8
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- * GNU General Public License for more details.
11
- *
12
- *
134 * RMNET Data virtual network driver
14
- *
155 */
166
177 #include <linux/etherdevice.h>
....@@ -68,9 +58,30 @@
6858 return NETDEV_TX_OK;
6959 }
7060
61
+static int rmnet_vnd_headroom(struct rmnet_port *port)
62
+{
63
+ u32 headroom;
64
+
65
+ headroom = sizeof(struct rmnet_map_header);
66
+
67
+ if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4)
68
+ headroom += sizeof(struct rmnet_map_ul_csum_header);
69
+
70
+ return headroom;
71
+}
72
+
7173 static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu)
7274 {
73
- if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE)
75
+ struct rmnet_priv *priv = netdev_priv(rmnet_dev);
76
+ struct rmnet_port *port;
77
+ u32 headroom;
78
+
79
+ port = rmnet_get_port_rtnl(priv->real_dev);
80
+
81
+ headroom = rmnet_vnd_headroom(port);
82
+
83
+ if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE ||
84
+ new_mtu > (priv->real_dev->mtu - headroom))
7485 return -EINVAL;
7586
7687 rmnet_dev->mtu = new_mtu;
....@@ -114,24 +125,24 @@
114125 struct rtnl_link_stats64 *s)
115126 {
116127 struct rmnet_priv *priv = netdev_priv(dev);
117
- struct rmnet_vnd_stats total_stats;
128
+ struct rmnet_vnd_stats total_stats = { };
118129 struct rmnet_pcpu_stats *pcpu_ptr;
130
+ struct rmnet_vnd_stats snapshot;
119131 unsigned int cpu, start;
120
-
121
- memset(&total_stats, 0, sizeof(struct rmnet_vnd_stats));
122132
123133 for_each_possible_cpu(cpu) {
124134 pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu);
125135
126136 do {
127137 start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp);
128
- total_stats.rx_pkts += pcpu_ptr->stats.rx_pkts;
129
- total_stats.rx_bytes += pcpu_ptr->stats.rx_bytes;
130
- total_stats.tx_pkts += pcpu_ptr->stats.tx_pkts;
131
- total_stats.tx_bytes += pcpu_ptr->stats.tx_bytes;
138
+ snapshot = pcpu_ptr->stats; /* struct assignment */
132139 } while (u64_stats_fetch_retry_irq(&pcpu_ptr->syncp, start));
133140
134
- total_stats.tx_drops += pcpu_ptr->stats.tx_drops;
141
+ total_stats.rx_pkts += snapshot.rx_pkts;
142
+ total_stats.rx_bytes += snapshot.rx_bytes;
143
+ total_stats.tx_pkts += snapshot.tx_pkts;
144
+ total_stats.tx_bytes += snapshot.tx_bytes;
145
+ total_stats.tx_drops += snapshot.tx_drops;
135146 }
136147
137148 s->rx_packets = total_stats.rx_pkts;
....@@ -222,6 +233,8 @@
222233 rmnet_dev->needs_free_netdev = true;
223234 rmnet_dev->ethtool_ops = &rmnet_ethtool_ops;
224235
236
+ rmnet_dev->features |= NETIF_F_LLTX;
237
+
225238 /* This perm addr will be used as interface identifier by IPv6 */
226239 rmnet_dev->addr_assign_type = NET_ADDR_RANDOM;
227240 eth_random_addr(rmnet_dev->perm_addr);
....@@ -232,22 +245,31 @@
232245 int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
233246 struct rmnet_port *port,
234247 struct net_device *real_dev,
235
- struct rmnet_endpoint *ep)
248
+ struct rmnet_endpoint *ep,
249
+ struct netlink_ext_ack *extack)
250
+
236251 {
237252 struct rmnet_priv *priv = netdev_priv(rmnet_dev);
253
+ u32 headroom;
238254 int rc;
239255
240
- if (ep->egress_dev)
241
- return -EINVAL;
242
-
243
- if (rmnet_get_endpoint(port, id))
256
+ if (rmnet_get_endpoint(port, id)) {
257
+ NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
244258 return -EBUSY;
259
+ }
245260
246261 rmnet_dev->hw_features = NETIF_F_RXCSUM;
247262 rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
248263 rmnet_dev->hw_features |= NETIF_F_SG;
249264
250265 priv->real_dev = real_dev;
266
+
267
+ headroom = rmnet_vnd_headroom(port);
268
+
269
+ if (rmnet_vnd_change_mtu(rmnet_dev, real_dev->mtu - headroom)) {
270
+ NL_SET_ERR_MSG_MOD(extack, "Invalid MTU on real dev");
271
+ return -EINVAL;
272
+ }
251273
252274 rc = register_netdevice(rmnet_dev);
253275 if (!rc) {
....@@ -290,3 +312,45 @@
290312
291313 return 0;
292314 }
315
+
316
+int rmnet_vnd_validate_real_dev_mtu(struct net_device *real_dev)
317
+{
318
+ struct hlist_node *tmp_ep;
319
+ struct rmnet_endpoint *ep;
320
+ struct rmnet_port *port;
321
+ unsigned long bkt_ep;
322
+ u32 headroom;
323
+
324
+ port = rmnet_get_port_rtnl(real_dev);
325
+
326
+ headroom = rmnet_vnd_headroom(port);
327
+
328
+ hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
329
+ if (ep->egress_dev->mtu > (real_dev->mtu - headroom))
330
+ return -1;
331
+ }
332
+
333
+ return 0;
334
+}
335
+
336
+int rmnet_vnd_update_dev_mtu(struct rmnet_port *port,
337
+ struct net_device *real_dev)
338
+{
339
+ struct hlist_node *tmp_ep;
340
+ struct rmnet_endpoint *ep;
341
+ unsigned long bkt_ep;
342
+ u32 headroom;
343
+
344
+ headroom = rmnet_vnd_headroom(port);
345
+
346
+ hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
347
+ if (ep->egress_dev->mtu <= (real_dev->mtu - headroom))
348
+ continue;
349
+
350
+ if (rmnet_vnd_change_mtu(ep->egress_dev,
351
+ real_dev->mtu - headroom))
352
+ return -1;
353
+ }
354
+
355
+ return 0;
356
+}