Loading include/linux/netdevice.h +2 −0 Original line number Diff line number Diff line Loading @@ -2330,6 +2330,7 @@ struct softnet_data { struct Qdisc *output_queue; struct Qdisc **output_queue_tailp; struct list_head poll_list; struct napi_struct *current_napi; struct sk_buff *completion_queue; struct sk_buff_head process_queue; Loading Loading @@ -2848,6 +2849,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi); gro_result_t napi_gro_frags(struct napi_struct *napi); struct packet_offload *gro_find_receive_by_type(__be16 type); struct packet_offload *gro_find_complete_by_type(__be16 type); extern struct napi_struct *get_current_napi_context(void); static inline void napi_free_frags(struct napi_struct *napi) { Loading net/core/dev.c +24 −4 Original line number Diff line number Diff line Loading @@ -4402,9 +4402,15 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) while (remsd) { struct softnet_data *next = remsd->rps_ipi_next; if (cpu_online(remsd->cpu)) if (cpu_online(remsd->cpu)) { smp_call_function_single_async(remsd->cpu, &remsd->csd); } else { pr_err("%s() cpu offline\n", __func__); rps_lock(remsd); remsd->backlog.state = 0; rps_unlock(remsd); } remsd = next; } } else Loading Loading @@ -4437,8 +4443,7 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_disable(); input_queue_head_incr(sd); if (++work >= quota) { local_irq_enable(); return work; goto state_changed; } } Loading @@ -4456,14 +4461,17 @@ static int process_backlog(struct napi_struct *napi, int quota) napi->state = 0; rps_unlock(sd); break; goto state_changed; } skb_queue_splice_tail_init(&sd->input_pkt_queue, &sd->process_queue); rps_unlock(sd); } state_changed: local_irq_enable(); napi_gro_flush(napi, false); sd->current_napi = NULL; return work; } Loading @@ -4486,11 +4494,14 @@ EXPORT_SYMBOL(__napi_schedule); void __napi_complete(struct napi_struct *n) { struct softnet_data *sd = &__get_cpu_var(softnet_data); BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); BUG_ON(n->gro_list); list_del(&n->poll_list); smp_mb__before_atomic(); sd->current_napi = NULL; clear_bit(NAPI_STATE_SCHED, &n->state); } EXPORT_SYMBOL(__napi_complete); Loading Loading @@ -4598,6 +4609,14 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); struct napi_struct *get_current_napi_context(void) { struct softnet_data *sd = &__get_cpu_var(softnet_data); return sd->current_napi; } EXPORT_SYMBOL(get_current_napi_context); static void net_rx_action(struct softirq_action *h) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); Loading Loading @@ -4639,6 +4658,7 @@ static void net_rx_action(struct softirq_action *h) */ work = 0; if (test_bit(NAPI_STATE_SCHED, &n->state)) { sd->current_napi = n; work = n->poll(n, weight); trace_napi_poll(n); } Loading net/rmnet_data/rmnet_data_handlers.c +6 −6 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -250,14 +250,14 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb, case RX_HANDLER_PASS: skb->pkt_type = PACKET_HOST; rmnet_reset_mac_header(skb); if (rmnet_check_skb_can_gro(skb)) { if (skb->dev->features & NETIF_F_GRO) { napi = rmnet_vnd_get_napi(skb->dev); napi_schedule(napi); if (rmnet_check_skb_can_gro(skb) && (skb->dev->features & NETIF_F_GRO)) { napi = get_current_napi_context(); if (napi != NULL) { gro_res = napi_gro_receive(napi, skb); trace_rmnet_gro_downlink(gro_res); } else { WARN_ONCE(1, "current napi is NULL\n"); netif_receive_skb(skb); } } else { Loading net/rmnet_data/rmnet_data_vnd.c +2 −40 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -19,7 +19,6 @@ #include <linux/rmnet_data.h> #include <linux/msm_rmnet.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/spinlock.h> #include <net/pkt_sched.h> Loading @@ -38,9 +37,6 @@ RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_VND); #define RMNET_MAP_FLOW_NUM_TC_HANDLE 3 #define RMNET_VND_UF_ACTION_ADD 0 #define RMNET_VND_UF_ACTION_DEL 1 #define RMNET_DATA_NAPI_WEIGHT 1 #define RMNET_DATA_NAPI_WORK 0 enum { RMNET_VND_UPDATE_FLOW_OK, RMNET_VND_UPDATE_FLOW_NO_ACTION, Loading @@ -62,7 +58,7 @@ struct rmnet_map_flow_mapping_s { struct rmnet_vnd_private_s { uint32_t qos_version; struct rmnet_logical_ep_conf_s local_ep; struct napi_struct napi; rwlock_t flow_map_lock; struct list_head flow_head; struct rmnet_map_flow_mapping_s root_flow; Loading Loading @@ -507,19 +503,6 @@ static void rmnet_vnd_setup(struct net_device *dev) INIT_LIST_HEAD(&dev_conf->flow_head); } /** * rmnet_data_napi_poll() - NAPI poll function * @napi: NAPI struct * * Called by net_rx_action() when NAPI is scheduled. Since we have already * queued packets to network stack, we just flush and return here. */ static int rmnet_data_napi_poll(struct napi_struct *napi, int budget) { napi_complete(napi); return RMNET_DATA_NAPI_WORK; } /* ***************** Exposed API ******************************************** */ /** Loading Loading @@ -574,7 +557,6 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, struct net_device *dev; char dev_prefix[IFNAMSIZ]; int p, rc = 0; struct napi_struct *n; if (id < 0 || id >= RMNET_DATA_MAX_VND) { *new_device = 0; Loading Loading @@ -634,10 +616,6 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, *new_device = dev; } n = rmnet_vnd_get_napi(dev); netif_napi_add(dev, n, rmnet_data_napi_poll, RMNET_DATA_NAPI_WEIGHT); napi_enable(n); LOGM("Registered device %s", dev->name); return rc; } Loading Loading @@ -681,10 +659,6 @@ int rmnet_vnd_free_dev(int id) rtnl_unlock(); if (dev) { struct napi_struct *n = rmnet_vnd_get_napi(dev); napi_disable(n); netif_napi_del(n); unregister_netdev(dev); free_netdev(dev); return 0; Loading Loading @@ -1125,15 +1099,3 @@ struct net_device *rmnet_vnd_get_by_id(int id) } return rmnet_devices[id]; } /** * rmnet_vnd_get_napi() - Get NAPI struct from the device * @dev: Virtual network device * * Return: * - napi struct corresponding to the netdevice */ struct napi_struct *rmnet_vnd_get_napi(struct net_device *dev) { return &(((struct rmnet_vnd_private_s *)netdev_priv(dev))->napi); } net/rmnet_data/rmnet_data_vnd.h +1 −2 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -37,6 +37,5 @@ int rmnet_vnd_del_tc_flow(uint32_t id, uint32_t map_flow, uint32_t tc_flow); int rmnet_vnd_init(void); void rmnet_vnd_exit(void); struct net_device *rmnet_vnd_get_by_id(int id); struct napi_struct *rmnet_vnd_get_napi(struct net_device *dev); #endif /* _RMNET_DATA_VND_H_ */ Loading
include/linux/netdevice.h +2 −0 Original line number Diff line number Diff line Loading @@ -2330,6 +2330,7 @@ struct softnet_data { struct Qdisc *output_queue; struct Qdisc **output_queue_tailp; struct list_head poll_list; struct napi_struct *current_napi; struct sk_buff *completion_queue; struct sk_buff_head process_queue; Loading Loading @@ -2848,6 +2849,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi); gro_result_t napi_gro_frags(struct napi_struct *napi); struct packet_offload *gro_find_receive_by_type(__be16 type); struct packet_offload *gro_find_complete_by_type(__be16 type); extern struct napi_struct *get_current_napi_context(void); static inline void napi_free_frags(struct napi_struct *napi) { Loading
net/core/dev.c +24 −4 Original line number Diff line number Diff line Loading @@ -4402,9 +4402,15 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) while (remsd) { struct softnet_data *next = remsd->rps_ipi_next; if (cpu_online(remsd->cpu)) if (cpu_online(remsd->cpu)) { smp_call_function_single_async(remsd->cpu, &remsd->csd); } else { pr_err("%s() cpu offline\n", __func__); rps_lock(remsd); remsd->backlog.state = 0; rps_unlock(remsd); } remsd = next; } } else Loading Loading @@ -4437,8 +4443,7 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_disable(); input_queue_head_incr(sd); if (++work >= quota) { local_irq_enable(); return work; goto state_changed; } } Loading @@ -4456,14 +4461,17 @@ static int process_backlog(struct napi_struct *napi, int quota) napi->state = 0; rps_unlock(sd); break; goto state_changed; } skb_queue_splice_tail_init(&sd->input_pkt_queue, &sd->process_queue); rps_unlock(sd); } state_changed: local_irq_enable(); napi_gro_flush(napi, false); sd->current_napi = NULL; return work; } Loading @@ -4486,11 +4494,14 @@ EXPORT_SYMBOL(__napi_schedule); void __napi_complete(struct napi_struct *n) { struct softnet_data *sd = &__get_cpu_var(softnet_data); BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); BUG_ON(n->gro_list); list_del(&n->poll_list); smp_mb__before_atomic(); sd->current_napi = NULL; clear_bit(NAPI_STATE_SCHED, &n->state); } EXPORT_SYMBOL(__napi_complete); Loading Loading @@ -4598,6 +4609,14 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); struct napi_struct *get_current_napi_context(void) { struct softnet_data *sd = &__get_cpu_var(softnet_data); return sd->current_napi; } EXPORT_SYMBOL(get_current_napi_context); static void net_rx_action(struct softirq_action *h) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); Loading Loading @@ -4639,6 +4658,7 @@ static void net_rx_action(struct softirq_action *h) */ work = 0; if (test_bit(NAPI_STATE_SCHED, &n->state)) { sd->current_napi = n; work = n->poll(n, weight); trace_napi_poll(n); } Loading
net/rmnet_data/rmnet_data_handlers.c +6 −6 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -250,14 +250,14 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb, case RX_HANDLER_PASS: skb->pkt_type = PACKET_HOST; rmnet_reset_mac_header(skb); if (rmnet_check_skb_can_gro(skb)) { if (skb->dev->features & NETIF_F_GRO) { napi = rmnet_vnd_get_napi(skb->dev); napi_schedule(napi); if (rmnet_check_skb_can_gro(skb) && (skb->dev->features & NETIF_F_GRO)) { napi = get_current_napi_context(); if (napi != NULL) { gro_res = napi_gro_receive(napi, skb); trace_rmnet_gro_downlink(gro_res); } else { WARN_ONCE(1, "current napi is NULL\n"); netif_receive_skb(skb); } } else { Loading
net/rmnet_data/rmnet_data_vnd.c +2 −40 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -19,7 +19,6 @@ #include <linux/rmnet_data.h> #include <linux/msm_rmnet.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/spinlock.h> #include <net/pkt_sched.h> Loading @@ -38,9 +37,6 @@ RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_VND); #define RMNET_MAP_FLOW_NUM_TC_HANDLE 3 #define RMNET_VND_UF_ACTION_ADD 0 #define RMNET_VND_UF_ACTION_DEL 1 #define RMNET_DATA_NAPI_WEIGHT 1 #define RMNET_DATA_NAPI_WORK 0 enum { RMNET_VND_UPDATE_FLOW_OK, RMNET_VND_UPDATE_FLOW_NO_ACTION, Loading @@ -62,7 +58,7 @@ struct rmnet_map_flow_mapping_s { struct rmnet_vnd_private_s { uint32_t qos_version; struct rmnet_logical_ep_conf_s local_ep; struct napi_struct napi; rwlock_t flow_map_lock; struct list_head flow_head; struct rmnet_map_flow_mapping_s root_flow; Loading Loading @@ -507,19 +503,6 @@ static void rmnet_vnd_setup(struct net_device *dev) INIT_LIST_HEAD(&dev_conf->flow_head); } /** * rmnet_data_napi_poll() - NAPI poll function * @napi: NAPI struct * * Called by net_rx_action() when NAPI is scheduled. Since we have already * queued packets to network stack, we just flush and return here. */ static int rmnet_data_napi_poll(struct napi_struct *napi, int budget) { napi_complete(napi); return RMNET_DATA_NAPI_WORK; } /* ***************** Exposed API ******************************************** */ /** Loading Loading @@ -574,7 +557,6 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, struct net_device *dev; char dev_prefix[IFNAMSIZ]; int p, rc = 0; struct napi_struct *n; if (id < 0 || id >= RMNET_DATA_MAX_VND) { *new_device = 0; Loading Loading @@ -634,10 +616,6 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, *new_device = dev; } n = rmnet_vnd_get_napi(dev); netif_napi_add(dev, n, rmnet_data_napi_poll, RMNET_DATA_NAPI_WEIGHT); napi_enable(n); LOGM("Registered device %s", dev->name); return rc; } Loading Loading @@ -681,10 +659,6 @@ int rmnet_vnd_free_dev(int id) rtnl_unlock(); if (dev) { struct napi_struct *n = rmnet_vnd_get_napi(dev); napi_disable(n); netif_napi_del(n); unregister_netdev(dev); free_netdev(dev); return 0; Loading Loading @@ -1125,15 +1099,3 @@ struct net_device *rmnet_vnd_get_by_id(int id) } return rmnet_devices[id]; } /** * rmnet_vnd_get_napi() - Get NAPI struct from the device * @dev: Virtual network device * * Return: * - napi struct corresponding to the netdevice */ struct napi_struct *rmnet_vnd_get_napi(struct net_device *dev) { return &(((struct rmnet_vnd_private_s *)netdev_priv(dev))->napi); }
net/rmnet_data/rmnet_data_vnd.h +1 −2 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -37,6 +37,5 @@ int rmnet_vnd_del_tc_flow(uint32_t id, uint32_t map_flow, uint32_t tc_flow); int rmnet_vnd_init(void); void rmnet_vnd_exit(void); struct net_device *rmnet_vnd_get_by_id(int id); struct napi_struct *rmnet_vnd_get_napi(struct net_device *dev); #endif /* _RMNET_DATA_VND_H_ */