From f650a38b4d3a3b5a14d0bc093f0ae7773faf7f41 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 20 Nov 2013 10:02:55 +0000 Subject: [PATCH] i40e: refactor reset code In order to re-size queues and vectors while the interface is still up, we need to be able to call functions to free and re-allocate without bringing down the VSI. We also need to reset the existing setup, update the configuration and then rebuild again. This requires us to have the reset flow broken down into two parts. Change-Id: I374dd25aabf769decda69b676491c7b7730a4635 Signed-off-by: Anjali Singhai Jain Signed-off-by: Jesse Brandeburg Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 131 ++++++++++++++------ 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 969a6871e3c3..273db9940ff1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4716,22 +4716,20 @@ static void i40e_fdir_teardown(struct i40e_pf *pf) } /** - * i40e_handle_reset_warning - prep for the core to reset + * i40e_prep_for_reset - prep for the core to reset * @pf: board private structure * - * Close up the VFs and other things in prep for a Core Reset, - * then get ready to rebuild the world. - **/ -static void i40e_handle_reset_warning(struct i40e_pf *pf) + * Close up the VFs and other things in prep for pf Reset. + **/ +static int i40e_prep_for_reset(struct i40e_pf *pf) { - struct i40e_driver_version dv; struct i40e_hw *hw = &pf->hw; i40e_status ret; u32 v; clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state); if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) - return; + return 0; dev_info(&pf->pdev->dev, "Tearing down internal switch for reset\n"); @@ -4747,6 +4745,26 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf) i40e_shutdown_adminq(&pf->hw); + /* call shutdown HMC */ + ret = i40e_shutdown_lan_hmc(hw); + if (ret) { + dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); + clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); + } + return ret; +} + +/** + * i40e_reset_and_rebuild - reset and rebuid using a saved config + * @pf: board private structure + **/ +static void i40e_reset_and_rebuild(struct i40e_pf *pf) +{ + struct i40e_driver_version dv; + struct i40e_hw *hw = &pf->hw; + i40e_status ret; + u32 v; + /* Now we wait for GRST to settle out. * We don't have to delete the VEBs or VSIs from the hw switch * because the reset will make them disappear. @@ -4774,13 +4792,6 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf) goto end_core_reset; } - /* call shutdown HMC */ - ret = i40e_shutdown_lan_hmc(hw); - if (ret) { - dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret); - goto end_core_reset; - } - ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, hw->func_caps.num_rx_qp, pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num); @@ -4873,6 +4884,22 @@ end_core_reset: clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state); } +/** + * i40e_handle_reset_warning - prep for the pf to reset, reset and rebuild + * @pf: board private structure + * + * Close up the VFs and other things in prep for a Core Reset, + * then get ready to rebuild the world. + **/ +static void i40e_handle_reset_warning(struct i40e_pf *pf) +{ + i40e_status ret; + + ret = i40e_prep_for_reset(pf); + if (!ret) + i40e_reset_and_rebuild(pf); +} + /** * i40e_handle_mdd_event * @pf: pointer to the pf structure @@ -5048,6 +5075,40 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi) return 0; } +/** + * i40e_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi + * @type: VSI pointer + * + * On error: returns error code (negative) + * On success: returns 0 + **/ +static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi) +{ + int size; + int ret = 0; + + /* allocate memory for ring pointers */ + size = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2; + vsi->tx_rings = kzalloc(size, GFP_KERNEL); + if (!vsi->tx_rings) + return -ENOMEM; + + vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; + + /* allocate memory for q_vector pointers */ + size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; + vsi->q_vectors = kzalloc(size, GFP_KERNEL); + if (!vsi->q_vectors) { + ret = -ENOMEM; + goto err_vectors; + } + return ret; + +err_vectors: + kfree(vsi->tx_rings); + return ret; +} + /** * i40e_vsi_mem_alloc - Allocates the next available struct vsi in the PF * @pf: board private structure @@ -5060,8 +5121,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) { int ret = -ENODEV; struct i40e_vsi *vsi; - int sz_vectors; - int sz_rings; int vsi_idx; int i; @@ -5111,22 +5170,9 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) if (ret) goto err_rings; - /* allocate memory for ring pointers */ - sz_rings = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2; - vsi->tx_rings = kzalloc(sz_rings, GFP_KERNEL); - if (!vsi->tx_rings) { - ret = -ENOMEM; + ret = i40e_vsi_alloc_arrays(vsi); + if (ret) goto err_rings; - } - vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs]; - - /* allocate memory for q_vector pointers */ - sz_vectors = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; - vsi->q_vectors = kzalloc(sz_vectors, GFP_KERNEL); - if (!vsi->q_vectors) { - ret = -ENOMEM; - goto err_vectors; - } /* Setup default MSIX irq handler for VSI */ i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings); @@ -5135,8 +5181,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) ret = vsi_idx; goto unlock_pf; -err_vectors: - kfree(vsi->tx_rings); err_rings: pf->next_vsi = i - 1; kfree(vsi); @@ -5145,6 +5189,23 @@ unlock_pf: return ret; } +/** + * i40e_vsi_free_arrays - Free queue and vector pointer arrays for the VSI + * @type: VSI pointer + * + * On error: returns error code (negative) + * On success: returns 0 + **/ +static void i40e_vsi_free_arrays(struct i40e_vsi *vsi) +{ + /* free the ring and vector containers */ + kfree(vsi->q_vectors); + vsi->q_vectors = NULL; + kfree(vsi->tx_rings); + vsi->tx_rings = NULL; + vsi->rx_rings = NULL; +} + /** * i40e_vsi_clear - Deallocate the VSI provided * @vsi: the VSI being un-configured @@ -5181,9 +5242,7 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi) i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx); i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx); - /* free the ring and vector containers */ - kfree(vsi->q_vectors); - kfree(vsi->tx_rings); + i40e_vsi_free_arrays(vsi); pf->vsi[vsi->idx] = NULL; if (vsi->idx < pf->next_vsi) -- 2.20.1