Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ixgbevf: implement CONFIG_NET_RX_BUSY_POLL

This patch enables CONFIG_NET_RX_BUSY_POLL support in the VF code. This enables
sockets which have enabled the SO_BUSY_POLL socket option to use the
ndo_busy_poll_recv operation which could result in lower latency, at the cost
of higher CPU utilization, and increased power usage. This support is similar
to how the ixgbe driver works.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Jacob Keller and committed by
Jeff Kirsher
c777cdfa 08e50a20

+177
+109
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
··· 38 38 39 39 #include "vf.h" 40 40 41 + #ifdef CONFIG_NET_RX_BUSY_POLL 42 + #include <net/busy_poll.h> 43 + #endif 44 + 41 45 /* wrapper around a pointer to a socket buffer, 42 46 * so a DMA handle can be stored along with the buffer */ 43 47 struct ixgbevf_tx_buffer { ··· 149 145 struct napi_struct napi; 150 146 struct ixgbevf_ring_container rx, tx; 151 147 char name[IFNAMSIZ + 9]; 148 + #ifdef CONFIG_NET_RX_BUSY_POLL 149 + unsigned int state; 150 + #define IXGBEVF_QV_STATE_IDLE 0 151 + #define IXGBEVF_QV_STATE_NAPI 1 /* NAPI owns this QV */ 152 + #define IXGBEVF_QV_STATE_POLL 2 /* poll owns this QV */ 153 + #define IXGBEVF_QV_STATE_DISABLED 4 /* QV is disabled */ 154 + #define IXGBEVF_QV_OWNED (IXGBEVF_QV_STATE_NAPI | IXGBEVF_QV_STATE_POLL) 155 + #define IXGBEVF_QV_LOCKED (IXGBEVF_QV_OWNED | IXGBEVF_QV_STATE_DISABLED) 156 + #define IXGBEVF_QV_STATE_NAPI_YIELD 8 /* NAPI yielded this QV */ 157 + #define IXGBEVF_QV_STATE_POLL_YIELD 16 /* poll yielded this QV */ 158 + #define IXGBEVF_QV_YIELD (IXGBEVF_QV_STATE_NAPI_YIELD | IXGBEVF_QV_STATE_POLL_YIELD) 159 + #define IXGBEVF_QV_USER_PEND (IXGBEVF_QV_STATE_POLL | IXGBEVF_QV_STATE_POLL_YIELD) 160 + spinlock_t lock; 161 + #endif /* CONFIG_NET_RX_BUSY_POLL */ 152 162 }; 163 + #ifdef CONFIG_NET_RX_BUSY_POLL 164 + static inline void ixgbevf_qv_init_lock(struct ixgbevf_q_vector *q_vector) 165 + { 166 + 167 + spin_lock_init(&q_vector->lock); 168 + q_vector->state = IXGBEVF_QV_STATE_IDLE; 169 + } 170 + 171 + /* called from the device poll routine to get ownership of a q_vector */ 172 + static inline bool ixgbevf_qv_lock_napi(struct ixgbevf_q_vector *q_vector) 173 + { 174 + int rc = true; 175 + spin_lock_bh(&q_vector->lock); 176 + if (q_vector->state & IXGBEVF_QV_LOCKED) { 177 + WARN_ON(q_vector->state & IXGBEVF_QV_STATE_NAPI); 178 + q_vector->state |= IXGBEVF_QV_STATE_NAPI_YIELD; 179 + rc = false; 180 + } else { 181 + /* we don't care if someone yielded */ 182 + q_vector->state = IXGBEVF_QV_STATE_NAPI; 183 + } 184 + spin_unlock_bh(&q_vector->lock); 185 + return rc; 186 + } 187 + 188 + /* returns true is someone tried to get the qv while napi had it */ 189 + static inline bool ixgbevf_qv_unlock_napi(struct ixgbevf_q_vector *q_vector) 190 + { 191 + int rc = false; 192 + spin_lock_bh(&q_vector->lock); 193 + WARN_ON(q_vector->state & (IXGBEVF_QV_STATE_POLL | 194 + IXGBEVF_QV_STATE_NAPI_YIELD)); 195 + 196 + if (q_vector->state & IXGBEVF_QV_STATE_POLL_YIELD) 197 + rc = true; 198 + /* reset state to idle, unless QV is disabled */ 199 + q_vector->state &= IXGBEVF_QV_STATE_DISABLED; 200 + spin_unlock_bh(&q_vector->lock); 201 + return rc; 202 + } 203 + 204 + /* called from ixgbevf_low_latency_poll() */ 205 + static inline bool ixgbevf_qv_lock_poll(struct ixgbevf_q_vector *q_vector) 206 + { 207 + int rc = true; 208 + spin_lock_bh(&q_vector->lock); 209 + if ((q_vector->state & IXGBEVF_QV_LOCKED)) { 210 + q_vector->state |= IXGBEVF_QV_STATE_POLL_YIELD; 211 + rc = false; 212 + } else { 213 + /* preserve yield marks */ 214 + q_vector->state |= IXGBEVF_QV_STATE_POLL; 215 + } 216 + spin_unlock_bh(&q_vector->lock); 217 + return rc; 218 + } 219 + 220 + /* returns true if someone tried to get the qv while it was locked */ 221 + static inline bool ixgbevf_qv_unlock_poll(struct ixgbevf_q_vector *q_vector) 222 + { 223 + int rc = false; 224 + spin_lock_bh(&q_vector->lock); 225 + WARN_ON(q_vector->state & (IXGBEVF_QV_STATE_NAPI)); 226 + 227 + if (q_vector->state & IXGBEVF_QV_STATE_POLL_YIELD) 228 + rc = true; 229 + /* reset state to idle, unless QV is disabled */ 230 + q_vector->state &= IXGBEVF_QV_STATE_DISABLED; 231 + spin_unlock_bh(&q_vector->lock); 232 + return rc; 233 + } 234 + 235 + /* true if a socket is polling, even if it did not get the lock */ 236 + static inline bool ixgbevf_qv_busy_polling(struct ixgbevf_q_vector *q_vector) 237 + { 238 + WARN_ON(!(q_vector->state & IXGBEVF_QV_OWNED)); 239 + return q_vector->state & IXGBEVF_QV_USER_PEND; 240 + } 241 + 242 + /* false if QV is currently owned */ 243 + static inline bool ixgbevf_qv_disable(struct ixgbevf_q_vector *q_vector) 244 + { 245 + int rc = true; 246 + spin_lock_bh(&q_vector->lock); 247 + if (q_vector->state & IXGBEVF_QV_OWNED) 248 + rc = false; 249 + spin_unlock_bh(&q_vector->lock); 250 + return rc; 251 + } 252 + 253 + #endif /* CONFIG_NET_RX_BUSY_POLL */ 153 254 154 255 /* 155 256 * microsecond values for various ITR rates shifted by 2 to fit itr register
+68
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
··· 310 310 struct sk_buff *skb, u8 status, 311 311 union ixgbe_adv_rx_desc *rx_desc) 312 312 { 313 + #ifdef CONFIG_NET_RX_BUSY_POLL 314 + skb_mark_napi_id(skb, &q_vector->napi); 315 + 316 + if (ixgbevf_qv_busy_polling(q_vector)) { 317 + netif_receive_skb(skb); 318 + /* exit early if we busy polled */ 319 + return; 320 + } 321 + #endif /* CONFIG_NET_RX_BUSY_POLL */ 322 + 313 323 ixgbevf_receive_skb(q_vector, skb, status, rx_desc); 314 324 } 315 325 ··· 573 563 ixgbevf_for_each_ring(ring, q_vector->tx) 574 564 clean_complete &= ixgbevf_clean_tx_irq(q_vector, ring); 575 565 566 + #ifdef CONFIG_NET_RX_BUSY_POLL 567 + if (!ixgbevf_qv_lock_napi(q_vector)) 568 + return budget; 569 + #endif 570 + 576 571 /* attempt to distribute budget to each queue fairly, but don't allow 577 572 * the budget to go below 1 because we'll exit polling */ 578 573 if (q_vector->rx.count > 1) ··· 591 576 per_ring_budget) 592 577 < per_ring_budget); 593 578 adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL; 579 + 580 + #ifdef CONFIG_NET_RX_BUSY_POLL 581 + ixgbevf_qv_unlock_napi(q_vector); 582 + #endif 594 583 595 584 /* If all work not completed, return budget and keep polling */ 596 585 if (!clean_complete) ··· 629 610 630 611 IXGBE_WRITE_REG(hw, IXGBE_VTEITR(v_idx), itr_reg); 631 612 } 613 + 614 + #ifdef CONFIG_NET_RX_BUSY_POLL 615 + /* must be called with local_bh_disable()d */ 616 + static int ixgbevf_busy_poll_recv(struct napi_struct *napi) 617 + { 618 + struct ixgbevf_q_vector *q_vector = 619 + container_of(napi, struct ixgbevf_q_vector, napi); 620 + struct ixgbevf_adapter *adapter = q_vector->adapter; 621 + struct ixgbevf_ring *ring; 622 + int found = 0; 623 + 624 + if (test_bit(__IXGBEVF_DOWN, &adapter->state)) 625 + return LL_FLUSH_FAILED; 626 + 627 + if (!ixgbevf_qv_lock_poll(q_vector)) 628 + return LL_FLUSH_BUSY; 629 + 630 + ixgbevf_for_each_ring(ring, q_vector->rx) { 631 + found = ixgbevf_clean_rx_irq(q_vector, ring, 4); 632 + if (found) 633 + break; 634 + } 635 + 636 + ixgbevf_qv_unlock_poll(q_vector); 637 + 638 + return found; 639 + } 640 + #endif /* CONFIG_NET_RX_BUSY_POLL */ 632 641 633 642 /** 634 643 * ixgbevf_configure_msix - Configure MSI-X hardware ··· 1344 1297 1345 1298 for (q_idx = 0; q_idx < q_vectors; q_idx++) { 1346 1299 q_vector = adapter->q_vector[q_idx]; 1300 + #ifdef CONFIG_NET_RX_BUSY_POLL 1301 + ixgbevf_qv_init_lock(adapter->q_vector[q_idx]); 1302 + #endif 1347 1303 napi_enable(&q_vector->napi); 1348 1304 } 1349 1305 } ··· 1360 1310 for (q_idx = 0; q_idx < q_vectors; q_idx++) { 1361 1311 q_vector = adapter->q_vector[q_idx]; 1362 1312 napi_disable(&q_vector->napi); 1313 + #ifdef CONFIG_NET_RX_BUSY_POLL 1314 + while (!ixgbevf_qv_disable(adapter->q_vector[q_idx])) { 1315 + pr_info("QV %d locked\n", q_idx); 1316 + usleep_range(1000, 20000); 1317 + } 1318 + #endif /* CONFIG_NET_RX_BUSY_POLL */ 1363 1319 } 1364 1320 } 1365 1321 ··· 2016 1960 q_vector->v_idx = q_idx; 2017 1961 netif_napi_add(adapter->netdev, &q_vector->napi, 2018 1962 ixgbevf_poll, 64); 1963 + #ifdef CONFIG_NET_RX_BUSY_POLL 1964 + napi_hash_add(&q_vector->napi); 1965 + #endif 2019 1966 adapter->q_vector[q_idx] = q_vector; 2020 1967 } 2021 1968 ··· 2028 1969 while (q_idx) { 2029 1970 q_idx--; 2030 1971 q_vector = adapter->q_vector[q_idx]; 1972 + #ifdef CONFIG_NET_RX_BUSY_POLL 1973 + napi_hash_del(&q_vector->napi); 1974 + #endif 2031 1975 netif_napi_del(&q_vector->napi); 2032 1976 kfree(q_vector); 2033 1977 adapter->q_vector[q_idx] = NULL; ··· 2054 1992 struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx]; 2055 1993 2056 1994 adapter->q_vector[q_idx] = NULL; 1995 + #ifdef CONFIG_NET_RX_BUSY_POLL 1996 + napi_hash_del(&q_vector->napi); 1997 + #endif 2057 1998 netif_napi_del(&q_vector->napi); 2058 1999 kfree(q_vector); 2059 2000 } ··· 3388 3323 .ndo_tx_timeout = ixgbevf_tx_timeout, 3389 3324 .ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid, 3390 3325 .ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid, 3326 + #ifdef CONFIG_NET_RX_BUSY_POLL 3327 + .ndo_busy_poll = ixgbevf_busy_poll_recv, 3328 + #endif 3391 3329 }; 3392 3330 3393 3331 static void ixgbevf_assign_netdev_ops(struct net_device *dev)