Merge "net: rmnet_data: adding support to GRO"
This commit is contained in:
commit
ea0e4d4ab4
|
@ -1795,6 +1795,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;
|
||||
|
||||
|
@ -2216,6 +2217,7 @@ extern gro_result_t napi_gro_receive(struct napi_struct *napi,
|
|||
extern void napi_gro_flush(struct napi_struct *napi, bool flush_old);
|
||||
extern struct sk_buff * napi_get_frags(struct napi_struct *napi);
|
||||
extern gro_result_t napi_gro_frags(struct napi_struct *napi);
|
||||
extern struct napi_struct *get_current_napi_context(void);
|
||||
|
||||
static inline void napi_free_frags(struct napi_struct *napi)
|
||||
{
|
||||
|
|
|
@ -4021,6 +4021,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
|
|||
{
|
||||
int work = 0;
|
||||
struct softnet_data *sd = container_of(napi, struct softnet_data, backlog);
|
||||
static int quota_changed;
|
||||
|
||||
#ifdef CONFIG_RPS
|
||||
/* Check if we have pending ipi, its better to send them now,
|
||||
|
@ -4043,7 +4044,14 @@ static int process_backlog(struct napi_struct *napi, int quota)
|
|||
local_irq_disable();
|
||||
input_queue_head_incr(sd);
|
||||
if (++work >= quota) {
|
||||
if (quota_changed) {
|
||||
local_irq_enable();
|
||||
napi_gro_flush(napi, false);
|
||||
local_irq_disable();
|
||||
quota_changed = 0;
|
||||
}
|
||||
local_irq_enable();
|
||||
sd->current_napi = NULL;
|
||||
return work;
|
||||
}
|
||||
}
|
||||
|
@ -4066,10 +4074,12 @@ static int process_backlog(struct napi_struct *napi, int quota)
|
|||
napi->state = 0;
|
||||
|
||||
quota = work + qlen;
|
||||
quota_changed = 1;
|
||||
}
|
||||
rps_unlock(sd);
|
||||
}
|
||||
local_irq_enable();
|
||||
sd->current_napi = NULL;
|
||||
|
||||
return work;
|
||||
}
|
||||
|
@ -4092,11 +4102,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);
|
||||
|
@ -4159,6 +4172,13 @@ 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 = &__get_cpu_var(softnet_data);
|
||||
|
@ -4200,6 +4220,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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -163,6 +163,20 @@ static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb,
|
|||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
|
||||
#ifdef NET_SKBUFF_DATA_USES_OFFSET
|
||||
static void rmnet_reset_mac_header(struct sk_buff *skb)
|
||||
{
|
||||
skb->mac_header = 0;
|
||||
skb->mac_len = 0;
|
||||
}
|
||||
#else
|
||||
static void rmnet_reset_mac_header(struct sk_buff *skb)
|
||||
{
|
||||
skb->mac_header = skb->data;
|
||||
skb->mac_len = 0;
|
||||
}
|
||||
#endif /*NET_SKBUFF_DATA_USES_OFFSET*/
|
||||
|
||||
/**
|
||||
* __rmnet_deliver_skb() - Deliver skb
|
||||
*
|
||||
|
@ -176,6 +190,9 @@ static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb,
|
|||
static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb,
|
||||
struct rmnet_logical_ep_conf_s *ep)
|
||||
{
|
||||
struct napi_struct *napi = NULL;
|
||||
gro_result_t gro_res;
|
||||
|
||||
trace___rmnet_deliver_skb(skb);
|
||||
switch (ep->rmnet_mode) {
|
||||
case RMNET_EPMODE_NONE:
|
||||
|
@ -193,7 +210,20 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb,
|
|||
|
||||
case RX_HANDLER_PASS:
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
netif_receive_skb(skb);
|
||||
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(skb->dev,
|
||||
gro_res);
|
||||
} else {
|
||||
WARN_ONCE(1, "current napi is NULL\n");
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
} else {
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
return RX_HANDLER_PASS;
|
||||
|
@ -304,7 +334,6 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb,
|
|||
skb_pull(skb, sizeof(struct rmnet_map_header_s));
|
||||
skb_trim(skb, len);
|
||||
__rmnet_data_set_skb_proto(skb);
|
||||
|
||||
return __rmnet_deliver_skb(skb, ep);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-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
|
||||
|
@ -305,6 +305,27 @@ DEFINE_EVENT(rmnet_physdev_action_template, rmnet_unassociate,
|
|||
|
||||
TP_ARGS(dev)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rmnet_gro_downlink,
|
||||
|
||||
TP_PROTO(struct net_device *dev, gro_result_t gro_res),
|
||||
|
||||
TP_ARGS(dev, gro_res),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, dev->name)
|
||||
__field(gro_result_t, res)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, dev->name);
|
||||
__entry->res = gro_res;
|
||||
),
|
||||
|
||||
TP_printk("GRO on dev=%s, res: %d",
|
||||
__get_str(name), __entry->res)
|
||||
)
|
||||
|
||||
#endif /* _RMNET_DATA_TRACE_H_ */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
|
@ -593,6 +593,8 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device,
|
|||
/* Configuring UL checksum offload on rmnet_data interfaces */
|
||||
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_IPV6_UDP_CSUM;
|
||||
/* Configuring GRO on rmnet_data interfaces */
|
||||
dev->hw_features = NETIF_F_GRO;
|
||||
}
|
||||
|
||||
rc = register_netdevice(dev);
|
||||
|
|
Loading…
Reference in New Issue