net: Add the get current NAPI context API

Commit 69235aa80090 ("net: Remove the get current NAPI context API")
removed the definition of get_current_napi_context() as rmnet_data
was no longer using it. However, the rmnet_data change to use its
NAPI in multiple contexts was prone to race in hotplug scenarios.

Add back get_current_napi_context() and current_napi to the
softnet_data struct

CRs-Fixed: 966095
Change-Id: I7cf1c5e39a5ccbd7a74a096b11efd179a4d0d034
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
[subashab@codeaurora.org: resolve trivial merge conflicts]
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
Subash Abhinov Kasiviswanathan 2016-01-25 18:09:54 -07:00 committed by David Keitel
parent 12fae71b18
commit 09a36c1368
2 changed files with 21 additions and 3 deletions

View file

@ -2518,6 +2518,7 @@ extern int netdev_flow_limit_table_len;
*/ */
struct softnet_data { struct softnet_data {
struct list_head poll_list; struct list_head poll_list;
struct napi_struct *current_napi;
struct sk_buff_head process_queue; struct sk_buff_head process_queue;
/* stats */ /* stats */
@ -3012,6 +3013,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi);
gro_result_t napi_gro_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_receive_by_type(__be16 type);
struct packet_offload *gro_find_complete_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) static inline void napi_free_frags(struct napi_struct *napi)
{ {

View file

@ -4557,8 +4557,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
local_irq_disable(); local_irq_disable();
input_queue_head_incr(sd); input_queue_head_incr(sd);
if (++work >= quota) { if (++work >= quota) {
local_irq_enable(); goto state_changed;
return work;
} }
} }
@ -4575,14 +4574,17 @@ static int process_backlog(struct napi_struct *napi, int quota)
napi->state = 0; napi->state = 0;
rps_unlock(sd); rps_unlock(sd);
break; goto state_changed;
} }
skb_queue_splice_tail_init(&sd->input_pkt_queue, skb_queue_splice_tail_init(&sd->input_pkt_queue,
&sd->process_queue); &sd->process_queue);
rps_unlock(sd); rps_unlock(sd);
} }
state_changed:
local_irq_enable(); local_irq_enable();
napi_gro_flush(napi, false);
sd->current_napi = NULL;
return work; return work;
} }
@ -4618,10 +4620,13 @@ EXPORT_SYMBOL(__napi_schedule_irqoff);
void __napi_complete(struct napi_struct *n) 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(!test_bit(NAPI_STATE_SCHED, &n->state));
list_del_init(&n->poll_list); list_del_init(&n->poll_list);
smp_mb__before_atomic(); smp_mb__before_atomic();
sd->current_napi = NULL;
clear_bit(NAPI_STATE_SCHED, &n->state); clear_bit(NAPI_STATE_SCHED, &n->state);
} }
EXPORT_SYMBOL(__napi_complete); EXPORT_SYMBOL(__napi_complete);
@ -4775,6 +4780,16 @@ void netif_napi_del(struct napi_struct *napi)
EXPORT_SYMBOL(netif_napi_del); EXPORT_SYMBOL(netif_napi_del);
static int napi_poll(struct napi_struct *n, struct list_head *repoll) static int napi_poll(struct napi_struct *n, struct list_head *repoll)
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)
{ {
void *have; void *have;
int work, weight; int work, weight;
@ -4793,6 +4808,7 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll)
*/ */
work = 0; work = 0;
if (test_bit(NAPI_STATE_SCHED, &n->state)) { if (test_bit(NAPI_STATE_SCHED, &n->state)) {
sd->current_napi = n;
work = n->poll(n, weight); work = n->poll(n, weight);
trace_napi_poll(n); trace_napi_poll(n);
} }