diff options
author | Govindarajulu Varadarajan <_govind@gmx.com> | 2014-06-23 16:08:04 +0530 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-23 14:32:19 -0700 |
commit | 14747cd977195a8aae13d0b1ad021e33c8786afe (patch) | |
tree | 25f8225f9c5f9cf8d9abd29f98417b193d44a94e /drivers/net/ethernet/cisco/enic/vnic_rq.h | |
parent | 8e091340cfcd6f96ca0dddb078ce28c407a6d44c (diff) |
enic: add low latency socket busy_poll support
This patch adds support for low latency busy_poll.
* Introduce drivers ndo_busy_poll function enic_busy_poll, which is called by
socket waiting for data.
* Introduce locking between napi_poll nad busy_poll
* enic_busy_poll cleans up all the rx pkts possible. While in busy_poll, rq
holds the state ENIC_POLL_STATE_POLL. While in napi_poll, rq holds the state
ENIC_POLL_STATE_NAPI.
* in napi_poll we return if we are in busy_poll. Incase of INTx & msix, we just
service wq and return if busy_poll is going on.
Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cisco/enic/vnic_rq.h')
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_rq.h | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.h b/drivers/net/ethernet/cisco/enic/vnic_rq.h index ee7bc95af278..8111d5202df2 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_rq.h +++ b/drivers/net/ethernet/cisco/enic/vnic_rq.h @@ -85,6 +85,21 @@ struct vnic_rq { struct vnic_rq_buf *to_clean; void *os_buf_head; unsigned int pkts_outstanding; +#ifdef CONFIG_NET_RX_BUSY_POLL +#define ENIC_POLL_STATE_IDLE 0 +#define ENIC_POLL_STATE_NAPI (1 << 0) /* NAPI owns this poll */ +#define ENIC_POLL_STATE_POLL (1 << 1) /* poll owns this poll */ +#define ENIC_POLL_STATE_NAPI_YIELD (1 << 2) /* NAPI yielded this poll */ +#define ENIC_POLL_STATE_POLL_YIELD (1 << 3) /* poll yielded this poll */ +#define ENIC_POLL_YIELD (ENIC_POLL_STATE_NAPI_YIELD | \ + ENIC_POLL_STATE_POLL_YIELD) +#define ENIC_POLL_LOCKED (ENIC_POLL_STATE_NAPI | \ + ENIC_POLL_STATE_POLL) +#define ENIC_POLL_USER_PEND (ENIC_POLL_STATE_POLL | \ + ENIC_POLL_STATE_POLL_YIELD) + unsigned int bpoll_state; + spinlock_t bpoll_lock; +#endif /* CONFIG_NET_RX_BUSY_POLL */ }; static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq) @@ -197,6 +212,113 @@ static inline int vnic_rq_fill(struct vnic_rq *rq, return 0; } +#ifdef CONFIG_NET_RX_BUSY_POLL +static inline void enic_busy_poll_init_lock(struct vnic_rq *rq) +{ + spin_lock_init(&rq->bpoll_lock); + rq->bpoll_state = ENIC_POLL_STATE_IDLE; +} + +static inline bool enic_poll_lock_napi(struct vnic_rq *rq) +{ + bool rc = true; + + spin_lock(&rq->bpoll_lock); + if (rq->bpoll_state & ENIC_POLL_LOCKED) { + WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI); + rq->bpoll_state |= ENIC_POLL_STATE_NAPI_YIELD; + rc = false; + } else { + rq->bpoll_state = ENIC_POLL_STATE_NAPI; + } + spin_unlock(&rq->bpoll_lock); + + return rc; +} + +static inline bool enic_poll_unlock_napi(struct vnic_rq *rq) +{ + bool rc = false; + + spin_lock(&rq->bpoll_lock); + WARN_ON(rq->bpoll_state & + (ENIC_POLL_STATE_POLL | ENIC_POLL_STATE_NAPI_YIELD)); + if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD) + rc = true; + rq->bpoll_state = ENIC_POLL_STATE_IDLE; + spin_unlock(&rq->bpoll_lock); + + return rc; +} + +static inline bool enic_poll_lock_poll(struct vnic_rq *rq) +{ + bool rc = true; + + spin_lock_bh(&rq->bpoll_lock); + if (rq->bpoll_state & ENIC_POLL_LOCKED) { + rq->bpoll_state |= ENIC_POLL_STATE_POLL_YIELD; + rc = false; + } else { + rq->bpoll_state |= ENIC_POLL_STATE_POLL; + } + spin_unlock_bh(&rq->bpoll_lock); + + return rc; +} + +static inline bool enic_poll_unlock_poll(struct vnic_rq *rq) +{ + bool rc = false; + + spin_lock_bh(&rq->bpoll_lock); + WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI); + if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD) + rc = true; + rq->bpoll_state = ENIC_POLL_STATE_IDLE; + spin_unlock_bh(&rq->bpoll_lock); + + return rc; +} + +static inline bool enic_poll_busy_polling(struct vnic_rq *rq) +{ + WARN_ON(!(rq->bpoll_state & ENIC_POLL_LOCKED)); + return rq->bpoll_state & ENIC_POLL_USER_PEND; +} + +#else + +static inline void enic_busy_poll_init_lock(struct vnic_rq *rq) +{ +} + +static inline bool enic_poll_lock_napi(struct vnic_rq *rq) +{ + return true; +} + +static inline bool enic_poll_unlock_napi(struct vnic_rq *rq) +{ + return false; +} + +static inline bool enic_poll_lock_poll(struct vnic_rq *rq) +{ + return false; +} + +static inline bool enic_poll_unlock_poll(struct vnic_rq *rq) +{ + return false; +} + +static inline bool enic_poll_ll_polling(struct vnic_rq *rq) +{ + return false; +} +#endif /* CONFIG_NET_RX_BUSY_POLL */ + void vnic_rq_free(struct vnic_rq *rq); int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, unsigned int desc_count, unsigned int desc_size); |