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

ice: Refactor getting/setting coalesce

Currently if the driver has an uneven amount of Rx/Tx queues
setting the coalesce settings through ethtool will result in
an error. This is happening because in the setting coalesce
flow we are reporting an error if either Rx or Tx fails.

Also, the flow for setting/getting per_q_coalesce and
setting/getting coalesce settings for the entire device
is different.

Fix these issues by adding one function, ice_set_q_coalesce(),
and another, ice_get_q_coalesce(), that both getting/setting
per_q and entire device coalesce can use. This makes handling
the error cases generic between the two flows and simplifies
__ice_set_coalesce() and __ice_get_coalesce().

Also, add a header comment to __ice_set_coalesce().

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Brett Creeley and committed by
Jeff Kirsher
e40c899a a85a3847

+93 -59
+93 -59
drivers/net/ethernet/intel/ice/ice_ethtool.c
··· 2255 2255 } 2256 2256 2257 2257 /** 2258 + * ice_get_q_coalesce - get a queue's ITR/INTRL (coalesce) settings 2259 + * @vsi: VSI associated to the queue for getting ITR/INTRL (coalesce) settings 2260 + * @ec: coalesce settings to program the device with 2261 + * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 2262 + * 2263 + * Return 0 on success, and negative under the following conditions: 2264 + * 1. Getting Tx or Rx ITR/INTRL (coalesce) settings failed. 2265 + * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 2266 + */ 2267 + static int 2268 + ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 2269 + { 2270 + if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2271 + if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2272 + &vsi->rx_rings[q_num]->q_vector->rx)) 2273 + return -EINVAL; 2274 + if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2275 + &vsi->tx_rings[q_num]->q_vector->tx)) 2276 + return -EINVAL; 2277 + } else if (q_num < vsi->num_rxq) { 2278 + if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2279 + &vsi->rx_rings[q_num]->q_vector->rx)) 2280 + return -EINVAL; 2281 + } else if (q_num < vsi->num_txq) { 2282 + if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2283 + &vsi->tx_rings[q_num]->q_vector->tx)) 2284 + return -EINVAL; 2285 + } else { 2286 + return -EINVAL; 2287 + } 2288 + 2289 + return 0; 2290 + } 2291 + 2292 + /** 2258 2293 * __ice_get_coalesce - get ITR/INTRL values for the device 2259 2294 * @netdev: pointer to the netdev associated with this query 2260 2295 * @ec: ethtool structure to fill with driver's coalesce settings 2261 2296 * @q_num: queue number to get the coalesce settings for 2297 + * 2298 + * If the caller passes in a negative q_num then we return coalesce settings 2299 + * based on queue number 0, else use the actual q_num passed in. 2262 2300 */ 2263 2301 static int 2264 2302 __ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 2265 2303 int q_num) 2266 2304 { 2267 2305 struct ice_netdev_priv *np = netdev_priv(netdev); 2268 - int tx = -EINVAL, rx = -EINVAL; 2269 2306 struct ice_vsi *vsi = np->vsi; 2270 2307 2271 - if (q_num < 0) { 2272 - rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2273 - &vsi->rx_rings[0]->q_vector->rx); 2274 - tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2275 - &vsi->tx_rings[0]->q_vector->tx); 2308 + if (q_num < 0) 2309 + q_num = 0; 2276 2310 2277 - goto update_coalesced_frames; 2278 - } 2279 - 2280 - if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2281 - rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2282 - &vsi->rx_rings[q_num]->q_vector->rx); 2283 - tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2284 - &vsi->tx_rings[q_num]->q_vector->tx); 2285 - } else if (q_num < vsi->num_rxq) { 2286 - rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2287 - &vsi->rx_rings[q_num]->q_vector->rx); 2288 - } else if (q_num < vsi->num_txq) { 2289 - tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2290 - &vsi->tx_rings[q_num]->q_vector->tx); 2291 - } else { 2292 - /* q_num is invalid for both Rx and Tx queues */ 2293 - return -EINVAL; 2294 - } 2295 - 2296 - update_coalesced_frames: 2297 - /* either q_num is invalid for both Rx and Tx queues or setting coalesce 2298 - * failed completely 2299 - */ 2300 - if (tx && rx) 2311 + if (ice_get_q_coalesce(vsi, ec, q_num)) 2301 2312 return -EINVAL; 2302 2313 2303 2314 if (q_num < vsi->num_txq) ··· 2434 2423 return 0; 2435 2424 } 2436 2425 2426 + /** 2427 + * ice_set_q_coalesce - set a queue's ITR/INTRL (coalesce) settings 2428 + * @vsi: VSI associated to the queue that need updating 2429 + * @ec: coalesce settings to program the device with 2430 + * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 2431 + * 2432 + * Return 0 on success, and negative under the following conditions: 2433 + * 1. Setting Tx or Rx ITR/INTRL (coalesce) settings failed. 2434 + * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 2435 + */ 2436 + static int 2437 + ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 2438 + { 2439 + if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2440 + if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2441 + &vsi->rx_rings[q_num]->q_vector->rx, 2442 + vsi)) 2443 + return -EINVAL; 2444 + 2445 + if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2446 + &vsi->tx_rings[q_num]->q_vector->tx, 2447 + vsi)) 2448 + return -EINVAL; 2449 + } else if (q_num < vsi->num_rxq) { 2450 + if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2451 + &vsi->rx_rings[q_num]->q_vector->rx, 2452 + vsi)) 2453 + return -EINVAL; 2454 + } else if (q_num < vsi->num_txq) { 2455 + if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2456 + &vsi->tx_rings[q_num]->q_vector->tx, 2457 + vsi)) 2458 + return -EINVAL; 2459 + } else { 2460 + return -EINVAL; 2461 + } 2462 + 2463 + return 0; 2464 + } 2465 + 2466 + /** 2467 + * __ice_set_coalesce - set ITR/INTRL values for the device 2468 + * @netdev: pointer to the netdev associated with this query 2469 + * @ec: ethtool structure to fill with driver's coalesce settings 2470 + * @q_num: queue number to get the coalesce settings for 2471 + * 2472 + * If the caller passes in a negative q_num then we set the coalesce settings 2473 + * for all Tx/Rx queues, else use the actual q_num passed in. 2474 + */ 2437 2475 static int 2438 2476 __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 2439 2477 int q_num) 2440 2478 { 2441 2479 struct ice_netdev_priv *np = netdev_priv(netdev); 2442 - int rx = -EINVAL, tx = -EINVAL; 2443 2480 struct ice_vsi *vsi = np->vsi; 2444 2481 2445 2482 if (q_num < 0) { 2446 2483 int i; 2447 2484 2448 2485 ice_for_each_q_vector(vsi, i) { 2449 - struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2450 - 2451 - if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2452 - &q_vector->rx, vsi) || 2453 - ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2454 - &q_vector->tx, vsi)) 2486 + if (ice_set_q_coalesce(vsi, ec, i)) 2455 2487 return -EINVAL; 2456 2488 } 2457 - 2458 2489 goto set_work_lmt; 2459 2490 } 2460 2491 2461 - if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2462 - rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2463 - &vsi->rx_rings[q_num]->q_vector->rx, 2464 - vsi); 2465 - tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2466 - &vsi->tx_rings[q_num]->q_vector->tx, 2467 - vsi); 2468 - } else if (q_num < vsi->num_rxq) { 2469 - rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2470 - &vsi->rx_rings[q_num]->q_vector->rx, 2471 - vsi); 2472 - } else if (q_num < vsi->num_txq) { 2473 - tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2474 - &vsi->tx_rings[q_num]->q_vector->tx, 2475 - vsi); 2476 - } 2477 - 2478 - /* either q_num is invalid for both Rx and Tx queues or setting coalesce 2479 - * failed completely 2480 - */ 2481 - if (rx && tx) 2492 + if (ice_set_q_coalesce(vsi, ec, q_num)) 2482 2493 return -EINVAL; 2483 2494 2484 2495 set_work_lmt: 2496 + 2485 2497 if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) 2486 2498 vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq, 2487 2499 ec->rx_max_coalesced_frames_irq);