Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / drivers / net / ethernet / qualcomm / rmnet / rmnet_vnd.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
3  *
4  * RMNET Data virtual network driver
5  */
6
7 #include <linux/etherdevice.h>
8 #include <linux/ethtool.h>
9 #include <linux/if_arp.h>
10 #include <net/pkt_sched.h>
11 #include "rmnet_config.h"
12 #include "rmnet_handlers.h"
13 #include "rmnet_private.h"
14 #include "rmnet_map.h"
15 #include "rmnet_vnd.h"
16
17 /* RX/TX Fixup */
18
19 void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev)
20 {
21         struct rmnet_priv *priv = netdev_priv(dev);
22         struct rmnet_pcpu_stats *pcpu_ptr;
23
24         pcpu_ptr = this_cpu_ptr(priv->pcpu_stats);
25
26         u64_stats_update_begin(&pcpu_ptr->syncp);
27         pcpu_ptr->stats.rx_pkts++;
28         pcpu_ptr->stats.rx_bytes += skb->len;
29         u64_stats_update_end(&pcpu_ptr->syncp);
30 }
31
32 void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev)
33 {
34         struct rmnet_priv *priv = netdev_priv(dev);
35         struct rmnet_pcpu_stats *pcpu_ptr;
36
37         pcpu_ptr = this_cpu_ptr(priv->pcpu_stats);
38
39         u64_stats_update_begin(&pcpu_ptr->syncp);
40         pcpu_ptr->stats.tx_pkts++;
41         pcpu_ptr->stats.tx_bytes += skb->len;
42         u64_stats_update_end(&pcpu_ptr->syncp);
43 }
44
45 /* Network Device Operations */
46
47 static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
48                                         struct net_device *dev)
49 {
50         struct rmnet_priv *priv;
51
52         priv = netdev_priv(dev);
53         if (priv->real_dev) {
54                 rmnet_egress_handler(skb);
55         } else {
56                 this_cpu_inc(priv->pcpu_stats->stats.tx_drops);
57                 kfree_skb(skb);
58         }
59         return NETDEV_TX_OK;
60 }
61
62 static int rmnet_vnd_headroom(struct rmnet_port *port)
63 {
64         u32 headroom;
65
66         headroom = sizeof(struct rmnet_map_header);
67
68         if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4)
69                 headroom += sizeof(struct rmnet_map_ul_csum_header);
70
71         return headroom;
72 }
73
74 static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu)
75 {
76         struct rmnet_priv *priv = netdev_priv(rmnet_dev);
77         struct rmnet_port *port;
78         u32 headroom;
79
80         port = rmnet_get_port_rtnl(priv->real_dev);
81
82         headroom = rmnet_vnd_headroom(port);
83
84         if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE ||
85             new_mtu > (priv->real_dev->mtu - headroom))
86                 return -EINVAL;
87
88         rmnet_dev->mtu = new_mtu;
89         return 0;
90 }
91
92 static int rmnet_vnd_get_iflink(const struct net_device *dev)
93 {
94         struct rmnet_priv *priv = netdev_priv(dev);
95
96         return priv->real_dev->ifindex;
97 }
98
99 static int rmnet_vnd_init(struct net_device *dev)
100 {
101         struct rmnet_priv *priv = netdev_priv(dev);
102         int err;
103
104         priv->pcpu_stats = alloc_percpu(struct rmnet_pcpu_stats);
105         if (!priv->pcpu_stats)
106                 return -ENOMEM;
107
108         err = gro_cells_init(&priv->gro_cells, dev);
109         if (err) {
110                 free_percpu(priv->pcpu_stats);
111                 return err;
112         }
113
114         return 0;
115 }
116
117 static void rmnet_vnd_uninit(struct net_device *dev)
118 {
119         struct rmnet_priv *priv = netdev_priv(dev);
120
121         gro_cells_destroy(&priv->gro_cells);
122         free_percpu(priv->pcpu_stats);
123 }
124
125 static void rmnet_get_stats64(struct net_device *dev,
126                               struct rtnl_link_stats64 *s)
127 {
128         struct rmnet_priv *priv = netdev_priv(dev);
129         struct rmnet_vnd_stats total_stats = { };
130         struct rmnet_pcpu_stats *pcpu_ptr;
131         struct rmnet_vnd_stats snapshot;
132         unsigned int cpu, start;
133
134         for_each_possible_cpu(cpu) {
135                 pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu);
136
137                 do {
138                         start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp);
139                         snapshot = pcpu_ptr->stats;     /* struct assignment */
140                 } while (u64_stats_fetch_retry_irq(&pcpu_ptr->syncp, start));
141
142                 total_stats.rx_pkts += snapshot.rx_pkts;
143                 total_stats.rx_bytes += snapshot.rx_bytes;
144                 total_stats.tx_pkts += snapshot.tx_pkts;
145                 total_stats.tx_bytes += snapshot.tx_bytes;
146                 total_stats.tx_drops += snapshot.tx_drops;
147         }
148
149         s->rx_packets = total_stats.rx_pkts;
150         s->rx_bytes = total_stats.rx_bytes;
151         s->tx_packets = total_stats.tx_pkts;
152         s->tx_bytes = total_stats.tx_bytes;
153         s->tx_dropped = total_stats.tx_drops;
154 }
155
156 static const struct net_device_ops rmnet_vnd_ops = {
157         .ndo_start_xmit = rmnet_vnd_start_xmit,
158         .ndo_change_mtu = rmnet_vnd_change_mtu,
159         .ndo_get_iflink = rmnet_vnd_get_iflink,
160         .ndo_add_slave  = rmnet_add_bridge,
161         .ndo_del_slave  = rmnet_del_bridge,
162         .ndo_init       = rmnet_vnd_init,
163         .ndo_uninit     = rmnet_vnd_uninit,
164         .ndo_get_stats64 = rmnet_get_stats64,
165 };
166
167 static const char rmnet_gstrings_stats[][ETH_GSTRING_LEN] = {
168         "Checksum ok",
169         "Checksum valid bit not set",
170         "Checksum validation failed",
171         "Checksum error bad buffer",
172         "Checksum error bad ip version",
173         "Checksum error bad transport",
174         "Checksum skipped on ip fragment",
175         "Checksum skipped",
176         "Checksum computed in software",
177 };
178
179 static void rmnet_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
180 {
181         switch (stringset) {
182         case ETH_SS_STATS:
183                 memcpy(buf, &rmnet_gstrings_stats,
184                        sizeof(rmnet_gstrings_stats));
185                 break;
186         }
187 }
188
189 static int rmnet_get_sset_count(struct net_device *dev, int sset)
190 {
191         switch (sset) {
192         case ETH_SS_STATS:
193                 return ARRAY_SIZE(rmnet_gstrings_stats);
194         default:
195                 return -EOPNOTSUPP;
196         }
197 }
198
199 static void rmnet_get_ethtool_stats(struct net_device *dev,
200                                     struct ethtool_stats *stats, u64 *data)
201 {
202         struct rmnet_priv *priv = netdev_priv(dev);
203         struct rmnet_priv_stats *st = &priv->stats;
204
205         if (!data)
206                 return;
207
208         memcpy(data, st, ARRAY_SIZE(rmnet_gstrings_stats) * sizeof(u64));
209 }
210
211 static const struct ethtool_ops rmnet_ethtool_ops = {
212         .get_ethtool_stats = rmnet_get_ethtool_stats,
213         .get_strings = rmnet_get_strings,
214         .get_sset_count = rmnet_get_sset_count,
215 };
216
217 /* Called by kernel whenever a new rmnet<n> device is created. Sets MTU,
218  * flags, ARP type, needed headroom, etc...
219  */
220 void rmnet_vnd_setup(struct net_device *rmnet_dev)
221 {
222         rmnet_dev->netdev_ops = &rmnet_vnd_ops;
223         rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE;
224         rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM;
225         eth_random_addr(rmnet_dev->dev_addr);
226         rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN;
227
228         /* Raw IP mode */
229         rmnet_dev->header_ops = NULL;  /* No header */
230         rmnet_dev->type = ARPHRD_RAWIP;
231         rmnet_dev->hard_header_len = 0;
232         rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
233
234         rmnet_dev->needs_free_netdev = true;
235         rmnet_dev->ethtool_ops = &rmnet_ethtool_ops;
236
237         rmnet_dev->features |= NETIF_F_LLTX;
238
239         /* This perm addr will be used as interface identifier by IPv6 */
240         rmnet_dev->addr_assign_type = NET_ADDR_RANDOM;
241         eth_random_addr(rmnet_dev->perm_addr);
242 }
243
244 /* Exposed API */
245
246 int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
247                       struct rmnet_port *port,
248                       struct net_device *real_dev,
249                       struct rmnet_endpoint *ep,
250                       struct netlink_ext_ack *extack)
251
252 {
253         struct rmnet_priv *priv = netdev_priv(rmnet_dev);
254         u32 headroom;
255         int rc;
256
257         if (rmnet_get_endpoint(port, id)) {
258                 NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
259                 return -EBUSY;
260         }
261
262         rmnet_dev->hw_features = NETIF_F_RXCSUM;
263         rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
264         rmnet_dev->hw_features |= NETIF_F_SG;
265
266         priv->real_dev = real_dev;
267
268         headroom = rmnet_vnd_headroom(port);
269
270         if (rmnet_vnd_change_mtu(rmnet_dev, real_dev->mtu - headroom)) {
271                 NL_SET_ERR_MSG_MOD(extack, "Invalid MTU on real dev");
272                 return -EINVAL;
273         }
274
275         rc = register_netdevice(rmnet_dev);
276         if (!rc) {
277                 ep->egress_dev = rmnet_dev;
278                 ep->mux_id = id;
279                 port->nr_rmnet_devs++;
280
281                 rmnet_dev->rtnl_link_ops = &rmnet_link_ops;
282
283                 priv->mux_id = id;
284
285                 netdev_dbg(rmnet_dev, "rmnet dev created\n");
286         }
287
288         return rc;
289 }
290
291 int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
292                       struct rmnet_endpoint *ep)
293 {
294         if (id >= RMNET_MAX_LOGICAL_EP || !ep->egress_dev)
295                 return -EINVAL;
296
297         ep->egress_dev = NULL;
298         port->nr_rmnet_devs--;
299         return 0;
300 }
301
302 int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
303 {
304         netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
305         /* Although we expect similar number of enable/disable
306          * commands, optimize for the disable. That is more
307          * latency sensitive than enable
308          */
309         if (unlikely(enable))
310                 netif_wake_queue(rmnet_dev);
311         else
312                 netif_stop_queue(rmnet_dev);
313
314         return 0;
315 }
316
317 int rmnet_vnd_validate_real_dev_mtu(struct net_device *real_dev)
318 {
319         struct hlist_node *tmp_ep;
320         struct rmnet_endpoint *ep;
321         struct rmnet_port *port;
322         unsigned long bkt_ep;
323         u32 headroom;
324
325         port = rmnet_get_port_rtnl(real_dev);
326
327         headroom = rmnet_vnd_headroom(port);
328
329         hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
330                 if (ep->egress_dev->mtu > (real_dev->mtu - headroom))
331                         return -1;
332         }
333
334         return 0;
335 }
336
337 int rmnet_vnd_update_dev_mtu(struct rmnet_port *port,
338                              struct net_device *real_dev)
339 {
340         struct hlist_node *tmp_ep;
341         struct rmnet_endpoint *ep;
342         unsigned long bkt_ep;
343         u32 headroom;
344
345         headroom = rmnet_vnd_headroom(port);
346
347         hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
348                 if (ep->egress_dev->mtu <= (real_dev->mtu - headroom))
349                         continue;
350
351                 if (rmnet_vnd_change_mtu(ep->egress_dev,
352                                          real_dev->mtu - headroom))
353                         return -1;
354         }
355
356         return 0;
357 }