blob: 8ffd434676b7a270af73534f3dbcc26f370fe215 [file] [log] [blame]
Eliezer Tamir06021292013-06-10 11:39:50 +03001/*
Eliezer Tamir8b80cda2013-07-10 17:13:26 +03002 * net busy poll support
Eliezer Tamir06021292013-06-10 11:39:50 +03003 * 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
Eliezer Tamir8b80cda2013-07-10 17:13:26 +030024#ifndef _LINUX_NET_BUSY_POLL_H
25#define _LINUX_NET_BUSY_POLL_H
Eliezer Tamir06021292013-06-10 11:39:50 +030026
27#include <linux/netdevice.h>
Ingo Molnare6017572017-02-01 16:36:40 +010028#include <linux/sched/clock.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010029#include <linux/sched/signal.h>
Eliezer Tamir06021292013-06-10 11:39:50 +030030#include <net/ip.h>
31
Cong Wange0d10952013-08-01 11:10:25 +080032#ifdef CONFIG_NET_RX_BUSY_POLL
Eliezer Tamir06021292013-06-10 11:39:50 +030033
34struct napi_struct;
Eliezer Tamir64b0dc52013-07-10 17:13:36 +030035extern unsigned int sysctl_net_busy_read __read_mostly;
36extern unsigned int sysctl_net_busy_poll __read_mostly;
Eliezer Tamir06021292013-06-10 11:39:50 +030037
Alexander Duyck545cd5e2017-03-24 10:07:53 -070038/* 0 - Reserved to indicate value not set
39 * 1..NR_CPUS - Reserved for sender_cpu
40 * NR_CPUS+1..~0 - Region available for NAPI IDs
41 */
42#define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1))
43
Eliezer Tamircbf55002013-07-08 16:20:34 +030044static inline bool net_busy_loop_on(void)
Eliezer Tamir91e2fd332013-06-28 15:59:35 +030045{
Eliezer Tamir64b0dc52013-07-10 17:13:36 +030046 return sysctl_net_busy_poll;
Eliezer Tamir91e2fd332013-06-28 15:59:35 +030047}
48
Eric Dumazet21cb84c2016-11-15 10:15:12 -080049static inline bool sk_can_busy_loop(const struct sock *sk)
Eliezer Tamir06021292013-06-10 11:39:50 +030050{
Alexander Duyck545cd5e2017-03-24 10:07:53 -070051 return sk->sk_ll_usec && !signal_pending(current);
Eliezer Tamir06021292013-06-10 11:39:50 +030052}
53
Sridhar Samudrala7db6b042017-03-24 10:08:24 -070054bool sk_busy_loop_end(void *p, unsigned long start_time);
55
56void napi_busy_loop(unsigned int napi_id,
57 bool (*loop_end)(void *, unsigned long),
58 void *loop_end_arg);
Eliezer Tamir06021292013-06-10 11:39:50 +030059
Cong Wange0d10952013-08-01 11:10:25 +080060#else /* CONFIG_NET_RX_BUSY_POLL */
Eliezer Tamircbf55002013-07-08 16:20:34 +030061static inline unsigned long net_busy_loop_on(void)
Eliezer Tamir91e2fd332013-06-28 15:59:35 +030062{
63 return 0;
64}
Eliezer Tamir06021292013-06-10 11:39:50 +030065
Eliezer Tamircbf55002013-07-08 16:20:34 +030066static inline bool sk_can_busy_loop(struct sock *sk)
Eliezer Tamir06021292013-06-10 11:39:50 +030067{
68 return false;
69}
70
Cong Wange0d10952013-08-01 11:10:25 +080071#endif /* CONFIG_NET_RX_BUSY_POLL */
Eric Dumazete68b6e52016-11-16 09:10:42 -080072
Alexander Duyck37056712017-03-24 10:08:18 -070073static inline unsigned long busy_loop_current_time(void)
74{
75#ifdef CONFIG_NET_RX_BUSY_POLL
76 return (unsigned long)(local_clock() >> 10);
77#else
78 return 0;
79#endif
80}
81
82/* in poll/select we use the global sysctl_net_ll_poll value */
83static inline bool busy_loop_timeout(unsigned long start_time)
84{
85#ifdef CONFIG_NET_RX_BUSY_POLL
86 unsigned long bp_usec = READ_ONCE(sysctl_net_busy_poll);
87
88 if (bp_usec) {
89 unsigned long end_time = start_time + bp_usec;
90 unsigned long now = busy_loop_current_time();
91
92 return time_after(now, end_time);
93 }
94#endif
95 return true;
96}
97
98static inline bool sk_busy_loop_timeout(struct sock *sk,
99 unsigned long start_time)
100{
101#ifdef CONFIG_NET_RX_BUSY_POLL
102 unsigned long bp_usec = READ_ONCE(sk->sk_ll_usec);
103
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}
113
Sridhar Samudrala7db6b042017-03-24 10:08:24 -0700114static 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
Alexander Duyckd2e64db2017-03-24 10:08:06 -0700124/* used in the NIC receive handler to mark the skb */
125static 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
Eric Dumazete68b6e52016-11-16 09:10:42 -0800133/* used in the protocol hanlder to propagate the napi_id to the socket */
134static 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 */
142static 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
Eliezer Tamir8b80cda2013-07-10 17:13:26 +0300151#endif /* _LINUX_NET_BUSY_POLL_H */