]>
Commit | Line | Data |
---|---|---|
06021292 | 1 | /* |
8b80cda5 | 2 | * net busy poll support |
06021292 ET |
3 | * Copyright(c) 2013 Intel Corporation. |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms and conditions of the GNU General Public License, | |
7 | * version 2, as published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | * | |
18 | * Author: Eliezer Tamir | |
19 | * | |
20 | * Contact Information: | |
21 | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | |
22 | */ | |
23 | ||
8b80cda5 ET |
24 | #ifndef _LINUX_NET_BUSY_POLL_H |
25 | #define _LINUX_NET_BUSY_POLL_H | |
06021292 ET |
26 | |
27 | #include <linux/netdevice.h> | |
e6017571 | 28 | #include <linux/sched/clock.h> |
174cd4b1 | 29 | #include <linux/sched/signal.h> |
06021292 ET |
30 | #include <net/ip.h> |
31 | ||
545cd5e5 AD |
32 | /* 0 - Reserved to indicate value not set |
33 | * 1..NR_CPUS - Reserved for sender_cpu | |
34 | * NR_CPUS+1..~0 - Region available for NAPI IDs | |
35 | */ | |
36 | #define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1)) | |
37 | ||
e4dde412 DB |
38 | #ifdef CONFIG_NET_RX_BUSY_POLL |
39 | ||
40 | struct napi_struct; | |
41 | extern unsigned int sysctl_net_busy_read __read_mostly; | |
42 | extern unsigned int sysctl_net_busy_poll __read_mostly; | |
43 | ||
cbf55001 | 44 | static inline bool net_busy_loop_on(void) |
91e2fd33 | 45 | { |
64b0dc51 | 46 | return sysctl_net_busy_poll; |
91e2fd33 ET |
47 | } |
48 | ||
37056719 | 49 | static inline bool sk_can_busy_loop(const struct sock *sk) |
ad6276e0 | 50 | { |
37056719 | 51 | return sk->sk_ll_usec && !signal_pending(current); |
ad6276e0 | 52 | } |
ad6276e0 | 53 | |
7db6b048 SS |
54 | bool sk_busy_loop_end(void *p, unsigned long start_time); |
55 | ||
56 | void napi_busy_loop(unsigned int napi_id, | |
57 | bool (*loop_end)(void *, unsigned long), | |
58 | void *loop_end_arg); | |
9a3c71aa | 59 | |
37056719 AD |
60 | #else /* CONFIG_NET_RX_BUSY_POLL */ |
61 | static inline unsigned long net_busy_loop_on(void) | |
1bc2774d | 62 | { |
37056719 | 63 | return 0; |
06021292 ET |
64 | } |
65 | ||
37056719 | 66 | static inline bool sk_can_busy_loop(struct sock *sk) |
06021292 | 67 | { |
37056719 | 68 | return false; |
06021292 ET |
69 | } |
70 | ||
37056719 | 71 | #endif /* CONFIG_NET_RX_BUSY_POLL */ |
06021292 | 72 | |
37056719 | 73 | static inline unsigned long busy_loop_current_time(void) |
91e2fd33 | 74 | { |
37056719 AD |
75 | #ifdef CONFIG_NET_RX_BUSY_POLL |
76 | return (unsigned long)(local_clock() >> 10); | |
77 | #else | |
91e2fd33 | 78 | return 0; |
37056719 | 79 | #endif |
91e2fd33 | 80 | } |
06021292 | 81 | |
37056719 AD |
82 | /* in poll/select we use the global sysctl_net_ll_poll value */ |
83 | static inline bool busy_loop_timeout(unsigned long start_time) | |
06021292 | 84 | { |
37056719 AD |
85 | #ifdef CONFIG_NET_RX_BUSY_POLL |
86 | unsigned long bp_usec = READ_ONCE(sysctl_net_busy_poll); | |
06021292 | 87 | |
37056719 AD |
88 | if (bp_usec) { |
89 | unsigned long end_time = start_time + bp_usec; | |
90 | unsigned long now = busy_loop_current_time(); | |
06021292 | 91 | |
37056719 AD |
92 | return time_after(now, end_time); |
93 | } | |
94 | #endif | |
76b1e9b9 | 95 | return true; |
06021292 ET |
96 | } |
97 | ||
37056719 AD |
98 | static inline bool sk_busy_loop_timeout(struct sock *sk, |
99 | unsigned long start_time) | |
dfcefb0b | 100 | { |
37056719 AD |
101 | #ifdef CONFIG_NET_RX_BUSY_POLL |
102 | unsigned long bp_usec = READ_ONCE(sk->sk_ll_usec); | |
dfcefb0b | 103 | |
37056719 AD |
104 | if (bp_usec) { |
105 | unsigned long end_time = start_time + bp_usec; | |
106 | unsigned long now = busy_loop_current_time(); | |
107 | ||
108 | return time_after(now, end_time); | |
109 | } | |
110 | #endif | |
111 | return true; | |
112 | } | |
e68b6e50 | 113 | |
7db6b048 SS |
114 | static inline void sk_busy_loop(struct sock *sk, int nonblock) |
115 | { | |
116 | #ifdef CONFIG_NET_RX_BUSY_POLL | |
117 | unsigned int napi_id = READ_ONCE(sk->sk_napi_id); | |
118 | ||
119 | if (napi_id >= MIN_NAPI_ID) | |
120 | napi_busy_loop(napi_id, nonblock ? NULL : sk_busy_loop_end, sk); | |
121 | #endif | |
122 | } | |
123 | ||
d2e64dbb AD |
124 | /* used in the NIC receive handler to mark the skb */ |
125 | static inline void skb_mark_napi_id(struct sk_buff *skb, | |
126 | struct napi_struct *napi) | |
127 | { | |
128 | #ifdef CONFIG_NET_RX_BUSY_POLL | |
129 | skb->napi_id = napi->napi_id; | |
130 | #endif | |
131 | } | |
132 | ||
e68b6e50 ED |
133 | /* used in the protocol hanlder to propagate the napi_id to the socket */ |
134 | static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) | |
135 | { | |
136 | #ifdef CONFIG_NET_RX_BUSY_POLL | |
137 | sk->sk_napi_id = skb->napi_id; | |
138 | #endif | |
139 | } | |
140 | ||
141 | /* variant used for unconnected sockets */ | |
142 | static inline void sk_mark_napi_id_once(struct sock *sk, | |
143 | const struct sk_buff *skb) | |
144 | { | |
145 | #ifdef CONFIG_NET_RX_BUSY_POLL | |
146 | if (!sk->sk_napi_id) | |
147 | sk->sk_napi_id = skb->napi_id; | |
148 | #endif | |
149 | } | |
150 | ||
8b80cda5 | 151 | #endif /* _LINUX_NET_BUSY_POLL_H */ |