net: rmnet_data: Add NAPI context for rmnet_data devices
This is needed so that we can pass the virtual netdevice NAPI struct to napi_gro_receive rather than relying on the current CPU NAPI context which can cause issues due to CPU hotplug. Change-Id: I41977c3a3a51212aa2fe092427b0ca924045b477 Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
parent
d6c7c80156
commit
a5bfaf0d40
3 changed files with 45 additions and 10 deletions
|
@ -212,14 +212,10 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb,
|
|||
skb->pkt_type = PACKET_HOST;
|
||||
rmnet_reset_mac_header(skb);
|
||||
if (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);
|
||||
}
|
||||
napi = rmnet_vnd_get_napi(skb->dev);
|
||||
napi_schedule(napi);
|
||||
gro_res = napi_gro_receive(napi, skb);
|
||||
trace_rmnet_gro_downlink(gro_res);
|
||||
} else {
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#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>
|
||||
|
@ -37,6 +38,9 @@ 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,
|
||||
|
@ -58,7 +62,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;
|
||||
|
@ -503,6 +507,19 @@ 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 ******************************************** */
|
||||
|
||||
/**
|
||||
|
@ -557,6 +574,7 @@ 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;
|
||||
|
@ -608,6 +626,10 @@ 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;
|
||||
}
|
||||
|
@ -651,6 +673,10 @@ 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;
|
||||
|
@ -1091,3 +1117,15 @@ 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);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2015, 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
|
||||
|
@ -37,5 +37,6 @@ 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…
Add table
Reference in a new issue