2013-06-10 12:39:50 +04:00
/*
2013-07-10 18:13:26 +04:00
* net busy poll support
2013-06-10 12:39:50 +04:00
* Copyright ( c ) 2013 Intel Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Author : Eliezer Tamir
*
* Contact Information :
* e1000 - devel Mailing List < e1000 - devel @ lists . sourceforge . net >
*/
2013-07-10 18:13:26 +04:00
# ifndef _LINUX_NET_BUSY_POLL_H
# define _LINUX_NET_BUSY_POLL_H
2013-06-10 12:39:50 +04:00
# include <linux/netdevice.h>
2017-02-01 18:36:40 +03:00
# include <linux/sched/clock.h>
2017-02-02 21:15:33 +03:00
# include <linux/sched/signal.h>
2013-06-10 12:39:50 +04:00
# include <net/ip.h>
2017-03-24 20:07:53 +03:00
/* 0 - Reserved to indicate value not set
* 1. . NR_CPUS - Reserved for sender_cpu
* NR_CPUS + 1. . ~ 0 - Region available for NAPI IDs
*/
# define MIN_NAPI_ID ((unsigned int)(NR_CPUS + 1))
2017-08-11 19:31:24 +03:00
# ifdef CONFIG_NET_RX_BUSY_POLL
struct napi_struct ;
extern unsigned int sysctl_net_busy_read __read_mostly ;
extern unsigned int sysctl_net_busy_poll __read_mostly ;
2013-07-08 17:20:34 +04:00
static inline bool net_busy_loop_on ( void )
2013-06-28 16:59:35 +04:00
{
2013-07-10 18:13:36 +04:00
return sysctl_net_busy_poll ;
2013-06-28 16:59:35 +04:00
}
2017-03-24 20:08:18 +03:00
static inline bool sk_can_busy_loop ( const struct sock * sk )
2013-06-28 16:59:26 +04:00
{
2017-03-24 20:08:18 +03:00
return sk - > sk_ll_usec & & ! signal_pending ( current ) ;
2013-06-28 16:59:26 +04:00
}
2017-03-24 20:08:24 +03:00
bool sk_busy_loop_end ( void * p , unsigned long start_time ) ;
void napi_busy_loop ( unsigned int napi_id ,
bool ( * loop_end ) ( void * , unsigned long ) ,
void * loop_end_arg ) ;
2013-06-14 17:33:35 +04:00
2017-03-24 20:08:18 +03:00
# else /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long net_busy_loop_on ( void )
2013-07-03 00:22:47 +04:00
{
2017-03-24 20:08:18 +03:00
return 0 ;
2013-06-10 12:39:50 +04:00
}
2017-03-24 20:08:18 +03:00
static inline bool sk_can_busy_loop ( struct sock * sk )
2013-06-10 12:39:50 +04:00
{
2017-03-24 20:08:18 +03:00
return false ;
2013-06-10 12:39:50 +04:00
}
2017-03-24 20:08:18 +03:00
# endif /* CONFIG_NET_RX_BUSY_POLL */
2013-06-10 12:39:50 +04:00
2017-03-24 20:08:18 +03:00
static inline unsigned long busy_loop_current_time ( void )
2013-06-28 16:59:35 +04:00
{
2017-03-24 20:08:18 +03:00
# ifdef CONFIG_NET_RX_BUSY_POLL
return ( unsigned long ) ( local_clock ( ) > > 10 ) ;
# else
2013-06-28 16:59:35 +04:00
return 0 ;
2017-03-24 20:08:18 +03:00
# endif
2013-06-28 16:59:35 +04:00
}
2013-06-10 12:39:50 +04:00
2017-03-24 20:08:18 +03:00
/* in poll/select we use the global sysctl_net_ll_poll value */
static inline bool busy_loop_timeout ( unsigned long start_time )
2013-06-10 12:39:50 +04:00
{
2017-03-24 20:08:18 +03:00
# ifdef CONFIG_NET_RX_BUSY_POLL
unsigned long bp_usec = READ_ONCE ( sysctl_net_busy_poll ) ;
2013-06-10 12:39:50 +04:00
2017-03-24 20:08:18 +03:00
if ( bp_usec ) {
unsigned long end_time = start_time + bp_usec ;
unsigned long now = busy_loop_current_time ( ) ;
2013-06-10 12:39:50 +04:00
2017-03-24 20:08:18 +03:00
return time_after ( now , end_time ) ;
}
# endif
2013-07-09 14:09:21 +04:00
return true ;
2013-06-10 12:39:50 +04:00
}
2017-03-24 20:08:18 +03:00
static inline bool sk_busy_loop_timeout ( struct sock * sk ,
unsigned long start_time )
2013-08-01 07:10:24 +04:00
{
2017-03-24 20:08:18 +03:00
# ifdef CONFIG_NET_RX_BUSY_POLL
unsigned long bp_usec = READ_ONCE ( sk - > sk_ll_usec ) ;
2013-08-01 07:10:24 +04:00
2017-03-24 20:08:18 +03:00
if ( bp_usec ) {
unsigned long end_time = start_time + bp_usec ;
unsigned long now = busy_loop_current_time ( ) ;
return time_after ( now , end_time ) ;
}
# endif
return true ;
}
2016-11-16 20:10:42 +03:00
2017-03-24 20:08:24 +03:00
static inline void sk_busy_loop ( struct sock * sk , int nonblock )
{
# ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int napi_id = READ_ONCE ( sk - > sk_napi_id ) ;
if ( napi_id > = MIN_NAPI_ID )
napi_busy_loop ( napi_id , nonblock ? NULL : sk_busy_loop_end , sk ) ;
# endif
}
2017-03-24 20:08:06 +03:00
/* used in the NIC receive handler to mark the skb */
static inline void skb_mark_napi_id ( struct sk_buff * skb ,
struct napi_struct * napi )
{
# ifdef CONFIG_NET_RX_BUSY_POLL
skb - > napi_id = napi - > napi_id ;
# endif
}
2016-11-16 20:10:42 +03:00
/* used in the protocol hanlder to propagate the napi_id to the socket */
static inline void sk_mark_napi_id ( struct sock * sk , const struct sk_buff * skb )
{
# ifdef CONFIG_NET_RX_BUSY_POLL
sk - > sk_napi_id = skb - > napi_id ;
# endif
}
/* variant used for unconnected sockets */
static inline void sk_mark_napi_id_once ( struct sock * sk ,
const struct sk_buff * skb )
{
# ifdef CONFIG_NET_RX_BUSY_POLL
if ( ! sk - > sk_napi_id )
sk - > sk_napi_id = skb - > napi_id ;
# endif
}
2013-07-10 18:13:26 +04:00
# endif /* _LINUX_NET_BUSY_POLL_H */