xref: /openbmc/linux/include/net/busy_poll.h (revision 37056719bba500d0d2b8216fdf641e5507ec9a0e)
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 
38545cd5e5SAlexander Duyck /*		0 - Reserved to indicate value not set
39545cd5e5SAlexander Duyck  *     1..NR_CPUS - Reserved for sender_cpu
40545cd5e5SAlexander Duyck  *  NR_CPUS+1..~0 - Region available for NAPI IDs
41545cd5e5SAlexander Duyck  */
42545cd5e5SAlexander Duyck #define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1))
43545cd5e5SAlexander Duyck 
44076bb0c8SEliezer Tamir static inline bool net_busy_loop_on(void)
45076bb0c8SEliezer Tamir {
4664b0dc51SEliezer Tamir 	return sysctl_net_busy_poll;
47076bb0c8SEliezer Tamir }
48076bb0c8SEliezer Tamir 
4921cb84c4SEric Dumazet static inline bool sk_can_busy_loop(const struct sock *sk)
50076bb0c8SEliezer Tamir {
51545cd5e5SAlexander Duyck 	return sk->sk_ll_usec && !signal_pending(current);
52076bb0c8SEliezer Tamir }
53076bb0c8SEliezer Tamir 
542b5cd0dfSAlexander Duyck void sk_busy_loop(struct sock *sk, int nonblock);
55076bb0c8SEliezer Tamir 
56e0d1095aSCong Wang #else /* CONFIG_NET_RX_BUSY_POLL */
57076bb0c8SEliezer Tamir static inline unsigned long net_busy_loop_on(void)
58076bb0c8SEliezer Tamir {
59076bb0c8SEliezer Tamir 	return 0;
60076bb0c8SEliezer Tamir }
61076bb0c8SEliezer Tamir 
62076bb0c8SEliezer Tamir static inline bool sk_can_busy_loop(struct sock *sk)
63076bb0c8SEliezer Tamir {
64076bb0c8SEliezer Tamir 	return false;
65076bb0c8SEliezer Tamir }
66076bb0c8SEliezer Tamir 
672b5cd0dfSAlexander Duyck static inline void sk_busy_loop(struct sock *sk, int nonblock)
68dfcefb0bSCong Wang {
69dfcefb0bSCong Wang }
70dfcefb0bSCong Wang 
71e0d1095aSCong Wang #endif /* CONFIG_NET_RX_BUSY_POLL */
72e68b6e50SEric Dumazet 
73*37056719SAlexander Duyck static inline unsigned long busy_loop_current_time(void)
74*37056719SAlexander Duyck {
75*37056719SAlexander Duyck #ifdef CONFIG_NET_RX_BUSY_POLL
76*37056719SAlexander Duyck 	return (unsigned long)(local_clock() >> 10);
77*37056719SAlexander Duyck #else
78*37056719SAlexander Duyck 	return 0;
79*37056719SAlexander Duyck #endif
80*37056719SAlexander Duyck }
81*37056719SAlexander Duyck 
82*37056719SAlexander Duyck /* in poll/select we use the global sysctl_net_ll_poll value */
83*37056719SAlexander Duyck static inline bool busy_loop_timeout(unsigned long start_time)
84*37056719SAlexander Duyck {
85*37056719SAlexander Duyck #ifdef CONFIG_NET_RX_BUSY_POLL
86*37056719SAlexander Duyck 	unsigned long bp_usec = READ_ONCE(sysctl_net_busy_poll);
87*37056719SAlexander Duyck 
88*37056719SAlexander Duyck 	if (bp_usec) {
89*37056719SAlexander Duyck 		unsigned long end_time = start_time + bp_usec;
90*37056719SAlexander Duyck 		unsigned long now = busy_loop_current_time();
91*37056719SAlexander Duyck 
92*37056719SAlexander Duyck 		return time_after(now, end_time);
93*37056719SAlexander Duyck 	}
94*37056719SAlexander Duyck #endif
95*37056719SAlexander Duyck 	return true;
96*37056719SAlexander Duyck }
97*37056719SAlexander Duyck 
98*37056719SAlexander Duyck static inline bool sk_busy_loop_timeout(struct sock *sk,
99*37056719SAlexander Duyck 					unsigned long start_time)
100*37056719SAlexander Duyck {
101*37056719SAlexander Duyck #ifdef CONFIG_NET_RX_BUSY_POLL
102*37056719SAlexander Duyck 	unsigned long bp_usec = READ_ONCE(sk->sk_ll_usec);
103*37056719SAlexander Duyck 
104*37056719SAlexander Duyck 	if (bp_usec) {
105*37056719SAlexander Duyck 		unsigned long end_time = start_time + bp_usec;
106*37056719SAlexander Duyck 		unsigned long now = busy_loop_current_time();
107*37056719SAlexander Duyck 
108*37056719SAlexander Duyck 		return time_after(now, end_time);
109*37056719SAlexander Duyck 	}
110*37056719SAlexander Duyck #endif
111*37056719SAlexander Duyck 	return true;
112*37056719SAlexander Duyck }
113*37056719SAlexander Duyck 
114d2e64dbbSAlexander Duyck /* used in the NIC receive handler to mark the skb */
115d2e64dbbSAlexander Duyck static inline void skb_mark_napi_id(struct sk_buff *skb,
116d2e64dbbSAlexander Duyck 				    struct napi_struct *napi)
117d2e64dbbSAlexander Duyck {
118d2e64dbbSAlexander Duyck #ifdef CONFIG_NET_RX_BUSY_POLL
119d2e64dbbSAlexander Duyck 	skb->napi_id = napi->napi_id;
120d2e64dbbSAlexander Duyck #endif
121d2e64dbbSAlexander Duyck }
122d2e64dbbSAlexander Duyck 
123e68b6e50SEric Dumazet /* used in the protocol hanlder to propagate the napi_id to the socket */
124e68b6e50SEric Dumazet static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb)
125e68b6e50SEric Dumazet {
126e68b6e50SEric Dumazet #ifdef CONFIG_NET_RX_BUSY_POLL
127e68b6e50SEric Dumazet 	sk->sk_napi_id = skb->napi_id;
128e68b6e50SEric Dumazet #endif
129e68b6e50SEric Dumazet }
130e68b6e50SEric Dumazet 
131e68b6e50SEric Dumazet /* variant used for unconnected sockets */
132e68b6e50SEric Dumazet static inline void sk_mark_napi_id_once(struct sock *sk,
133e68b6e50SEric Dumazet 					const struct sk_buff *skb)
134e68b6e50SEric Dumazet {
135e68b6e50SEric Dumazet #ifdef CONFIG_NET_RX_BUSY_POLL
136e68b6e50SEric Dumazet 	if (!sk->sk_napi_id)
137e68b6e50SEric Dumazet 		sk->sk_napi_id = skb->napi_id;
138e68b6e50SEric Dumazet #endif
139e68b6e50SEric Dumazet }
140e68b6e50SEric Dumazet 
1418b80cda5SEliezer Tamir #endif /* _LINUX_NET_BUSY_POLL_H */
142