1076bb0c8SEliezer Tamir /* 28b80cda5SEliezer Tamir * net busy poll support 3076bb0c8SEliezer Tamir * Copyright(c) 2013 Intel Corporation. 4076bb0c8SEliezer Tamir * 5076bb0c8SEliezer Tamir * This program is free software; you can redistribute it and/or modify it 6076bb0c8SEliezer Tamir * under the terms and conditions of the GNU General Public License, 7076bb0c8SEliezer Tamir * version 2, as published by the Free Software Foundation. 8076bb0c8SEliezer Tamir * 9076bb0c8SEliezer Tamir * This program is distributed in the hope it will be useful, but WITHOUT 10076bb0c8SEliezer Tamir * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11076bb0c8SEliezer Tamir * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12076bb0c8SEliezer Tamir * more details. 13076bb0c8SEliezer Tamir * 14076bb0c8SEliezer Tamir * You should have received a copy of the GNU General Public License along with 15076bb0c8SEliezer Tamir * this program; if not, write to the Free Software Foundation, Inc., 16076bb0c8SEliezer Tamir * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17076bb0c8SEliezer Tamir * 18076bb0c8SEliezer Tamir * Author: Eliezer Tamir 19076bb0c8SEliezer Tamir * 20076bb0c8SEliezer Tamir * Contact Information: 21076bb0c8SEliezer Tamir * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 22076bb0c8SEliezer Tamir */ 23076bb0c8SEliezer Tamir 248b80cda5SEliezer Tamir #ifndef _LINUX_NET_BUSY_POLL_H 258b80cda5SEliezer Tamir #define _LINUX_NET_BUSY_POLL_H 26076bb0c8SEliezer Tamir 27076bb0c8SEliezer Tamir #include <linux/netdevice.h> 28e6017571SIngo Molnar #include <linux/sched/clock.h> 29174cd4b1SIngo Molnar #include <linux/sched/signal.h> 30076bb0c8SEliezer Tamir #include <net/ip.h> 31076bb0c8SEliezer Tamir 32e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL 33076bb0c8SEliezer Tamir 34076bb0c8SEliezer Tamir struct napi_struct; 3564b0dc51SEliezer Tamir extern unsigned int sysctl_net_busy_read __read_mostly; 3664b0dc51SEliezer Tamir extern unsigned int sysctl_net_busy_poll __read_mostly; 37076bb0c8SEliezer Tamir 38*545cd5e5SAlexander Duyck /* 0 - Reserved to indicate value not set 39*545cd5e5SAlexander Duyck * 1..NR_CPUS - Reserved for sender_cpu 40*545cd5e5SAlexander Duyck * NR_CPUS+1..~0 - Region available for NAPI IDs 41*545cd5e5SAlexander Duyck */ 42*545cd5e5SAlexander Duyck #define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1)) 43*545cd5e5SAlexander Duyck 44076bb0c8SEliezer Tamir static inline bool net_busy_loop_on(void) 45076bb0c8SEliezer Tamir { 4664b0dc51SEliezer Tamir return sysctl_net_busy_poll; 47076bb0c8SEliezer Tamir } 48076bb0c8SEliezer Tamir 49076bb0c8SEliezer Tamir static inline u64 busy_loop_us_clock(void) 50076bb0c8SEliezer Tamir { 5137089834SPeter Zijlstra return local_clock() >> 10; 52076bb0c8SEliezer Tamir } 53076bb0c8SEliezer Tamir 54076bb0c8SEliezer Tamir static inline unsigned long sk_busy_loop_end_time(struct sock *sk) 55076bb0c8SEliezer Tamir { 56076bb0c8SEliezer Tamir return busy_loop_us_clock() + ACCESS_ONCE(sk->sk_ll_usec); 57076bb0c8SEliezer Tamir } 58076bb0c8SEliezer Tamir 59076bb0c8SEliezer Tamir /* in poll/select we use the global sysctl_net_ll_poll value */ 60076bb0c8SEliezer Tamir static inline unsigned long busy_loop_end_time(void) 61076bb0c8SEliezer Tamir { 6264b0dc51SEliezer Tamir return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_busy_poll); 63076bb0c8SEliezer Tamir } 64076bb0c8SEliezer Tamir 6521cb84c4SEric Dumazet static inline bool sk_can_busy_loop(const struct sock *sk) 66076bb0c8SEliezer Tamir { 67*545cd5e5SAlexander Duyck return sk->sk_ll_usec && !signal_pending(current); 68076bb0c8SEliezer Tamir } 69076bb0c8SEliezer Tamir 70076bb0c8SEliezer Tamir static inline bool busy_loop_timeout(unsigned long end_time) 71076bb0c8SEliezer Tamir { 72076bb0c8SEliezer Tamir unsigned long now = busy_loop_us_clock(); 73076bb0c8SEliezer Tamir 74076bb0c8SEliezer Tamir return time_after(now, end_time); 75076bb0c8SEliezer Tamir } 76076bb0c8SEliezer Tamir 7702d62e86SEric Dumazet bool sk_busy_loop(struct sock *sk, int nonblock); 78076bb0c8SEliezer Tamir 79076bb0c8SEliezer Tamir /* used in the NIC receive handler to mark the skb */ 808b80cda5SEliezer Tamir static inline void skb_mark_napi_id(struct sk_buff *skb, 818b80cda5SEliezer Tamir struct napi_struct *napi) 82076bb0c8SEliezer Tamir { 83076bb0c8SEliezer Tamir skb->napi_id = napi->napi_id; 84076bb0c8SEliezer Tamir } 85076bb0c8SEliezer Tamir 86076bb0c8SEliezer Tamir 87e0d1095aSCong Wang #else /* CONFIG_NET_RX_BUSY_POLL */ 88076bb0c8SEliezer Tamir static inline unsigned long net_busy_loop_on(void) 89076bb0c8SEliezer Tamir { 90076bb0c8SEliezer Tamir return 0; 91076bb0c8SEliezer Tamir } 92076bb0c8SEliezer Tamir 93076bb0c8SEliezer Tamir static inline unsigned long busy_loop_end_time(void) 94076bb0c8SEliezer Tamir { 95076bb0c8SEliezer Tamir return 0; 96076bb0c8SEliezer Tamir } 97076bb0c8SEliezer Tamir 98076bb0c8SEliezer Tamir static inline bool sk_can_busy_loop(struct sock *sk) 99076bb0c8SEliezer Tamir { 100076bb0c8SEliezer Tamir return false; 101076bb0c8SEliezer Tamir } 102076bb0c8SEliezer Tamir 1038b80cda5SEliezer Tamir static inline void skb_mark_napi_id(struct sk_buff *skb, 1048b80cda5SEliezer Tamir struct napi_struct *napi) 105076bb0c8SEliezer Tamir { 106076bb0c8SEliezer Tamir } 107076bb0c8SEliezer Tamir 108076bb0c8SEliezer Tamir static inline bool busy_loop_timeout(unsigned long end_time) 109076bb0c8SEliezer Tamir { 110076bb0c8SEliezer Tamir return true; 111076bb0c8SEliezer Tamir } 112076bb0c8SEliezer Tamir 113dfcefb0bSCong Wang static inline bool sk_busy_loop(struct sock *sk, int nonblock) 114dfcefb0bSCong Wang { 115dfcefb0bSCong Wang return false; 116dfcefb0bSCong Wang } 117dfcefb0bSCong Wang 118e0d1095aSCong Wang #endif /* CONFIG_NET_RX_BUSY_POLL */ 119e68b6e50SEric Dumazet 120e68b6e50SEric Dumazet /* used in the protocol hanlder to propagate the napi_id to the socket */ 121e68b6e50SEric Dumazet static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) 122e68b6e50SEric Dumazet { 123e68b6e50SEric Dumazet #ifdef CONFIG_NET_RX_BUSY_POLL 124e68b6e50SEric Dumazet sk->sk_napi_id = skb->napi_id; 125e68b6e50SEric Dumazet #endif 126e68b6e50SEric Dumazet } 127e68b6e50SEric Dumazet 128e68b6e50SEric Dumazet /* variant used for unconnected sockets */ 129e68b6e50SEric Dumazet static inline void sk_mark_napi_id_once(struct sock *sk, 130e68b6e50SEric Dumazet const struct sk_buff *skb) 131e68b6e50SEric Dumazet { 132e68b6e50SEric Dumazet #ifdef CONFIG_NET_RX_BUSY_POLL 133e68b6e50SEric Dumazet if (!sk->sk_napi_id) 134e68b6e50SEric Dumazet sk->sk_napi_id = skb->napi_id; 135e68b6e50SEric Dumazet #endif 136e68b6e50SEric Dumazet } 137e68b6e50SEric Dumazet 1388b80cda5SEliezer Tamir #endif /* _LINUX_NET_BUSY_POLL_H */ 139