11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Common code for low-level network console, dump, and debugger code 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Derived from netconsole, kgdb-over-ethernet, and netdump patches 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds #ifndef _LINUX_NETPOLL_H 81da177e4SLinus Torvalds #define _LINUX_NETPOLL_H 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds #include <linux/netdevice.h> 111da177e4SLinus Torvalds #include <linux/interrupt.h> 1253fb95d3SMatt Mackall #include <linux/rcupdate.h> 131da177e4SLinus Torvalds #include <linux/list.h> 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds struct netpoll { 161da177e4SLinus Torvalds struct net_device *dev; 170e34e931SWANG Cong struct net_device *real_dev; 18bf6bce71SStephen Hemminger char dev_name[IFNAMSIZ]; 19bf6bce71SStephen Hemminger const char *name; 201da177e4SLinus Torvalds void (*rx_hook)(struct netpoll *, int, char *, int); 215de4a473SStephen Hemminger 22e7557af5SHarvey Harrison __be32 local_ip, remote_ip; 231da177e4SLinus Torvalds u16 local_port, remote_port; 2409538641SStephen Hemminger u8 remote_mac[ETH_ALEN]; 25508e14b4SDaniel Borkmann 26508e14b4SDaniel Borkmann struct list_head rx; /* rx_np list element */ 27115c1d6eSJeff Moyer }; 28115c1d6eSJeff Moyer 29115c1d6eSJeff Moyer struct netpoll_info { 3093ec2c72SStephen Hemminger atomic_t refcnt; 31508e14b4SDaniel Borkmann 32d9452e9fSDavid S. Miller int rx_flags; 33fbeec2e1SJeff Moyer spinlock_t rx_lock; 34508e14b4SDaniel Borkmann struct list_head rx_np; /* netpolls that registered an rx_hook */ 35508e14b4SDaniel Borkmann 36068c6e98SNeil Horman struct sk_buff_head arp_tx; /* list of arp requests to reply to */ 37b6cd27edSStephen Hemminger struct sk_buff_head txq; 38508e14b4SDaniel Borkmann 396d5aefb8SDavid Howells struct delayed_work tx_work; 400e34e931SWANG Cong 410e34e931SWANG Cong struct netpoll *netpoll; 421da177e4SLinus Torvalds }; 431da177e4SLinus Torvalds 440e34e931SWANG Cong void netpoll_poll_dev(struct net_device *dev); 451da177e4SLinus Torvalds void netpoll_poll(struct netpoll *np); 461da177e4SLinus Torvalds void netpoll_send_udp(struct netpoll *np, const char *msg, int len); 470bcc1816SSatyam Sharma void netpoll_print_options(struct netpoll *np); 481da177e4SLinus Torvalds int netpoll_parse_options(struct netpoll *np, char *opt); 498fdd95ecSHerbert Xu int __netpoll_setup(struct netpoll *np); 501da177e4SLinus Torvalds int netpoll_setup(struct netpoll *np); 511da177e4SLinus Torvalds int netpoll_trap(void); 521da177e4SLinus Torvalds void netpoll_set_trap(int trap); 538fdd95ecSHerbert Xu void __netpoll_cleanup(struct netpoll *np); 541da177e4SLinus Torvalds void netpoll_cleanup(struct netpoll *np); 551da177e4SLinus Torvalds int __netpoll_rx(struct sk_buff *skb); 560e34e931SWANG Cong void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb); 575de4a473SStephen Hemminger 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds #ifdef CONFIG_NETPOLL 60ffb27362SDavid S. Miller static inline bool netpoll_rx(struct sk_buff *skb) 611da177e4SLinus Torvalds { 62de85d99eSHerbert Xu struct netpoll_info *npinfo; 63fbeec2e1SJeff Moyer unsigned long flags; 64ffb27362SDavid S. Miller bool ret = false; 65115c1d6eSJeff Moyer 66de85d99eSHerbert Xu rcu_read_lock_bh(); 67de85d99eSHerbert Xu npinfo = rcu_dereference(skb->dev->npinfo); 68de85d99eSHerbert Xu 69508e14b4SDaniel Borkmann if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) 70de85d99eSHerbert Xu goto out; 71115c1d6eSJeff Moyer 72fbeec2e1SJeff Moyer spin_lock_irqsave(&npinfo->rx_lock, flags); 73d9452e9fSDavid S. Miller /* check rx_flags again with the lock held */ 74d9452e9fSDavid S. Miller if (npinfo->rx_flags && __netpoll_rx(skb)) 75ffb27362SDavid S. Miller ret = true; 76fbeec2e1SJeff Moyer spin_unlock_irqrestore(&npinfo->rx_lock, flags); 77fbeec2e1SJeff Moyer 78de85d99eSHerbert Xu out: 79de85d99eSHerbert Xu rcu_read_unlock_bh(); 80fbeec2e1SJeff Moyer return ret; 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 83d1c76af9SHerbert Xu static inline int netpoll_rx_on(struct sk_buff *skb) 84d1c76af9SHerbert Xu { 85de85d99eSHerbert Xu struct netpoll_info *npinfo = rcu_dereference(skb->dev->npinfo); 86d1c76af9SHerbert Xu 87508e14b4SDaniel Borkmann return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); 88d1c76af9SHerbert Xu } 89d1c76af9SHerbert Xu 90bea3348eSStephen Hemminger static inline int netpoll_receive_skb(struct sk_buff *skb) 911da177e4SLinus Torvalds { 92bea3348eSStephen Hemminger if (!list_empty(&skb->dev->napi_list)) 93bea3348eSStephen Hemminger return netpoll_rx(skb); 94bea3348eSStephen Hemminger return 0; 95bea3348eSStephen Hemminger } 96bea3348eSStephen Hemminger 97bea3348eSStephen Hemminger static inline void *netpoll_poll_lock(struct napi_struct *napi) 98bea3348eSStephen Hemminger { 99bea3348eSStephen Hemminger struct net_device *dev = napi->dev; 100bea3348eSStephen Hemminger 101bea3348eSStephen Hemminger if (dev && dev->npinfo) { 102bea3348eSStephen Hemminger spin_lock(&napi->poll_lock); 103bea3348eSStephen Hemminger napi->poll_owner = smp_processor_id(); 104bea3348eSStephen Hemminger return napi; 1051da177e4SLinus Torvalds } 10653fb95d3SMatt Mackall return NULL; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 10953fb95d3SMatt Mackall static inline void netpoll_poll_unlock(void *have) 1101da177e4SLinus Torvalds { 111bea3348eSStephen Hemminger struct napi_struct *napi = have; 11253fb95d3SMatt Mackall 113bea3348eSStephen Hemminger if (napi) { 114bea3348eSStephen Hemminger napi->poll_owner = -1; 115bea3348eSStephen Hemminger spin_unlock(&napi->poll_lock); 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds } 1181da177e4SLinus Torvalds 119*c18370f5SHerbert Xu static inline int netpoll_tx_running(struct net_device *dev) 120*c18370f5SHerbert Xu { 121*c18370f5SHerbert Xu return irqs_disabled(); 122*c18370f5SHerbert Xu } 123*c18370f5SHerbert Xu 1241da177e4SLinus Torvalds #else 125bea3348eSStephen Hemminger static inline int netpoll_rx(struct sk_buff *skb) 126bea3348eSStephen Hemminger { 127bea3348eSStephen Hemminger return 0; 128bea3348eSStephen Hemminger } 129d1c76af9SHerbert Xu static inline int netpoll_rx_on(struct sk_buff *skb) 130d1c76af9SHerbert Xu { 131d1c76af9SHerbert Xu return 0; 132d1c76af9SHerbert Xu } 133bea3348eSStephen Hemminger static inline int netpoll_receive_skb(struct sk_buff *skb) 134bea3348eSStephen Hemminger { 135bea3348eSStephen Hemminger return 0; 136bea3348eSStephen Hemminger } 137bea3348eSStephen Hemminger static inline void *netpoll_poll_lock(struct napi_struct *napi) 138bea3348eSStephen Hemminger { 139bea3348eSStephen Hemminger return NULL; 140bea3348eSStephen Hemminger } 141bea3348eSStephen Hemminger static inline void netpoll_poll_unlock(void *have) 142bea3348eSStephen Hemminger { 143bea3348eSStephen Hemminger } 144bea3348eSStephen Hemminger static inline void netpoll_netdev_init(struct net_device *dev) 145bea3348eSStephen Hemminger { 146bea3348eSStephen Hemminger } 147*c18370f5SHerbert Xu static inline int netpoll_tx_running(struct net_device *dev) 148*c18370f5SHerbert Xu { 149*c18370f5SHerbert Xu return 0; 150*c18370f5SHerbert Xu } 1511da177e4SLinus Torvalds #endif 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds #endif 154