diff options
Diffstat (limited to 'include/linux/netpoll.h')
| -rw-r--r-- | include/linux/netpoll.h | 42 | 
1 files changed, 24 insertions, 18 deletions
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 28f5389c924b..66d5379c305e 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -23,6 +23,7 @@ struct netpoll {  	u8 remote_mac[ETH_ALEN];  	struct list_head rx; /* rx_np list element */ +	struct rcu_head rcu;  };  struct netpoll_info { @@ -38,28 +39,40 @@ struct netpoll_info {  	struct delayed_work tx_work;  	struct netpoll *netpoll; +	struct rcu_head rcu;  };  void netpoll_send_udp(struct netpoll *np, const char *msg, int len);  void netpoll_print_options(struct netpoll *np);  int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev); +int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp);  int netpoll_setup(struct netpoll *np);  int netpoll_trap(void);  void netpoll_set_trap(int trap);  void __netpoll_cleanup(struct netpoll *np); +void __netpoll_free_rcu(struct netpoll *np);  void netpoll_cleanup(struct netpoll *np); -int __netpoll_rx(struct sk_buff *skb); +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo);  void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  			     struct net_device *dev);  static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)  { +	unsigned long flags; +	local_irq_save(flags);  	netpoll_send_skb_on_dev(np, skb, np->dev); +	local_irq_restore(flags);  }  #ifdef CONFIG_NETPOLL +static inline bool netpoll_rx_on(struct sk_buff *skb) +{ +	struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); + +	return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); +} +  static inline bool netpoll_rx(struct sk_buff *skb)  {  	struct netpoll_info *npinfo; @@ -67,14 +80,14 @@ static inline bool netpoll_rx(struct sk_buff *skb)  	bool ret = false;  	local_irq_save(flags); -	npinfo = rcu_dereference_bh(skb->dev->npinfo); -	if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) +	if (!netpoll_rx_on(skb))  		goto out; +	npinfo = rcu_dereference_bh(skb->dev->npinfo);  	spin_lock(&npinfo->rx_lock);  	/* check rx_flags again with the lock held */ -	if (npinfo->rx_flags && __netpoll_rx(skb)) +	if (npinfo->rx_flags && __netpoll_rx(skb, npinfo))  		ret = true;  	spin_unlock(&npinfo->rx_lock); @@ -83,13 +96,6 @@ out:  	return ret;  } -static inline int netpoll_rx_on(struct sk_buff *skb) -{ -	struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - -	return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); -} -  static inline int netpoll_receive_skb(struct sk_buff *skb)  {  	if (!list_empty(&skb->dev->napi_list)) @@ -119,7 +125,7 @@ static inline void netpoll_poll_unlock(void *have)  	}  } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev)  {  	return irqs_disabled();  } @@ -127,11 +133,11 @@ static inline int netpoll_tx_running(struct net_device *dev)  #else  static inline bool netpoll_rx(struct sk_buff *skb)  { -	return 0; +	return false;  } -static inline int netpoll_rx_on(struct sk_buff *skb) +static inline bool netpoll_rx_on(struct sk_buff *skb)  { -	return 0; +	return false;  }  static inline int netpoll_receive_skb(struct sk_buff *skb)  { @@ -147,9 +153,9 @@ static inline void netpoll_poll_unlock(void *have)  static inline void netpoll_netdev_init(struct net_device *dev)  {  } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev)  { -	return 0; +	return false;  }  #endif  |