blob: 28adb7f52a74510908c8465088ee0b7aa79d7409 [file] [log] [blame]
Subash Abhinov Kasiviswanathan0c26bab2019-01-15 19:42:37 -07001/* Copyright (c) 2013-2017, 2019 The Linux Foundation. All rights reserved.
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06002 *
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 * RMNET Data configuration engine
13 */
14
15#include <net/sock.h>
16#include <linux/module.h>
17#include <linux/netlink.h>
18#include <linux/netdevice.h>
19#include <linux/skbuff.h>
20#include <linux/spinlock.h>
21#include <linux/rmnet_data.h>
22#include <net/rmnet_config.h>
23#include "rmnet_data_config.h"
24#include "rmnet_data_handlers.h"
25#include "rmnet_data_vnd.h"
26#include "rmnet_data_private.h"
27#include "rmnet_data_trace.h"
Subash Abhinov Kasiviswanathan08fed022017-11-17 17:54:49 -070028#include "rmnet_map.h"
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -060029
30RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_CONFIG);
31
32/* Local Definitions and Declarations */
33static struct sock *nl_socket_handle;
34
35#ifndef RMNET_KERNEL_PRE_3_8
36static struct netlink_kernel_cfg rmnet_netlink_cfg = {
37 .input = rmnet_config_netlink_msg_handler
38};
39#endif
40
41static struct notifier_block rmnet_dev_notifier = {
42 .notifier_call = rmnet_config_notify_cb,
43 .next = 0,
44 .priority = 0
45};
46
47struct rmnet_free_vnd_work {
48 struct work_struct work;
49 int vnd_id[RMNET_DATA_MAX_VND];
50 int count;
51};
52
53/* Init and Cleanup */
54
55#ifdef RMNET_KERNEL_PRE_3_8
56static struct sock *_rmnet_config_start_netlink(void)
57{
58 return netlink_kernel_create(&init_net,
59 RMNET_NETLINK_PROTO,
60 0,
61 rmnet_config_netlink_msg_handler,
62 NULL,
63 THIS_MODULE);
64}
65#else
66static struct sock *_rmnet_config_start_netlink(void)
67{
68 return netlink_kernel_create(&init_net,
69 RMNET_NETLINK_PROTO,
70 &rmnet_netlink_cfg);
71}
72#endif /* RMNET_KERNEL_PRE_3_8 */
73
74/* rmnet_config_init() - Startup init
75 *
76 * Registers netlink protocol with kernel and opens socket. Netlink handler is
77 * registered with kernel.
78 */
79int rmnet_config_init(void)
80{
81 int rc;
82
83 nl_socket_handle = _rmnet_config_start_netlink();
84 if (!nl_socket_handle) {
85 LOGE("%s", "Failed to init netlink socket");
86 return RMNET_INIT_ERROR;
87 }
88
89 rc = register_netdevice_notifier(&rmnet_dev_notifier);
90 if (rc != 0) {
91 LOGE("Failed to register device notifier; rc=%d", rc);
92 /* TODO: Cleanup the nl socket */
93 return RMNET_INIT_ERROR;
94 }
95
96 return 0;
97}
98
99/* rmnet_config_exit() - Cleans up all netlink related resources */
100void rmnet_config_exit(void)
101{
102 int rc;
103
104 netlink_kernel_release(nl_socket_handle);
105 rc = unregister_netdevice_notifier(&rmnet_dev_notifier);
106 if (rc != 0)
107 LOGE("Failed to unregister device notifier; rc=%d", rc);
108}
109
110/* Helper Functions */
111
112/* _rmnet_is_physical_endpoint_associated() - Determines if device is associated
113 * @dev: Device to get check
114 *
115 * Compares device rx_handler callback pointer against known function
116 *
117 * Return:
118 * - 1 if associated
119 * - 0 if NOT associated
120 */
121static inline int _rmnet_is_physical_endpoint_associated(struct net_device *dev)
122{
123 rx_handler_func_t *rx_handler;
124
125 rx_handler = rcu_dereference(dev->rx_handler);
126
127 if (rx_handler == rmnet_rx_handler)
128 return 1;
129 else
130 return 0;
131}
132
133/* _rmnet_get_phys_ep_config() - Get physical ep config for an associated device
134 * @dev: Device to get endpoint configuration from
135 *
136 * Return:
137 * - pointer to configuration if successful
138 * - 0 (null) if device is not associated
139 */
140struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config
141 (struct net_device *dev)
142{
143 struct rmnet_phys_ep_conf_s *_rmnet_phys_ep_config;
144
145 if (_rmnet_is_physical_endpoint_associated(dev)) {
146 _rmnet_phys_ep_config = (struct rmnet_phys_ep_conf_s *)
147 rcu_dereference(dev->rx_handler_data);
148 if (_rmnet_phys_ep_config && _rmnet_phys_ep_config->config)
149 return (struct rmnet_phys_ep_config *)
150 _rmnet_phys_ep_config->config;
151 else
152 return 0;
153 } else {
154 return 0;
155 }
156}
157
158/* _rmnet_get_logical_ep() - Gets the logical end point configuration
159 * structure for a network device
160 * @dev: Device to get endpoint configuration from
161 * @config_id: Logical endpoint id on device
162 * Retrieves the logical_endpoint_config structure.
163 *
164 * Return:
165 * - End point configuration structure
166 * - NULL in case of an error
167 */
168struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep(struct net_device *dev,
169 int config_id)
170{
171 struct rmnet_phys_ep_config *config;
172 struct rmnet_logical_ep_conf_s *epconfig_l;
173
174 if (rmnet_vnd_is_vnd(dev)) {
175 epconfig_l = rmnet_vnd_get_le_config(dev);
176 } else {
177 config = _rmnet_get_phys_ep_config(dev);
178
179 if (!config)
180 return NULL;
181
182 if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
183 epconfig_l = &config->local_ep;
184 else
185 epconfig_l = &config->muxed_ep[config_id];
186 }
187
188 return epconfig_l;
189}
190
191/* Netlink Handler */
192static void _rmnet_netlink_set_link_egress_data_format
193 (struct rmnet_nl_msg_s *rmnet_header,
194 struct rmnet_nl_msg_s *resp_rmnet)
195{
196 struct net_device *dev;
197
198 if (!rmnet_header || !resp_rmnet)
199 return;
200
201 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
202 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
203
204 if (!dev) {
205 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
206 return;
207 }
208
209 resp_rmnet->return_code =
210 rmnet_set_egress_data_format(dev,
211 rmnet_header->data_format.flags,
212 rmnet_header->data_format.agg_size,
213 rmnet_header->data_format.agg_count
214 );
215 dev_put(dev);
216}
217
218static void _rmnet_netlink_set_link_ingress_data_format
219 (struct rmnet_nl_msg_s *rmnet_header,
220 struct rmnet_nl_msg_s *resp_rmnet)
221{
222 struct net_device *dev;
223
224 if (!rmnet_header || !resp_rmnet)
225 return;
226
227 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
228
229 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
230 if (!dev) {
231 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
232 return;
233 }
234
235 resp_rmnet->return_code = rmnet_set_ingress_data_format(
236 dev,
237 rmnet_header->data_format.flags,
238 rmnet_header->data_format.tail_spacing);
239 dev_put(dev);
240}
241
242static void _rmnet_netlink_set_logical_ep_config
243 (struct rmnet_nl_msg_s *rmnet_header,
244 struct rmnet_nl_msg_s *resp_rmnet)
245{
246 struct net_device *dev, *dev2;
247
248 if (!rmnet_header || !resp_rmnet)
249 return;
250
251 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
252 if (rmnet_header->local_ep_config.ep_id < -1 ||
253 rmnet_header->local_ep_config.ep_id > 254) {
254 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
255 return;
256 }
257
258 dev = dev_get_by_name(&init_net,
259 rmnet_header->local_ep_config.dev);
260
261 dev2 = dev_get_by_name(&init_net,
262 rmnet_header->local_ep_config.next_dev);
263
264 if (dev && dev2)
265 resp_rmnet->return_code =
266 rmnet_set_logical_endpoint_config(
267 dev,
268 rmnet_header->local_ep_config.ep_id,
269 rmnet_header->local_ep_config.operating_mode,
270 dev2);
271 else
272 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
273
274 if (dev)
275 dev_put(dev);
276 if (dev2)
277 dev_put(dev2);
278}
279
280static void _rmnet_netlink_unset_logical_ep_config
281 (struct rmnet_nl_msg_s *rmnet_header,
282 struct rmnet_nl_msg_s *resp_rmnet)
283{
284 struct net_device *dev;
285
286 if (!rmnet_header || !resp_rmnet)
287 return;
288
289 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
290 if (rmnet_header->local_ep_config.ep_id < -1 ||
291 rmnet_header->local_ep_config.ep_id > 254) {
292 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
293 return;
294 }
295
296 dev = dev_get_by_name(&init_net,
297 rmnet_header->local_ep_config.dev);
298
299 if (dev) {
300 resp_rmnet->return_code =
301 rmnet_unset_logical_endpoint_config(
302 dev,
303 rmnet_header->local_ep_config.ep_id);
304 dev_put(dev);
305 } else {
306 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
307 }
308}
309
310static void _rmnet_netlink_get_logical_ep_config
311 (struct rmnet_nl_msg_s *rmnet_header,
312 struct rmnet_nl_msg_s *resp_rmnet)
313{
314 struct net_device *dev;
315
316 if (!rmnet_header || !resp_rmnet)
317 return;
318
319 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
320 if (rmnet_header->local_ep_config.ep_id < -1 ||
321 rmnet_header->local_ep_config.ep_id > 254) {
322 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
323 return;
324 }
325
326 dev = dev_get_by_name(&init_net,
327 rmnet_header->local_ep_config.dev);
328
329 if (dev)
330 resp_rmnet->return_code =
331 rmnet_get_logical_endpoint_config(
332 dev,
333 rmnet_header->local_ep_config.ep_id,
334 &resp_rmnet->local_ep_config.operating_mode,
335 resp_rmnet->local_ep_config.next_dev,
336 sizeof(resp_rmnet->local_ep_config.next_dev));
337 else {
338 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
339 return;
340 }
341
342 if (resp_rmnet->return_code == RMNET_CONFIG_OK) {
343 /* Begin Data */
344 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
345 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
346 ->local_ep_config);
347 }
348 dev_put(dev);
349}
350
351static void _rmnet_netlink_associate_network_device
352 (struct rmnet_nl_msg_s *rmnet_header,
353 struct rmnet_nl_msg_s *resp_rmnet)
354{
355 struct net_device *dev;
356
357 if (!rmnet_header || !resp_rmnet)
358 return;
359
360 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
361
362 dev = dev_get_by_name(&init_net, rmnet_header->data);
363 if (!dev) {
364 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
365 return;
366 }
367
368 resp_rmnet->return_code = rmnet_associate_network_device(dev);
369 dev_put(dev);
370}
371
372static void _rmnet_netlink_unassociate_network_device
373 (struct rmnet_nl_msg_s *rmnet_header,
374 struct rmnet_nl_msg_s *resp_rmnet)
375{
376 struct net_device *dev;
377
378 if (!rmnet_header || !resp_rmnet)
379 return;
380
381 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
382
383 dev = dev_get_by_name(&init_net, rmnet_header->data);
384 if (!dev) {
385 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
386 return;
387 }
388
389 resp_rmnet->return_code = rmnet_unassociate_network_device(dev);
390 dev_put(dev);
391}
392
393static void _rmnet_netlink_get_network_device_associated
394 (struct rmnet_nl_msg_s *rmnet_header,
395 struct rmnet_nl_msg_s *resp_rmnet)
396{
397 struct net_device *dev;
398
399 if (!rmnet_header || !resp_rmnet)
400 return;
401
402 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
403
404 dev = dev_get_by_name(&init_net, rmnet_header->data);
405 if (!dev) {
406 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
407 return;
408 }
409
410 resp_rmnet->return_code = _rmnet_is_physical_endpoint_associated(dev);
411 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
412 dev_put(dev);
413}
414
415static void _rmnet_netlink_get_link_egress_data_format
416 (struct rmnet_nl_msg_s *rmnet_header,
417 struct rmnet_nl_msg_s *resp_rmnet)
418{
419 struct net_device *dev;
420 struct rmnet_phys_ep_config *config;
421
422 if (!rmnet_header || !resp_rmnet)
423 return;
424
425 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
426
427 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
428 if (!dev) {
429 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
430 return;
431 }
432
433 config = _rmnet_get_phys_ep_config(dev);
434 if (!config) {
435 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
436 dev_put(dev);
437 return;
438 }
439
440 /* Begin Data */
441 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
442 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
443 ->data_format);
444 resp_rmnet->data_format.flags = config->egress_data_format;
445 resp_rmnet->data_format.agg_count = config->egress_agg_count;
446 resp_rmnet->data_format.agg_size = config->egress_agg_size;
447 dev_put(dev);
448}
449
450static void _rmnet_netlink_get_link_ingress_data_format
451 (struct rmnet_nl_msg_s *rmnet_header,
452 struct rmnet_nl_msg_s *resp_rmnet)
453{
454 struct net_device *dev;
455 struct rmnet_phys_ep_config *config;
456
457 if (!rmnet_header || !resp_rmnet)
458 return;
459
460 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
461
462 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
463 if (!dev) {
464 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
465 return;
466 }
467
468 config = _rmnet_get_phys_ep_config(dev);
469 if (!config) {
470 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
471 dev_put(dev);
472 return;
473 }
474
475 /* Begin Data */
476 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
477 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
478 ->data_format);
479 resp_rmnet->data_format.flags = config->ingress_data_format;
480 resp_rmnet->data_format.tail_spacing = config->tail_spacing;
481 dev_put(dev);
482}
483
484static void _rmnet_netlink_get_vnd_name
485 (struct rmnet_nl_msg_s *rmnet_header,
486 struct rmnet_nl_msg_s *resp_rmnet)
487{
488 int r;
489
490 if (!rmnet_header || !resp_rmnet)
491 return;
492
493 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
494
495 r = rmnet_vnd_get_name(rmnet_header->vnd.id, resp_rmnet->vnd.vnd_name,
496 RMNET_MAX_STR_LEN);
497
498 if (r != 0) {
499 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
500 return;
501 }
502
503 /* Begin Data */
504 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
505 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)->vnd);
506}
507
508static void _rmnet_netlink_add_del_vnd_tc_flow
509 (u32 command,
510 struct rmnet_nl_msg_s *rmnet_header,
511 struct rmnet_nl_msg_s *resp_rmnet)
512{
513 u32 id;
514 u32 map_flow_id;
515 u32 tc_flow_id;
516
517 if (!rmnet_header || !resp_rmnet)
518 return;
519
520 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
521
522 id = rmnet_header->flow_control.id;
523 map_flow_id = rmnet_header->flow_control.map_flow_id;
524 tc_flow_id = rmnet_header->flow_control.tc_flow_id;
525
526 switch (command) {
527 case RMNET_NETLINK_ADD_VND_TC_FLOW:
528 resp_rmnet->return_code = rmnet_vnd_add_tc_flow(id,
529 map_flow_id,
530 tc_flow_id);
531 break;
532 case RMNET_NETLINK_DEL_VND_TC_FLOW:
533 resp_rmnet->return_code = rmnet_vnd_del_tc_flow(id,
534 map_flow_id,
535 tc_flow_id);
536 break;
537 default:
538 LOGM("Called with unhandled command %d", command);
539 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
540 break;
541 }
542}
543
544/* rmnet_config_netlink_msg_handler() - Netlink message handler callback
545 * @skb: Packet containing netlink messages
546 *
547 * Standard kernel-expected format for a netlink message handler. Processes SKBs
548 * which contain RmNet data specific netlink messages.
549 */
550void rmnet_config_netlink_msg_handler(struct sk_buff *skb)
551{
552 struct nlmsghdr *nlmsg_header, *resp_nlmsg;
553 struct rmnet_nl_msg_s *rmnet_header, *resp_rmnet;
554 int return_pid, response_data_length;
555 struct sk_buff *skb_response;
556
557 response_data_length = 0;
558 nlmsg_header = (struct nlmsghdr *)skb->data;
559 rmnet_header = (struct rmnet_nl_msg_s *)nlmsg_data(nlmsg_header);
560
Conner Huff2357fa52017-02-03 11:19:02 -0800561 if (!nlmsg_header->nlmsg_pid ||
562 (nlmsg_header->nlmsg_len < sizeof(struct nlmsghdr) +
563 sizeof(struct rmnet_nl_msg_s)))
564 return;
565
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600566 LOGL("Netlink message pid=%d, seq=%d, length=%d, rmnet_type=%d",
567 nlmsg_header->nlmsg_pid,
568 nlmsg_header->nlmsg_seq,
569 nlmsg_header->nlmsg_len,
570 rmnet_header->message_type);
571
572 return_pid = nlmsg_header->nlmsg_pid;
573
574 skb_response = nlmsg_new(sizeof(struct nlmsghdr)
575 + sizeof(struct rmnet_nl_msg_s),
576 GFP_KERNEL);
577
578 if (!skb_response) {
579 LOGH("%s", "Failed to allocate response buffer");
580 return;
581 }
582
583 resp_nlmsg = nlmsg_put(skb_response,
584 0,
585 nlmsg_header->nlmsg_seq,
586 NLMSG_DONE,
587 sizeof(struct rmnet_nl_msg_s),
588 0);
589
590 resp_rmnet = nlmsg_data(resp_nlmsg);
591
592 if (!resp_rmnet)
593 return;
594
595 resp_rmnet->message_type = rmnet_header->message_type;
596 rtnl_lock();
597 switch (rmnet_header->message_type) {
598 case RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE:
599 _rmnet_netlink_associate_network_device
600 (rmnet_header, resp_rmnet);
601 break;
602
603 case RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE:
604 _rmnet_netlink_unassociate_network_device
605 (rmnet_header, resp_rmnet);
606 break;
607
608 case RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED:
609 _rmnet_netlink_get_network_device_associated
610 (rmnet_header, resp_rmnet);
611 break;
612
613 case RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT:
614 _rmnet_netlink_set_link_egress_data_format
615 (rmnet_header, resp_rmnet);
616 break;
617
618 case RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT:
619 _rmnet_netlink_get_link_egress_data_format
620 (rmnet_header, resp_rmnet);
621 break;
622
623 case RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT:
624 _rmnet_netlink_set_link_ingress_data_format
625 (rmnet_header, resp_rmnet);
626 break;
627
628 case RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT:
629 _rmnet_netlink_get_link_ingress_data_format
630 (rmnet_header, resp_rmnet);
631 break;
632
633 case RMNET_NETLINK_SET_LOGICAL_EP_CONFIG:
634 _rmnet_netlink_set_logical_ep_config(rmnet_header, resp_rmnet);
635 break;
636
637 case RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG:
638 _rmnet_netlink_unset_logical_ep_config(rmnet_header,
639 resp_rmnet);
640 break;
641
642 case RMNET_NETLINK_GET_LOGICAL_EP_CONFIG:
643 _rmnet_netlink_get_logical_ep_config(rmnet_header, resp_rmnet);
644 break;
645
646 case RMNET_NETLINK_NEW_VND:
647 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
648 resp_rmnet->return_code =
649 rmnet_create_vnd(rmnet_header->vnd.id);
650 break;
651
652 case RMNET_NETLINK_NEW_VND_WITH_PREFIX:
653 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
654 resp_rmnet->return_code = rmnet_create_vnd_prefix(
655 rmnet_header->vnd.id,
656 rmnet_header->vnd.vnd_name);
657 break;
658
Subash Abhinov Kasiviswanathan58598632017-02-23 18:24:42 -0700659 case RMNET_NETLINK_NEW_VND_WITH_NAME:
660 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
661 resp_rmnet->return_code = rmnet_create_vnd_name(
662 rmnet_header->vnd.id,
663 rmnet_header->vnd.vnd_name);
664 break;
665
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600666 case RMNET_NETLINK_FREE_VND:
667 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
668 /* Please check rmnet_vnd_free_dev documentation regarding
669 * the below locking sequence
670 */
671 rtnl_unlock();
672 resp_rmnet->return_code = rmnet_free_vnd(rmnet_header->vnd.id);
673 rtnl_lock();
674 break;
675
676 case RMNET_NETLINK_GET_VND_NAME:
677 _rmnet_netlink_get_vnd_name(rmnet_header, resp_rmnet);
678 break;
679
680 case RMNET_NETLINK_DEL_VND_TC_FLOW:
681 case RMNET_NETLINK_ADD_VND_TC_FLOW:
682 _rmnet_netlink_add_del_vnd_tc_flow(rmnet_header->message_type,
683 rmnet_header,
684 resp_rmnet);
685 break;
686
687 default:
688 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
689 resp_rmnet->return_code = RMNET_CONFIG_UNKNOWN_MESSAGE;
690 break;
691 }
692 rtnl_unlock();
693 nlmsg_unicast(nl_socket_handle, skb_response, return_pid);
694 LOGD("%s", "Done processing command");
695}
696
697/* Configuration API */
698
699/* rmnet_unassociate_network_device() - Unassociate network device
700 * @dev: Device to unassociate
701 *
702 * Frees all structures generate for device. Unregisters rx_handler
703 * todo: needs to do some sanity verification first (is device in use, etc...)
704 *
705 * Return:
706 * - RMNET_CONFIG_OK if successful
707 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
708 * - RMNET_CONFIG_INVALID_REQUEST if device is not already associated
709 * - RMNET_CONFIG_DEVICE_IN_USE if device has logical ep that wasn't unset
710 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
711 */
712int rmnet_unassociate_network_device(struct net_device *dev)
713{
714 struct rmnet_phys_ep_conf_s *config;
715 int config_id = RMNET_LOCAL_LOGICAL_ENDPOINT;
716 struct rmnet_logical_ep_conf_s *epconfig_l;
717
718 ASSERT_RTNL();
719
720 LOGL("(%s);", dev->name);
721
722 if (!dev)
723 return RMNET_CONFIG_NO_SUCH_DEVICE;
724
725 if (!_rmnet_is_physical_endpoint_associated(dev))
726 return RMNET_CONFIG_INVALID_REQUEST;
727
728 for (; config_id < RMNET_DATA_MAX_LOGICAL_EP; config_id++) {
729 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
730 if (epconfig_l && epconfig_l->refcount)
731 return RMNET_CONFIG_DEVICE_IN_USE;
732 }
733
734 config = (struct rmnet_phys_ep_conf_s *)
735 rcu_dereference(dev->rx_handler_data);
736
737 if (!config)
738 return RMNET_CONFIG_UNKNOWN_ERROR;
739
740 kfree(config);
741
742 netdev_rx_handler_unregister(dev);
743
744 /* Explicitly release the reference from the device */
745 dev_put(dev);
746 trace_rmnet_unassociate(dev);
747 return RMNET_CONFIG_OK;
748}
749
750/* rmnet_set_ingress_data_format() - Set ingress data format on network device
751 * @dev: Device to ingress data format on
752 * @egress_data_format: 32-bit unsigned bitmask of ingress format
753 *
754 * Network device must already have association with RmNet Data driver
755 *
756 * Return:
757 * - RMNET_CONFIG_OK if successful
758 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
759 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
760 */
761int rmnet_set_ingress_data_format(struct net_device *dev,
762 u32 ingress_data_format,
763 uint8_t tail_spacing)
764{
765 struct rmnet_phys_ep_config *config;
766
767 ASSERT_RTNL();
768
769 LOGL("(%s,0x%08X);", dev->name, ingress_data_format);
770
771 if (!dev)
772 return RMNET_CONFIG_NO_SUCH_DEVICE;
773
774 config = _rmnet_get_phys_ep_config(dev);
775
776 if (!config)
777 return RMNET_CONFIG_INVALID_REQUEST;
778
779 config->ingress_data_format = ingress_data_format;
780 config->tail_spacing = tail_spacing;
781
782 return RMNET_CONFIG_OK;
783}
784
785/* rmnet_set_egress_data_format() - Set egress data format on network device
786 * @dev: Device to egress data format on
787 * @egress_data_format: 32-bit unsigned bitmask of egress format
788 *
789 * Network device must already have association with RmNet Data driver
790 * todo: Bounds check on agg_*
791 *
792 * Return:
793 * - RMNET_CONFIG_OK if successful
794 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
795 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
796 */
797int rmnet_set_egress_data_format(struct net_device *dev,
798 u32 egress_data_format,
799 u16 agg_size,
800 u16 agg_count)
801{
802 struct rmnet_phys_ep_config *config;
Subash Abhinov Kasiviswanathan0c26bab2019-01-15 19:42:37 -0700803 unsigned long flags;
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600804
805 ASSERT_RTNL();
806
807 LOGL("(%s,0x%08X, %d, %d);",
808 dev->name, egress_data_format, agg_size, agg_count);
809
810 if (!dev)
811 return RMNET_CONFIG_NO_SUCH_DEVICE;
812
813 config = _rmnet_get_phys_ep_config(dev);
814
815 if (!config)
816 return RMNET_CONFIG_UNKNOWN_ERROR;
817
818 config->egress_data_format = egress_data_format;
Subash Abhinov Kasiviswanathan0c26bab2019-01-15 19:42:37 -0700819
820 spin_lock_irqsave(&config->agg_lock, flags);
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600821 config->egress_agg_size = agg_size;
822 config->egress_agg_count = agg_count;
Subash Abhinov Kasiviswanathan0c26bab2019-01-15 19:42:37 -0700823 spin_unlock_irqrestore(&config->agg_lock, flags);
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600824
825 return RMNET_CONFIG_OK;
826}
827
828/* rmnet_associate_network_device() - Associate network device
829 * @dev: Device to register with RmNet data
830 *
831 * Typically used on physical network devices. Registers RX handler and private
832 * metadata structures.
833 *
834 * Return:
835 * - RMNET_CONFIG_OK if successful
836 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
837 * - RMNET_CONFIG_INVALID_REQUEST if the device to be associated is a vnd
838 * - RMNET_CONFIG_DEVICE_IN_USE if dev rx_handler is already filled
839 * - RMNET_CONFIG_DEVICE_IN_USE if netdev_rx_handler_register() fails
840 */
841int rmnet_associate_network_device(struct net_device *dev)
842{
843 struct rmnet_phys_ep_conf_s *config;
844 struct rmnet_phys_ep_config *conf;
845 int rc;
846
847 ASSERT_RTNL();
848
849 LOGL("(%s);\n", dev->name);
850
851 if (!dev)
852 return RMNET_CONFIG_NO_SUCH_DEVICE;
853
854 if (_rmnet_is_physical_endpoint_associated(dev)) {
855 LOGM("%s is already regestered", dev->name);
856 return RMNET_CONFIG_DEVICE_IN_USE;
857 }
858
859 if (rmnet_vnd_is_vnd(dev)) {
860 LOGM("%s is a vnd", dev->name);
861 return RMNET_CONFIG_INVALID_REQUEST;
862 }
863
864 config = kmalloc(sizeof(*config), GFP_ATOMIC);
865 conf = kmalloc(sizeof(*conf), GFP_ATOMIC);
866
867 if (!config || !conf)
868 return RMNET_CONFIG_NOMEM;
869
870 memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s));
871 memset(conf, 0, sizeof(struct rmnet_phys_ep_config));
872
873 config->config = conf;
874 conf->dev = dev;
875 spin_lock_init(&conf->agg_lock);
876 config->recycle = kfree_skb;
Subash Abhinov Kasiviswanathan08fed022017-11-17 17:54:49 -0700877 hrtimer_init(&conf->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
878 conf->hrtimer.function = rmnet_map_flush_packet_queue;
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600879 rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config);
880
881 if (rc) {
882 LOGM("netdev_rx_handler_register returns %d", rc);
883 kfree(config);
884 kfree(conf);
885 return RMNET_CONFIG_DEVICE_IN_USE;
886 }
887
888 /* Explicitly hold a reference to the device */
889 dev_hold(dev);
890 trace_rmnet_associate(dev);
891 return RMNET_CONFIG_OK;
892}
893
894/* _rmnet_set_logical_endpoint_config() - Set logical endpoing config on device
895 * @dev: Device to set endpoint configuration on
896 * @config_id: logical endpoint id on device
897 * @epconfig: endpoing configuration structure to set
898 *
899 * Return:
900 * - RMNET_CONFIG_OK if successful
901 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
902 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
903 * - RMNET_CONFIG_DEVICE_IN_USE if device already has a logical ep
904 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
905 */
906int _rmnet_set_logical_endpoint_config(struct net_device *dev,
907 int config_id,
908 struct rmnet_logical_ep_conf_s *epconfig)
909{
910 struct rmnet_logical_ep_conf_s *epconfig_l;
911
912 ASSERT_RTNL();
913
914 if (!dev)
915 return RMNET_CONFIG_NO_SUCH_DEVICE;
916
917 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
918 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
919 return RMNET_CONFIG_BAD_ARGUMENTS;
920
921 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
922
923 if (!epconfig_l)
924 return RMNET_CONFIG_UNKNOWN_ERROR;
925
926 if (epconfig_l->refcount)
927 return RMNET_CONFIG_DEVICE_IN_USE;
928
929 memcpy(epconfig_l, epconfig, sizeof(struct rmnet_logical_ep_conf_s));
930 if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
931 epconfig_l->mux_id = 0;
932 else
933 epconfig_l->mux_id = config_id;
934
935 /* Explicitly hold a reference to the egress device */
936 dev_hold(epconfig_l->egress_dev);
937 return RMNET_CONFIG_OK;
938}
939
940/* _rmnet_unset_logical_endpoint_config() - Un-set the logical endpoing config
941 * on device
942 * @dev: Device to set endpoint configuration on
943 * @config_id: logical endpoint id on device
944 *
945 * Return:
946 * - RMNET_CONFIG_OK if successful
947 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
948 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
949 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
950 */
951int _rmnet_unset_logical_endpoint_config(struct net_device *dev,
952 int config_id)
953{
954 struct rmnet_logical_ep_conf_s *epconfig_l = 0;
955
956 ASSERT_RTNL();
957
958 if (!dev)
959 return RMNET_CONFIG_NO_SUCH_DEVICE;
960
961 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
962 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
963 return RMNET_CONFIG_BAD_ARGUMENTS;
964
965 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
966
967 if (!epconfig_l || !epconfig_l->refcount)
968 return RMNET_CONFIG_NO_SUCH_DEVICE;
969
970 /* Explicitly release the reference from the egress device */
971 dev_put(epconfig_l->egress_dev);
972 memset(epconfig_l, 0, sizeof(struct rmnet_logical_ep_conf_s));
973
974 return RMNET_CONFIG_OK;
975}
976
977/* rmnet_set_logical_endpoint_config() - Set logical endpoint config on a device
978 * @dev: Device to set endpoint configuration on
979 * @config_id: logical endpoint id on device
980 * @rmnet_mode: endpoint mode. Values from: rmnet_config_endpoint_modes_e
981 * @egress_device: device node to forward packet to once done processing in
982 * ingress/egress handlers
983 *
984 * Creates a logical_endpoint_config structure and fills in the information from
985 * function arguments. Calls _rmnet_set_logical_endpoint_config() to finish
986 * configuration. Network device must already have association with RmNet Data
987 * driver
988 *
989 * Return:
990 * - RMNET_CONFIG_OK if successful
991 * - RMNET_CONFIG_BAD_EGRESS_DEVICE if egress device is null
992 * - RMNET_CONFIG_BAD_EGRESS_DEVICE if egress device is not handled by
993 * RmNet data module
994 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
995 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
996 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
997 */
998int rmnet_set_logical_endpoint_config(struct net_device *dev,
999 int config_id,
1000 u8 rmnet_mode,
1001 struct net_device *egress_dev)
1002{
1003 struct rmnet_logical_ep_conf_s epconfig;
1004
1005 LOGL("(%s, %d, %d, %s);",
1006 dev->name, config_id, rmnet_mode, egress_dev->name);
1007
1008 if (!egress_dev ||
1009 ((!_rmnet_is_physical_endpoint_associated(egress_dev)) &&
1010 (!rmnet_vnd_is_vnd(egress_dev)))) {
1011 return RMNET_CONFIG_BAD_EGRESS_DEVICE;
1012 }
1013
1014 memset(&epconfig, 0, sizeof(struct rmnet_logical_ep_conf_s));
1015 epconfig.refcount = 1;
1016 epconfig.rmnet_mode = rmnet_mode;
1017 epconfig.egress_dev = egress_dev;
1018
1019 return _rmnet_set_logical_endpoint_config(dev, config_id, &epconfig);
1020}
1021
1022/* rmnet_unset_logical_endpoint_config() - Un-set logical endpoing configuration
1023 * on a device
1024 * @dev: Device to set endpoint configuration on
1025 * @config_id: logical endpoint id on device
1026 *
1027 * Retrieves the logical_endpoint_config structure and frees the egress device.
1028 * Network device must already have association with RmNet Data driver
1029 *
1030 * Return:
1031 * - RMNET_CONFIG_OK if successful
1032 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
1033 * - RMNET_CONFIG_NO_SUCH_DEVICE device is not associated
1034 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
1035 */
1036int rmnet_unset_logical_endpoint_config(struct net_device *dev,
1037 int config_id)
1038{
1039 LOGL("(%s, %d);", dev->name, config_id);
1040
1041 if (!dev || ((!_rmnet_is_physical_endpoint_associated(dev)) &&
1042 (!rmnet_vnd_is_vnd(dev)))) {
1043 return RMNET_CONFIG_NO_SUCH_DEVICE;
1044 }
1045
1046 return _rmnet_unset_logical_endpoint_config(dev, config_id);
1047}
1048
1049/* rmnet_get_logical_endpoint_config() - Gets logical endpoing configuration
1050 * for a device
1051 * @dev: Device to get endpoint configuration on
1052 * @config_id: logical endpoint id on device
1053 * @rmnet_mode: (I/O) logical endpoint mode
1054 * @egress_dev_name: (I/O) logical endpoint egress device name
1055 * @egress_dev_name_size: The maximal size of the I/O egress_dev_name
1056 *
1057 * Retrieves the logical_endpoint_config structure.
1058 * Network device must already have association with RmNet Data driver
1059 *
1060 * Return:
1061 * - RMNET_CONFIG_OK if successful
1062 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
1063 * - RMNET_CONFIG_NO_SUCH_DEVICE device is not associated
1064 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range or
1065 * if the provided buffer size for egress dev name is too short
1066 */
1067int rmnet_get_logical_endpoint_config(struct net_device *dev,
1068 int config_id,
1069 u8 *rmnet_mode,
1070 u8 *egress_dev_name,
1071 size_t egress_dev_name_size)
1072{
1073 struct rmnet_logical_ep_conf_s *epconfig_l = 0;
1074 size_t strlcpy_res = 0;
1075
1076 LOGL("(%s, %d);", dev->name, config_id);
1077
1078 if (!egress_dev_name || !rmnet_mode)
1079 return RMNET_CONFIG_BAD_ARGUMENTS;
1080 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
1081 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
1082 return RMNET_CONFIG_BAD_ARGUMENTS;
1083
1084 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
1085
1086 if (!epconfig_l || !epconfig_l->refcount)
1087 return RMNET_CONFIG_NO_SUCH_DEVICE;
1088
1089 *rmnet_mode = epconfig_l->rmnet_mode;
1090
1091 strlcpy_res = strlcpy(egress_dev_name, epconfig_l->egress_dev->name,
1092 egress_dev_name_size);
1093
1094 if (strlcpy_res >= egress_dev_name_size)
1095 return RMNET_CONFIG_BAD_ARGUMENTS;
1096
1097 return RMNET_CONFIG_OK;
1098}
1099
1100/* rmnet_create_vnd() - Create virtual network device node
1101 * @id: RmNet virtual device node id
1102 *
1103 * Return:
1104 * - result of rmnet_vnd_create_dev()
1105 */
1106int rmnet_create_vnd(int id)
1107{
1108 struct net_device *dev;
1109
1110 ASSERT_RTNL();
1111 LOGL("(%d);", id);
Subash Abhinov Kasiviswanathan58598632017-02-23 18:24:42 -07001112 return rmnet_vnd_create_dev(id, &dev, NULL, 0);
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06001113}
1114
Subash Abhinov Kasiviswanathan58598632017-02-23 18:24:42 -07001115/* rmnet_create_vnd_prefix() - Create virtual network device node
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06001116 * @id: RmNet virtual device node id
1117 * @prefix: String prefix for device name
1118 *
1119 * Return:
1120 * - result of rmnet_vnd_create_dev()
1121 */
1122int rmnet_create_vnd_prefix(int id, const char *prefix)
1123{
1124 struct net_device *dev;
1125
1126 ASSERT_RTNL();
1127 LOGL("(%d, \"%s\");", id, prefix);
Subash Abhinov Kasiviswanathan58598632017-02-23 18:24:42 -07001128 return rmnet_vnd_create_dev(id, &dev, prefix, 0);
1129}
1130
1131/**
1132 * rmnet_create_vnd_name() - Create virtual network device node
1133 * @id: RmNet virtual device node id
1134 * @prefix: String prefix for device name
1135 *
1136 * Return:
1137 * - result of rmnet_vnd_create_dev()
1138 */
1139int rmnet_create_vnd_name(int id, const char *name)
1140{
1141 struct net_device *dev;
1142
1143 ASSERT_RTNL();
1144 LOGL("(%d, \"%s\");", id, name);
1145 return rmnet_vnd_create_dev(id, &dev, name, 1);
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06001146}
1147
1148/* rmnet_free_vnd() - Free virtual network device node
1149 * @id: RmNet virtual device node id
1150 *
1151 * Return:
1152 * - result of rmnet_vnd_free_dev()
1153 */
1154int rmnet_free_vnd(int id)
1155{
1156 LOGL("(%d);", id);
1157 return rmnet_vnd_free_dev(id);
1158}
1159
1160static void _rmnet_free_vnd_later(struct work_struct *work)
1161{
1162 int i;
1163 struct rmnet_free_vnd_work *fwork;
1164
1165 fwork = container_of(work, struct rmnet_free_vnd_work, work);
1166
1167 for (i = 0; i < fwork->count; i++)
1168 rmnet_free_vnd(fwork->vnd_id[i]);
1169 kfree(fwork);
1170}
1171
1172/* rmnet_force_unassociate_device() - Force a device to unassociate
1173 * @dev: Device to unassociate
1174 *
1175 * Return:
1176 * - void
1177 */
1178static void rmnet_force_unassociate_device(struct net_device *dev)
1179{
1180 int i, j;
1181 struct net_device *vndev;
Ashwanth Golic85bfbe2017-02-24 11:03:03 -07001182 struct rmnet_phys_ep_config *config;
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06001183 struct rmnet_logical_ep_conf_s *cfg;
1184 struct rmnet_free_vnd_work *vnd_work;
1185
1186 ASSERT_RTNL();
1187
1188 if (!dev)
1189 return;
1190
1191 if (!_rmnet_is_physical_endpoint_associated(dev)) {
1192 LOGM("%s", "Called on unassociated device, skipping");
1193 return;
1194 }
1195
1196 trace_rmnet_unregister_cb_clear_vnds(dev);
1197 vnd_work = kmalloc(sizeof(*vnd_work), GFP_KERNEL);
1198 if (!vnd_work) {
1199 LOGH("%s", "Out of Memory");
1200 return;
1201 }
1202 INIT_WORK(&vnd_work->work, _rmnet_free_vnd_later);
1203 vnd_work->count = 0;
1204
1205 /* Check the VNDs for offending mappings */
1206 for (i = 0, j = 0; i < RMNET_DATA_MAX_VND &&
1207 j < RMNET_DATA_MAX_VND; i++) {
1208 vndev = rmnet_vnd_get_by_id(i);
1209 if (!vndev) {
1210 LOGL("VND %d not in use; skipping", i);
1211 continue;
1212 }
1213 cfg = rmnet_vnd_get_le_config(vndev);
1214 if (!cfg) {
1215 LOGH("Got NULL config from VND %d", i);
1216 continue;
1217 }
1218 if (cfg->refcount && (cfg->egress_dev == dev)) {
1219 /* Make sure the device is down before clearing any of
1220 * the mappings. Otherwise we could see a potential
1221 * race condition if packets are actively being
1222 * transmitted.
1223 */
1224 dev_close(vndev);
1225 rmnet_unset_logical_endpoint_config
1226 (vndev, RMNET_LOCAL_LOGICAL_ENDPOINT);
1227 vnd_work->vnd_id[j] = i;
1228 j++;
1229 }
1230 }
1231 if (j > 0) {
1232 vnd_work->count = j;
1233 schedule_work(&vnd_work->work);
1234 } else {
1235 kfree(vnd_work);
1236 }
1237
Ashwanth Golic85bfbe2017-02-24 11:03:03 -07001238 config = _rmnet_get_phys_ep_config(dev);
1239
1240 if (config) {
Subash Abhinov Kasiviswanathan08fed022017-11-17 17:54:49 -07001241 unsigned long flags;
1242
1243 hrtimer_cancel(&config->hrtimer);
1244 spin_lock_irqsave(&config->agg_lock, flags);
1245 if (config->agg_state == RMNET_MAP_TXFER_SCHEDULED) {
1246 if (config->agg_skb) {
1247 kfree_skb(config->agg_skb);
1248 config->agg_skb = NULL;
1249 config->agg_count = 0;
1250 memset(&config->agg_time, 0,
1251 sizeof(struct timespec));
1252 }
1253 config->agg_state = RMNET_MAP_AGG_IDLE;
1254 }
1255 spin_unlock_irqrestore(&config->agg_lock, flags);
1256
Ashwanth Golic85bfbe2017-02-24 11:03:03 -07001257 cfg = &config->local_ep;
1258
1259 if (cfg && cfg->refcount)
1260 rmnet_unset_logical_endpoint_config
1261 (cfg->egress_dev, RMNET_LOCAL_LOGICAL_ENDPOINT);
1262 }
1263
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06001264 /* Clear the mappings on the phys ep */
1265 trace_rmnet_unregister_cb_clear_lepcs(dev);
1266 rmnet_unset_logical_endpoint_config(dev, RMNET_LOCAL_LOGICAL_ENDPOINT);
1267 for (i = 0; i < RMNET_DATA_MAX_LOGICAL_EP; i++)
1268 rmnet_unset_logical_endpoint_config(dev, i);
1269 rmnet_unassociate_network_device(dev);
1270}
1271
1272/* rmnet_config_notify_cb() - Callback for netdevice notifier chain
1273 * @nb: Notifier block data
1274 * @event: Netdevice notifier event ID
1275 * @data: Contains a net device for which we are getting notified
1276 *
1277 * Return:
1278 * - result of NOTIFY_DONE()
1279 */
1280int rmnet_config_notify_cb(struct notifier_block *nb,
1281 unsigned long event, void *data)
1282{
1283 struct net_device *dev = netdev_notifier_info_to_dev(data);
1284
1285 if (!dev)
1286 return NOTIFY_DONE;
1287
1288 LOGL("(..., %lu, %s)", event, dev->name);
1289
1290 switch (event) {
1291 case NETDEV_UNREGISTER_FINAL:
1292 case NETDEV_UNREGISTER:
1293 trace_rmnet_unregister_cb_entry(dev);
1294 LOGH("Kernel is trying to unregister %s", dev->name);
1295 rmnet_force_unassociate_device(dev);
1296 trace_rmnet_unregister_cb_exit(dev);
1297 break;
1298
1299 default:
1300 trace_rmnet_unregister_cb_unhandled(dev);
1301 LOGD("Unhandeled event [%lu]", event);
1302 break;
1303 }
1304
1305 return NOTIFY_DONE;
1306}