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

Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2022-08-12 (iavf)

This series contains updates to iavf driver only.

Przemyslaw frees memory for admin queues in initialization error paths,
prevents freeing of vf_res which is causing null pointer dereference,
and adjusts calls in error path of reset to avoid iavf_close() which
could cause deadlock.

Ivan Vecera avoids deadlock that can occur when driver if part of
failover.

* '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue:
iavf: Fix deadlock in initialization
iavf: Fix reset error handling
iavf: Fix NULL pointer dereference in iavf_get_link_ksettings
iavf: Fix adminq error handling
====================

Link: https://lore.kernel.org/r/20220812172309.853230-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+30 -7
+13 -2
drivers/net/ethernet/intel/iavf/iavf_adminq.c
··· 324 324 static enum iavf_status iavf_init_asq(struct iavf_hw *hw) 325 325 { 326 326 enum iavf_status ret_code = 0; 327 + int i; 327 328 328 329 if (hw->aq.asq.count > 0) { 329 330 /* queue already initialized */ ··· 355 354 /* initialize base registers */ 356 355 ret_code = iavf_config_asq_regs(hw); 357 356 if (ret_code) 358 - goto init_adminq_free_rings; 357 + goto init_free_asq_bufs; 359 358 360 359 /* success! */ 361 360 hw->aq.asq.count = hw->aq.num_asq_entries; 362 361 goto init_adminq_exit; 362 + 363 + init_free_asq_bufs: 364 + for (i = 0; i < hw->aq.num_asq_entries; i++) 365 + iavf_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]); 366 + iavf_free_virt_mem(hw, &hw->aq.asq.dma_head); 363 367 364 368 init_adminq_free_rings: 365 369 iavf_free_adminq_asq(hw); ··· 389 383 static enum iavf_status iavf_init_arq(struct iavf_hw *hw) 390 384 { 391 385 enum iavf_status ret_code = 0; 386 + int i; 392 387 393 388 if (hw->aq.arq.count > 0) { 394 389 /* queue already initialized */ ··· 420 413 /* initialize base registers */ 421 414 ret_code = iavf_config_arq_regs(hw); 422 415 if (ret_code) 423 - goto init_adminq_free_rings; 416 + goto init_free_arq_bufs; 424 417 425 418 /* success! */ 426 419 hw->aq.arq.count = hw->aq.num_arq_entries; 427 420 goto init_adminq_exit; 428 421 422 + init_free_arq_bufs: 423 + for (i = 0; i < hw->aq.num_arq_entries; i++) 424 + iavf_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]); 425 + iavf_free_virt_mem(hw, &hw->aq.arq.dma_head); 429 426 init_adminq_free_rings: 430 427 iavf_free_adminq_arq(hw); 431 428
+17 -5
drivers/net/ethernet/intel/iavf/iavf_main.c
··· 2367 2367 err = iavf_get_vf_config(adapter); 2368 2368 if (err == -EALREADY) { 2369 2369 err = iavf_send_vf_config_msg(adapter); 2370 - goto err_alloc; 2370 + goto err; 2371 2371 } else if (err == -EINVAL) { 2372 2372 /* We only get -EINVAL if the device is in a very bad 2373 2373 * state or if we've been disabled for previous bad ··· 3086 3086 3087 3087 return; 3088 3088 reset_err: 3089 + if (running) { 3090 + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); 3091 + iavf_free_traffic_irqs(adapter); 3092 + } 3093 + iavf_disable_vf(adapter); 3094 + 3089 3095 mutex_unlock(&adapter->client_lock); 3090 3096 mutex_unlock(&adapter->crit_lock); 3091 - if (running) 3092 - iavf_change_state(adapter, __IAVF_RUNNING); 3093 3097 dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); 3094 - iavf_close(netdev); 3095 3098 } 3096 3099 3097 3100 /** ··· 4088 4085 return -EIO; 4089 4086 } 4090 4087 4091 - while (!mutex_trylock(&adapter->crit_lock)) 4088 + while (!mutex_trylock(&adapter->crit_lock)) { 4089 + /* If we are in __IAVF_INIT_CONFIG_ADAPTER state the crit_lock 4090 + * is already taken and iavf_open is called from an upper 4091 + * device's notifier reacting on NETDEV_REGISTER event. 4092 + * We have to leave here to avoid dead lock. 4093 + */ 4094 + if (adapter->state == __IAVF_INIT_CONFIG_ADAPTER) 4095 + return -EBUSY; 4096 + 4092 4097 usleep_range(500, 1000); 4098 + } 4093 4099 4094 4100 if (adapter->state != __IAVF_DOWN) { 4095 4101 err = -EBUSY;