All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support
@ 2018-08-02  0:40 Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 02/13] i40e: Add setting pf->lan_vsi in a recovery mode init path Alice Michael
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Mariusz Stachura <mariusz.stachura@intel.com>

This patch introduces "recovery mode" to the i40e driver. It is
part of a new Any2Any idea of upgrading the firmware. In this
approach, it is required for the driver to have support for
"transition firmware", that is used for migrating from structured
to flat firmware image. In this new, very basic mode, i40e driver
must be able to handle particular IOCTL calls from the NVM Update
Tool and run a small set of AQ commands.

Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e.h         |   1 +
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c |  14 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c    | 212 ++++++++++++++++++++++---
 3 files changed, 206 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 7a80652..db911e3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -140,6 +140,7 @@ enum i40e_state_t {
 	__I40E_RESET_FAILED,
 	__I40E_PORT_SUSPENDED,
 	__I40E_VF_DISABLE,
+	__I40E_RECOVERY_MODE,
 	__I40E_MACVLAN_SYNC_PENDING,
 	__I40E_UDP_FILTER_SYNC_PENDING,
 	__I40E_TEMP_LINK_POLLING,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index abcd096..19606a2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -4829,6 +4829,12 @@ static int i40e_get_module_eeprom(struct net_device *netdev,
 	return 0;
 }
 
+static const struct ethtool_ops i40e_ethtool_recovery_mode_ops = {
+	.set_eeprom		= i40e_set_eeprom,
+	.get_eeprom_len		= i40e_get_eeprom_len,
+	.get_eeprom		= i40e_get_eeprom,
+};
+
 static const struct ethtool_ops i40e_ethtool_ops = {
 	.get_drvinfo		= i40e_get_drvinfo,
 	.get_regs_len		= i40e_get_regs_len,
@@ -4874,5 +4880,11 @@ static const struct ethtool_ops i40e_ethtool_ops = {
 
 void i40e_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->ethtool_ops = &i40e_ethtool_ops;
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf		*pf = np->vsi->back;
+
+	if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
+		netdev->ethtool_ops = &i40e_ethtool_ops;
+	else
+		netdev->ethtool_ops = &i40e_ethtool_recovery_mode_ops;
 }
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index a730f48..c4ba44c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -44,6 +44,8 @@ static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
 static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
 static int i40e_reset(struct i40e_pf *pf);
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
+static bool i40e_check_recovery_mode(struct i40e_pf *pf);
+static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw);
 static void i40e_fdir_sb_setup(struct i40e_pf *pf);
 static int i40e_veb_get_bw_info(struct i40e_veb *veb);
 static int i40e_get_capabilities(struct i40e_pf *pf,
@@ -276,8 +278,9 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
  **/
 void i40e_service_event_schedule(struct i40e_pf *pf)
 {
-	if (!test_bit(__I40E_DOWN, pf->state) &&
-	    !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
+	if ((!test_bit(__I40E_DOWN, pf->state) &&
+	     !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) ||
+	      test_bit(__I40E_RECOVERY_MODE, pf->state))
 		queue_work(i40e_wq, &pf->service_task);
 }
 
@@ -9332,7 +9335,14 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 	u32 val;
 	int v;
 
-	if (test_bit(__I40E_DOWN, pf->state))
+	if (pf->hw.mac.type == I40E_MAC_X722 &&
+	    test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
+	    i40e_check_recovery_mode(pf)) {
+		i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
+	}
+
+	if (test_bit(__I40E_DOWN, pf->state) &&
+	    !test_bit(__I40E_RECOVERY_MODE, pf->state))
 		goto clear_recovery;
 	dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -9358,8 +9368,14 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 	}
 
 	/* re-verify the eeprom if we just had an EMP reset */
-	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state))
+	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state)) {
 		i40e_verify_eeprom(pf);
+		/* bail out in case recovery mode was detected, as there is
+		 * no need for further configuration.
+		 */
+		if (test_bit(__I40E_RECOVERY_MODE, pf->state))
+			goto end_unlock;
+	}
 
 	i40e_clear_pxe_mode(hw);
 	ret = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
@@ -9827,25 +9843,31 @@ static void i40e_service_task(struct work_struct *work)
 	if (test_and_set_bit(__I40E_SERVICE_SCHED, pf->state))
 		return;
 
-	i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
-	i40e_sync_filters_subtask(pf);
-	i40e_reset_subtask(pf);
-	i40e_handle_mdd_event(pf);
-	i40e_vc_process_vflr_event(pf);
-	i40e_watchdog_subtask(pf);
-	i40e_fdir_reinit_subtask(pf);
-	if (test_and_clear_bit(__I40E_CLIENT_RESET, pf->state)) {
-		/* Client subtask will reopen next time through. */
-		i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], true);
-	} else {
-		i40e_client_subtask(pf);
-		if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
-				       pf->state))
-			i40e_notify_client_of_l2_param_changes(
+	if (!test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+		i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
+		i40e_sync_filters_subtask(pf);
+		i40e_reset_subtask(pf);
+		i40e_handle_mdd_event(pf);
+		i40e_vc_process_vflr_event(pf);
+		i40e_watchdog_subtask(pf);
+		i40e_fdir_reinit_subtask(pf);
+		if (pf->flags & __I40E_CLIENT_RESET) {
+			/* Client subtask will reopen next time through. */
+			i40e_notify_client_of_netdev_close(
+						pf->vsi[pf->lan_vsi], true);
+		} else {
+			i40e_client_subtask(pf);
+			if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
+					       pf->state))
+				i40e_notify_client_of_l2_param_changes(
 							pf->vsi[pf->lan_vsi]);
+		}
+		i40e_sync_udp_filters_subtask(pf);
+
+	} else {
+		i40e_reset_subtask(pf);
 	}
 	i40e_sync_filters_subtask(pf);
-	i40e_sync_udp_filters_subtask(pf);
 	i40e_clean_adminq_subtask(pf);
 
 	/* flush memory to make sure state is correct before next watchdog */
@@ -13524,6 +13546,137 @@ static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
 }
 
 /**
+ * i40e_check_recovery_mode - check if we are running transition firmware
+ * @pf: board private structure
+ *
+ * Check registers indicating the firmware runs in recovery mode. Sets the
+ * appropriate driver state.
+ *
+ * Returns true if the recovery mode was detected, false otherwise
+ **/
+static bool i40e_check_recovery_mode(struct i40e_pf *pf)
+{
+	u32 val = rd32(&pf->hw, I40E_GL_FWSTS);
+
+	if (val & I40E_GL_FWSTS_FWS1B_MASK) {
+		dev_info(&pf->pdev->dev, "transition FW detected, running in recovery mode\n");
+		set_bit(__I40E_RECOVERY_MODE, pf->state);
+
+		return true;
+	}
+	clear_bit(__I40E_RECOVERY_MODE, pf->state);
+
+	return false;
+}
+
+/**
+ * i40e_init_recovery_mode - initialize subsystems needed in recovery mode
+ * @pf: board private structure
+ * @hw: ptr to the hardware info
+ *
+ * This function does a minimal setup of all subsystems needed for running
+ * recovery mode.
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
+{
+	struct i40e_vsi *vsi;
+	int err;
+	int v_idx;
+
+	err = i40e_sw_init(pf);
+	if (err) {
+		dev_info(&pf->pdev->dev, "sw_init failed: %d\n", err);
+		goto err_sw_init;
+	}
+
+	/* allow a platform config to override the HW addr */
+	i40e_get_platform_mac_addr(pf->pdev, pf);
+
+	if (!is_valid_ether_addr(hw->mac.addr)) {
+		/* normally we would return -EIO here */
+		dev_info(&pf->pdev->dev, "invalid MAC address %pM\n",
+			 hw->mac.addr);
+	} else {
+		dev_info(&pf->pdev->dev, "MAC address: %pM\n", hw->mac.addr);
+	}
+	ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
+	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
+	if (is_valid_ether_addr(hw->mac.port_addr))
+		pf->hw_features |= I40E_HW_PORT_ID_VALID;
+
+	pci_save_state(pf->pdev);
+
+	/* set up periodic task facility */
+	timer_setup(&pf->service_timer, i40e_service_timer, (unsigned long)pf);
+	pf->service_timer_period = HZ;
+
+	INIT_WORK(&pf->service_task, i40e_service_task);
+	clear_bit(__I40E_SERVICE_SCHED, pf->state);
+
+	err = i40e_init_interrupt_scheme(pf);
+	if (err)
+		goto err_switch_setup;
+
+	/* The number of VSIs reported by the FW is the minimum guaranteed
+	 * to us; HW supports far more and we share the remaining pool with
+	 * the other PFs. We allocate space for more than the guarantee with
+	 * the understanding that we might not get them all later.
+	 */
+	if (pf->hw.func_caps.num_vsis < I40E_MIN_VSI_ALLOC)
+		pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC;
+	else
+		pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
+
+	/* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */
+	pf->vsi = kcalloc(pf->num_alloc_vsi, sizeof(struct i40e_vsi *),
+			  GFP_KERNEL);
+	if (!pf->vsi) {
+		err = -ENOMEM;
+		goto err_switch_setup;
+	}
+
+	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
+	if (v_idx < 0)
+		goto err_switch_setup;
+	vsi = pf->vsi[v_idx];
+	if (!vsi)
+		goto err_switch_setup;
+	err = i40e_config_netdev(vsi);
+	if (err)
+		goto err_switch_setup;
+	err = register_netdev(vsi->netdev);
+	if (err)
+		goto err_switch_setup;
+	i40e_dbg_pf_init(pf);
+
+	/* tell the firmware that we're starting */
+	i40e_send_version(pf);
+
+	/* since everything's happy, start the service_task timer */
+	mod_timer(&pf->service_timer,
+		  round_jiffies(jiffies + pf->service_timer_period));
+
+	return 0;
+
+err_switch_setup:
+	i40e_reset_interrupt_capability(pf);
+	del_timer_sync(&pf->service_timer);
+err_sw_init:
+	i40e_shutdown_adminq(hw);
+	iounmap(hw->hw_addr);
+	kfree(pf);
+	pci_disable_pcie_error_reporting(pf->pdev);
+	pci_release_selected_regions(pf->pdev,
+				     pci_select_bars(pf->pdev,
+						     IORESOURCE_MEM));
+	pci_disable_device(pf->pdev);
+
+	return err;
+}
+
+/**
  * i40e_probe - Device initialization routine
  * @pdev: PCI device information struct
  * @ent: entry in i40e_pci_tbl
@@ -13708,6 +13861,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_warn(&pdev->dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues with your hardware. If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
 
 	i40e_clear_pxe_mode(hw);
+
+	if (pf->hw.mac.type == I40E_MAC_X722)
+		if (i40e_check_recovery_mode(pf))
+			return i40e_init_recovery_mode(pf, hw);
+
 	err = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
 	if (err)
 		goto err_adminq_setup;
@@ -14100,6 +14258,19 @@ static void i40e_remove(struct pci_dev *pdev)
 	if (pf->service_task.func)
 		cancel_work_sync(&pf->service_task);
 
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+		struct i40e_vsi *vsi = pf->vsi[0];
+
+		/* We know that we have allocated only one vsi for this PF,
+		 * * it was just for registering netdevice, so the interface
+		 * could be visible in the 'ifconfig' output
+		 */
+		unregister_netdev(vsi->netdev);
+		free_netdev(vsi->netdev);
+
+		goto unmap;
+	}
+
 	/* Client close must be called explicitly here because the timer
 	 * has been stopped.
 	 */
@@ -14149,6 +14320,7 @@ static void i40e_remove(struct pci_dev *pdev)
 				 ret_code);
 	}
 
+unmap:
 	/* shutdown the adminq */
 	i40e_shutdown_adminq(hw);
 
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 02/13] i40e: Add setting pf->lan_vsi in a recovery mode init path
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 03/13] i40e: Don't read MAC address in recovery mode Alice Michael
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Pawe? Jab?o?ski <pawel.jablonski@intel.com>

This patch fixes the issue with shutdowning the system, after
entering the recovery mode. This is needed in the upgrade
scenario. Without this the driver tries to access an array out of
bounds.

Signed-off-by: Pawe? Jab?o?ski <pawel.jablonski@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index c4ba44c..c9b1d0c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13640,6 +13640,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
 	if (v_idx < 0)
 		goto err_switch_setup;
+	pf->lan_vsi = v_idx;
 	vsi = pf->vsi[v_idx];
 	if (!vsi)
 		goto err_switch_setup;
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 03/13] i40e: Don't read MAC address in recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 02/13] i40e: Add setting pf->lan_vsi in a recovery mode init path Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 04/13] i40e: Display message when entering and leaving " Alice Michael
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

This patch removes reading MAC address via AQC
"Manage MAC address read command" in recovery mode
since it's not supported.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index c9b1d0c..0a1ecdf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13591,21 +13591,6 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 		goto err_sw_init;
 	}
 
-	/* allow a platform config to override the HW addr */
-	i40e_get_platform_mac_addr(pf->pdev, pf);
-
-	if (!is_valid_ether_addr(hw->mac.addr)) {
-		/* normally we would return -EIO here */
-		dev_info(&pf->pdev->dev, "invalid MAC address %pM\n",
-			 hw->mac.addr);
-	} else {
-		dev_info(&pf->pdev->dev, "MAC address: %pM\n", hw->mac.addr);
-	}
-	ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
-	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
-	if (is_valid_ether_addr(hw->mac.port_addr))
-		pf->hw_features |= I40E_HW_PORT_ID_VALID;
-
 	pci_save_state(pf->pdev);
 
 	/* set up periodic task facility */
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 04/13] i40e: Display message when entering and leaving recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 02/13] i40e: Add setting pf->lan_vsi in a recovery mode init path Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 03/13] i40e: Don't read MAC address in recovery mode Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 05/13] i40e: Enable interrupts in " Alice Michael
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Filip Sadowski <filip.sadowski@intel.com>

This patch adds notification in dmesg when the driver detects the NIC
entered recovery mode. It also displays appropriate information when the
adapter leaves recovery mode restoring normal functionality.

Signed-off-by: Filip Sadowski <filip.sadowski@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 0a1ecdf..c1bccf8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13559,12 +13559,14 @@ static bool i40e_check_recovery_mode(struct i40e_pf *pf)
 	u32 val = rd32(&pf->hw, I40E_GL_FWSTS);
 
 	if (val & I40E_GL_FWSTS_FWS1B_MASK) {
-		dev_info(&pf->pdev->dev, "transition FW detected, running in recovery mode\n");
+		dev_notice(&pf->pdev->dev, "Firmware recovery mode detected. Limiting functionality.\n");
+		dev_notice(&pf->pdev->dev, "Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
 		set_bit(__I40E_RECOVERY_MODE, pf->state);
 
 		return true;
 	}
-	clear_bit(__I40E_RECOVERY_MODE, pf->state);
+	if (test_and_clear_bit(__I40E_RECOVERY_MODE, pf->state))
+		dev_info(&pf->pdev->dev, "Reinitializing in normal mode with full functionality.\n");
 
 	return false;
 }
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 05/13] i40e: Enable interrupts in recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (2 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 04/13] i40e: Display message when entering and leaving " Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 06/13] i40e: Limit initialization when going out of " Alice Michael
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

This patch enables interrupts in recovery mode. Thanks to
this, NVM update process speed is significantly increased since
we do not wait for watchdog to trigger the driver to take a look
at AdminQ in order to check if there is an event to read.
Instead we are immediately notified via an interrupt.

Additionally this patch corrects interrupts reinitialization
in i40e_rebuild.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 104 +++++++++++++++++++++++-----
 1 file changed, 85 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index c1bccf8..d53938c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -44,6 +44,7 @@ static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
 static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
 static int i40e_reset(struct i40e_pf *pf);
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
+static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf);
 static bool i40e_check_recovery_mode(struct i40e_pf *pf);
 static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw);
 static void i40e_fdir_sb_setup(struct i40e_pf *pf);
@@ -3929,7 +3930,8 @@ static irqreturn_t i40e_intr(int irq, void *data)
 enable_intr:
 	/* re-enable interrupt causes */
 	wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
-	if (!test_bit(__I40E_DOWN, pf->state)) {
+	if (!test_bit(__I40E_DOWN, pf->state) ||
+	    test_bit(__I40E_RECOVERY_MODE, pf->state)) {
 		i40e_service_event_schedule(pf);
 		i40e_irq_dynamic_enable_icr0(pf);
 	}
@@ -9335,8 +9337,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 	u32 val;
 	int v;
 
-	if (pf->hw.mac.type == I40E_MAC_X722 &&
-	    test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
+	if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
 	    i40e_check_recovery_mode(pf)) {
 		i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
 	}
@@ -9370,11 +9371,24 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 	/* re-verify the eeprom if we just had an EMP reset */
 	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state)) {
 		i40e_verify_eeprom(pf);
+	}
+
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+		if (i40e_get_capabilities(pf,
+					  i40e_aqc_opc_list_func_capabilities))
+			goto end_unlock;
+
+		/* reinit the misc interrupt */
+		if (i40e_setup_misc_vector_for_recovery_mode(pf))
+			goto end_unlock;
+
+		/* tell the firmware that we're starting */
+		i40e_send_version(pf);
+
 		/* bail out in case recovery mode was detected, as there is
 		 * no need for further configuration.
 		 */
-		if (test_bit(__I40E_RECOVERY_MODE, pf->state))
-			goto end_unlock;
+		goto end_unlock;
 	}
 
 	i40e_clear_pxe_mode(hw);
@@ -10682,6 +10696,48 @@ static int i40e_restore_interrupt_scheme(struct i40e_pf *pf)
 }
 
 /**
+ * i40e_setup_misc_vector_for_recovery_mode - Setup the misc vector to handle
+ * non queue events in recovery mode
+ * @pf: board private structure
+ *
+ * This sets up the handler for MSIX 0 or MSI/legacy, which is used to manage
+ * the non-queue interrupts, e.g. AdminQ and errors in recovery mode.
+ * This is handled differently than in recovery mode since no Tx/Rx resources
+ * are being allocated.
+ **/
+static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf)
+{
+	int err;
+
+	if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
+		err = i40e_setup_misc_vector(pf);
+
+		if (err) {
+			dev_info(&pf->pdev->dev,
+				 "MSI-X misc vector request failed, error %d\n",
+				 err);
+			return err;
+		}
+	} else {
+		u32 flags = pf->flags & I40E_FLAG_MSI_ENABLED ? 0 : IRQF_SHARED;
+
+		err = request_irq(pf->pdev->irq, i40e_intr, flags,
+				  pf->int_name, pf);
+
+		if (err) {
+			dev_info(&pf->pdev->dev,
+				 "MSI/legacy misc vector request failed, error %d\n",
+				 err);
+			return err;
+		}
+		i40e_enable_misc_int_causes(pf);
+		i40e_irq_dynamic_enable_icr0(pf);
+	}
+
+	return 0;
+}
+
+/**
  * i40e_setup_misc_vector - Setup the misc vector to handle non queue events
  * @pf: board private structure
  *
@@ -13587,12 +13643,6 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 	int err;
 	int v_idx;
 
-	err = i40e_sw_init(pf);
-	if (err) {
-		dev_info(&pf->pdev->dev, "sw_init failed: %d\n", err);
-		goto err_sw_init;
-	}
-
 	pci_save_state(pf->pdev);
 
 	/* set up periodic task facility */
@@ -13616,7 +13666,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 	else
 		pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
 
-	/* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */
+	/* Set up the vsi struct and our local tracking of the MAIN PF vsi. */
 	pf->vsi = kcalloc(pf->num_alloc_vsi, sizeof(struct i40e_vsi *),
 			  GFP_KERNEL);
 	if (!pf->vsi) {
@@ -13624,6 +13674,9 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 		goto err_switch_setup;
 	}
 
+	/* We allocate one VSI which is needed as absolute minimum
+	 * in order to register the netdev
+	 */
 	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
 	if (v_idx < 0)
 		goto err_switch_setup;
@@ -13631,6 +13684,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 	vsi = pf->vsi[v_idx];
 	if (!vsi)
 		goto err_switch_setup;
+	vsi->alloc_queue_pairs = 1;
 	err = i40e_config_netdev(vsi);
 	if (err)
 		goto err_switch_setup;
@@ -13639,6 +13693,10 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 		goto err_switch_setup;
 	i40e_dbg_pf_init(pf);
 
+	err = i40e_setup_misc_vector_for_recovery_mode(pf);
+	if (err)
+		goto err_switch_setup;
+
 	/* tell the firmware that we're starting */
 	i40e_send_version(pf);
 
@@ -13651,7 +13709,6 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 err_switch_setup:
 	i40e_reset_interrupt_capability(pf);
 	del_timer_sync(&pf->service_timer);
-err_sw_init:
 	i40e_shutdown_adminq(hw);
 	iounmap(hw->hw_addr);
 	kfree(pf);
@@ -13849,11 +13906,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_warn(&pdev->dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues with your hardware. If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
 
 	i40e_clear_pxe_mode(hw);
-
-	if (pf->hw.mac.type == I40E_MAC_X722)
-		if (i40e_check_recovery_mode(pf))
-			return i40e_init_recovery_mode(pf, hw);
-
 	err = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
 	if (err)
 		goto err_adminq_setup;
@@ -13864,6 +13916,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_sw_init;
 	}
 
+	if (i40e_check_recovery_mode(pf))
+		return i40e_init_recovery_mode(pf, hw);
+
 	err = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
 				hw->func_caps.num_rx_qp, 0, 0);
 	if (err) {
@@ -14316,11 +14371,22 @@ static void i40e_remove(struct pci_dev *pdev)
 	mutex_destroy(&hw->aq.arq_mutex);
 	mutex_destroy(&hw->aq.asq_mutex);
 
+	/* Free MSI/legacy interrupt 0 when in recovery mode.
+	 * This is normally done in i40e_vsi_free_irq on
+	 * VSI close but since recovery mode doesn't allow to up
+	 * an interface and we do not allocate all Rx/Tx resources
+	 * for it we'll just do it here
+	 */
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state) &&
+	    !(pf->flags & I40E_FLAG_MSIX_ENABLED))
+		free_irq(pf->pdev->irq, pf);
+
 	/* Clear all dynamic memory lists of rings, q_vectors, and VSIs */
 	i40e_clear_interrupt_scheme(pf);
 	for (i = 0; i < pf->num_alloc_vsi; i++) {
 		if (pf->vsi[i]) {
-			i40e_vsi_clear_rings(pf->vsi[i]);
+			if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
+				i40e_vsi_clear_rings(pf->vsi[i]);
 			i40e_vsi_clear(pf->vsi[i]);
 			pf->vsi[i] = NULL;
 		}
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 06/13] i40e: Limit initialization when going out of recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (3 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 05/13] i40e: Enable interrupts in " Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 07/13] i40e: Check for recovery mode before doing PF reset Alice Michael
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

This patch limits adapter (re)initialization when going out
of recovery mode when the driver was initially loaded in
recovery mode and no SW initialization has been done.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d53938c..d7eeced 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9330,6 +9330,7 @@ static int i40e_reset(struct i40e_pf *pf)
  **/
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 {
+	int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state);
 	struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
 	struct i40e_hw *hw = &pf->hw;
 	u8 set_fc_aq_fail = 0;
@@ -9343,7 +9344,8 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 	}
 
 	if (test_bit(__I40E_DOWN, pf->state) &&
-	    !test_bit(__I40E_RECOVERY_MODE, pf->state))
+	    !test_bit(__I40E_RECOVERY_MODE, pf->state) &&
+	    !old_recovery_mode_bit)
 		goto clear_recovery;
 	dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -9373,7 +9375,8 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 		i40e_verify_eeprom(pf);
 	}
 
-	if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state) ||
+	    old_recovery_mode_bit) {
 		if (i40e_get_capabilities(pf,
 					  i40e_aqc_opc_list_func_capabilities))
 			goto end_unlock;
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 07/13] i40e: Check for recovery mode before doing PF reset
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (4 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 06/13] i40e: Limit initialization when going out of " Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 08/13] i40e: Reorder irq and adminq deinitialization in i40e_remove Alice Michael
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Mariusz Stachura <mariusz.stachura@intel.com>

This patch moves call to i40e_check_recovery_mode() before we do PF
resets. Previous behavior was proven to be working on A2A scenario,
but was not sufficient for addressing other RecoveryMode cases.

Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d7eeced..5720d40 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13848,12 +13848,15 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/* Reset here to make sure all is clean and to define PF 'n' */
 	i40e_clear_hw(hw);
-	err = i40e_pf_reset(hw);
-	if (err) {
-		dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err);
-		goto err_pf_reset;
+	if (!i40e_check_recovery_mode(pf)) {
+		err = i40e_pf_reset(hw);
+		if (err) {
+			dev_info(&pdev->dev, "Initial pf_reset failed: %d\n",
+				 err);
+			goto err_pf_reset;
+		}
+		pf->pfr_count++;
 	}
-	pf->pfr_count++;
 
 	hw->aq.num_arq_entries = I40E_AQ_LEN;
 	hw->aq.num_asq_entries = I40E_AQ_LEN;
@@ -13919,7 +13922,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_sw_init;
 	}
 
-	if (i40e_check_recovery_mode(pf))
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state))
 		return i40e_init_recovery_mode(pf, hw);
 
 	err = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 08/13] i40e: Reorder irq and adminq deinitialization in i40e_remove
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (5 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 07/13] i40e: Check for recovery mode before doing PF reset Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 09/13] i40e: Set netdev_registered when registering netdev in recovery mode Alice Michael
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

This is needed to allow changing of deinitialization flow in
order to skip freeing uninitialized irq when in recovery mode.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 5720d40..725b2de 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -14370,13 +14370,6 @@ static void i40e_remove(struct pci_dev *pdev)
 	}
 
 unmap:
-	/* shutdown the adminq */
-	i40e_shutdown_adminq(hw);
-
-	/* destroy the locks only once, here */
-	mutex_destroy(&hw->aq.arq_mutex);
-	mutex_destroy(&hw->aq.asq_mutex);
-
 	/* Free MSI/legacy interrupt 0 when in recovery mode.
 	 * This is normally done in i40e_vsi_free_irq on
 	 * VSI close but since recovery mode doesn't allow to up
@@ -14398,6 +14391,13 @@ static void i40e_remove(struct pci_dev *pdev)
 		}
 	}
 
+	/* shutdown the adminq */
+	i40e_shutdown_adminq(hw);
+
+	/* destroy the locks only once, here */
+	mutex_destroy(&hw->aq.arq_mutex);
+	mutex_destroy(&hw->aq.asq_mutex);
+
 	for (i = 0; i < I40E_MAX_VEB; i++) {
 		kfree(pf->veb[i]);
 		pf->veb[i] = NULL;
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 09/13] i40e: Set netdev_registered when registering netdev in recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (6 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 08/13] i40e: Reorder irq and adminq deinitialization in i40e_remove Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 10/13] i40e: Reinitialize interrupt scheme when going out of " Alice Michael
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

When initializing adapter in recovery mode we've forgotten to set
netdev_registered to true causing kernel BUGs when we unload the module
after successful recovery. This patch sets this flag correctly as it was
supposed to be set.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 725b2de..ca701e0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13694,6 +13694,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
 	err = register_netdev(vsi->netdev);
 	if (err)
 		goto err_switch_setup;
+	vsi->netdev_registered = true;
 	i40e_dbg_pf_init(pf);
 
 	err = i40e_setup_misc_vector_for_recovery_mode(pf);
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 10/13] i40e: Reinitialize interrupt scheme when going out of recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (7 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 09/13] i40e: Set netdev_registered when registering netdev in recovery mode Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 11/13] i40e: Prevent kernel panic when rebooting server while NIC is in recovery Alice Michael
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

When we go out of recovery mode (after a reset is triggerred) we have
to free IRQ, clear and reinitialize the interrupt scheme to restore
full interrupt functionality.

This patch fixes a kernel panic in the event of driver being unloaded
after performing a recovery with nvmupdate - which was caused by calling
pci_disable_msi() while an interrupt was still registered in the system.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index ca701e0..3b1740d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -45,6 +45,7 @@ static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
 static int i40e_reset(struct i40e_pf *pf);
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
 static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf);
+static int i40e_restore_interrupt_scheme(struct i40e_pf *pf);
 static bool i40e_check_recovery_mode(struct i40e_pf *pf);
 static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw);
 static void i40e_fdir_sb_setup(struct i40e_pf *pf);
@@ -9375,15 +9376,32 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 		i40e_verify_eeprom(pf);
 	}
 
+	/* if we are going out of or into recovery mode we have to act
+	 * accordingly with regard to resources initialization
+	 * and deinitialization
+	 */
 	if (test_bit(__I40E_RECOVERY_MODE, pf->state) ||
 	    old_recovery_mode_bit) {
 		if (i40e_get_capabilities(pf,
 					  i40e_aqc_opc_list_func_capabilities))
 			goto end_unlock;
 
-		/* reinit the misc interrupt */
-		if (i40e_setup_misc_vector_for_recovery_mode(pf))
-			goto end_unlock;
+		if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+			/* we're staying in recovery mode so we'll reinitialize
+			 * misc vector here
+			 */
+			if (i40e_setup_misc_vector_for_recovery_mode(pf))
+				goto end_unlock;
+		} else {
+			/* we're going out of recovery mode so we'll free
+			 * the IRQ allocated specifically for recovery mode
+			 * and restore the interrupt scheme
+			 */
+			free_irq(pf->pdev->irq, pf);
+			i40e_clear_interrupt_scheme(pf);
+			if (i40e_restore_interrupt_scheme(pf))
+				goto end_unlock;
+		}
 
 		/* tell the firmware that we're starting */
 		i40e_send_version(pf);
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 11/13] i40e: Prevent kernel panic when rebooting server while NIC is in recovery
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (8 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 10/13] i40e: Reinitialize interrupt scheme when going out of " Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 12/13] i40e: Lock the rtnl lock when restoring interrupt scheme for recovery mode Alice Michael
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

If user triggers a reboot and the adapter is in recovery
mode, we are not taking this fact into account and we are
not freeing irq that has been specifically allocated for
NVM update/recover purposes, what bothers kernel when we issue
pci_disable_msi when irq still has an interrupt registered.
This patch fixes that and ensures that we free this irq.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 3b1740d..ff04dc4 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -14627,6 +14627,16 @@ static void i40e_shutdown(struct pci_dev *pdev)
 	wr32(hw, I40E_PFPM_WUFC,
 	     (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
 
+	/* Free MSI/legacy interrupt 0 when in recovery mode.
+	 * This is normally done in i40e_vsi_free_irq on
+	 * VSI close but since recovery mode doesn't allow to up
+	 * an interface and we do not allocate all Rx/Tx resources
+	 * for it we'll just do it here
+	 */
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state) &&
+	    !(pf->flags & I40E_FLAG_MSIX_ENABLED))
+		free_irq(pf->pdev->irq, pf);
+
 	i40e_clear_interrupt_scheme(pf);
 
 	if (system_state == SYSTEM_POWER_OFF) {
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 12/13] i40e: Lock the rtnl lock when restoring interrupt scheme for recovery mode
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (9 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 11/13] i40e: Prevent kernel panic when rebooting server while NIC is in recovery Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 13/13] i40e: set vsi->netdev to NULL after free_netdev() Alice Michael
  2018-08-03 16:45 ` [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Shannon Nelson
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

When going out of recovery mode we have to check if rtnl lock is locked,
if it isn't then we have to lock it since i40e_restore_interrupt_scheme
will reinitialize queues and this needs to be done under the lock.

This patch fixes it by adding a rtnl_lock() call when the lock is not
held.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index ff04dc4..e46f8ab 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9393,6 +9393,8 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 			if (i40e_setup_misc_vector_for_recovery_mode(pf))
 				goto end_unlock;
 		} else {
+			if (!lock_acquired)
+				rtnl_lock();
 			/* we're going out of recovery mode so we'll free
 			 * the IRQ allocated specifically for recovery mode
 			 * and restore the interrupt scheme
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 13/13] i40e: set vsi->netdev to NULL after free_netdev()
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (10 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 12/13] i40e: Lock the rtnl lock when restoring interrupt scheme for recovery mode Alice Michael
@ 2018-08-02  0:40 ` Alice Michael
  2018-08-03 16:45 ` [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Shannon Nelson
  12 siblings, 0 replies; 14+ messages in thread
From: Alice Michael @ 2018-08-02  0:40 UTC (permalink / raw)
  To: intel-wired-lan

From: Patryk Ma?ek <patryk.malek@intel.com>

After adding a special case for recovery mode in i40e_remove
we have forgotten to set vsi->netdev to NULL after calling free_netdev()
on it. This patch fixes that.

Signed-off-by: Patryk Ma?ek <patryk.malek@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index e46f8ab..4300483 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -14337,6 +14337,7 @@ static void i40e_remove(struct pci_dev *pdev)
 		 */
 		unregister_netdev(vsi->netdev);
 		free_netdev(vsi->netdev);
+		vsi->netdev = NULL;
 
 		goto unmap;
 	}
-- 
2.9.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support
  2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
                   ` (11 preceding siblings ...)
  2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 13/13] i40e: set vsi->netdev to NULL after free_netdev() Alice Michael
@ 2018-08-03 16:45 ` Shannon Nelson
  12 siblings, 0 replies; 14+ messages in thread
From: Shannon Nelson @ 2018-08-03 16:45 UTC (permalink / raw)
  To: intel-wired-lan

On 8/1/2018 5:40 PM, Alice Michael wrote:
> From: Mariusz Stachura <mariusz.stachura@intel.com>
> 
> This patch introduces "recovery mode" to the i40e driver. It is
> part of a new Any2Any idea of upgrading the firmware. In this
> approach, it is required for the driver to have support for
> "transition firmware", that is used for migrating from structured
> to flat firmware image. In this new, very basic mode, i40e driver
> must be able to handle particular IOCTL calls from the NVM Update
> Tool and run a small set of AQ commands.

Since all the followup patches are fixes to this patch, rather than 
adding more functionality and features, why are they not simply rolled 
into this one and made a single correct patch?  If you know this one is 
broken, why try to push it upstream?

Please roll the fixes into this and don't send a known broken patch 
upstream.

... and a couple more simple comments below.

sln

> 
> Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
> ---
>   drivers/net/ethernet/intel/i40e/i40e.h         |   1 +
>   drivers/net/ethernet/intel/i40e/i40e_ethtool.c |  14 +-
>   drivers/net/ethernet/intel/i40e/i40e_main.c    | 212 ++++++++++++++++++++++---
>   3 files changed, 206 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index 7a80652..db911e3 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -140,6 +140,7 @@ enum i40e_state_t {
>   	__I40E_RESET_FAILED,
>   	__I40E_PORT_SUSPENDED,
>   	__I40E_VF_DISABLE,
> +	__I40E_RECOVERY_MODE,
>   	__I40E_MACVLAN_SYNC_PENDING,
>   	__I40E_UDP_FILTER_SYNC_PENDING,
>   	__I40E_TEMP_LINK_POLLING,
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index abcd096..19606a2 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -4829,6 +4829,12 @@ static int i40e_get_module_eeprom(struct net_device *netdev,
>   	return 0;
>   }
>   
> +static const struct ethtool_ops i40e_ethtool_recovery_mode_ops = {
> +	.set_eeprom		= i40e_set_eeprom,
> +	.get_eeprom_len		= i40e_get_eeprom_len,
> +	.get_eeprom		= i40e_get_eeprom,
> +};
> +
>   static const struct ethtool_ops i40e_ethtool_ops = {
>   	.get_drvinfo		= i40e_get_drvinfo,
>   	.get_regs_len		= i40e_get_regs_len,
> @@ -4874,5 +4880,11 @@ static const struct ethtool_ops i40e_ethtool_ops = {
>   
>   void i40e_set_ethtool_ops(struct net_device *netdev)
>   {
> -	netdev->ethtool_ops = &i40e_ethtool_ops;
> +	struct i40e_netdev_priv *np = netdev_priv(netdev);
> +	struct i40e_pf		*pf = np->vsi->back;
> +
> +	if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
> +		netdev->ethtool_ops = &i40e_ethtool_ops;
> +	else
> +		netdev->ethtool_ops = &i40e_ethtool_recovery_mode_ops;

Just to be picky and git rid of negative logic, I would turn this around to

	if (test_bit(__I40E_RECOVERY_MODE, pf->state))
		netdev->ethtool_ops = &i40e_ethtool_recovery_mode_ops;
	else
		netdev->ethtool_ops = &i40e_ethtool_ops;


>   }
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index a730f48..c4ba44c 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -44,6 +44,8 @@ static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
>   static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
>   static int i40e_reset(struct i40e_pf *pf);
>   static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
> +static bool i40e_check_recovery_mode(struct i40e_pf *pf);
> +static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw);
>   static void i40e_fdir_sb_setup(struct i40e_pf *pf);
>   static int i40e_veb_get_bw_info(struct i40e_veb *veb);
>   static int i40e_get_capabilities(struct i40e_pf *pf,
> @@ -276,8 +278,9 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
>    **/
>   void i40e_service_event_schedule(struct i40e_pf *pf)
>   {
> -	if (!test_bit(__I40E_DOWN, pf->state) &&
> -	    !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
> +	if ((!test_bit(__I40E_DOWN, pf->state) &&
> +	     !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) ||
> +	      test_bit(__I40E_RECOVERY_MODE, pf->state))
>   		queue_work(i40e_wq, &pf->service_task);
>   }
>   
> @@ -9332,7 +9335,14 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
>   	u32 val;
>   	int v;
>   
> -	if (test_bit(__I40E_DOWN, pf->state))
> +	if (pf->hw.mac.type == I40E_MAC_X722 &&
> +	    test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
> +	    i40e_check_recovery_mode(pf)) {
> +		i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
> +	}
> +
> +	if (test_bit(__I40E_DOWN, pf->state) &&
> +	    !test_bit(__I40E_RECOVERY_MODE, pf->state))
>   		goto clear_recovery;
>   	dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
>   
> @@ -9358,8 +9368,14 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
>   	}
>   
>   	/* re-verify the eeprom if we just had an EMP reset */
> -	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state))
> +	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state)) {
>   		i40e_verify_eeprom(pf);
> +		/* bail out in case recovery mode was detected, as there is
> +		 * no need for further configuration.
> +		 */
> +		if (test_bit(__I40E_RECOVERY_MODE, pf->state))
> +			goto end_unlock;
> +	}
>   
>   	i40e_clear_pxe_mode(hw);
>   	ret = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
> @@ -9827,25 +9843,31 @@ static void i40e_service_task(struct work_struct *work)
>   	if (test_and_set_bit(__I40E_SERVICE_SCHED, pf->state))
>   		return;
>   
> -	i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
> -	i40e_sync_filters_subtask(pf);
> -	i40e_reset_subtask(pf);
> -	i40e_handle_mdd_event(pf);
> -	i40e_vc_process_vflr_event(pf);
> -	i40e_watchdog_subtask(pf);
> -	i40e_fdir_reinit_subtask(pf);
> -	if (test_and_clear_bit(__I40E_CLIENT_RESET, pf->state)) {
> -		/* Client subtask will reopen next time through. */
> -		i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], true);
> -	} else {
> -		i40e_client_subtask(pf);
> -		if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
> -				       pf->state))
> -			i40e_notify_client_of_l2_param_changes(
> +	if (!test_bit(__I40E_RECOVERY_MODE, pf->state)) {
> +		i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
> +		i40e_sync_filters_subtask(pf);
> +		i40e_reset_subtask(pf);
> +		i40e_handle_mdd_event(pf);
> +		i40e_vc_process_vflr_event(pf);
> +		i40e_watchdog_subtask(pf);
> +		i40e_fdir_reinit_subtask(pf);
> +		if (pf->flags & __I40E_CLIENT_RESET) {
> +			/* Client subtask will reopen next time through. */
> +			i40e_notify_client_of_netdev_close(
> +						pf->vsi[pf->lan_vsi], true);
> +		} else {
> +			i40e_client_subtask(pf);
> +			if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
> +					       pf->state))
> +				i40e_notify_client_of_l2_param_changes(
>   							pf->vsi[pf->lan_vsi]);
> +		}
> +		i40e_sync_udp_filters_subtask(pf);
> +
> +	} else {
> +		i40e_reset_subtask(pf);
>   	}
>   	i40e_sync_filters_subtask(pf);
> -	i40e_sync_udp_filters_subtask(pf);
>   	i40e_clean_adminq_subtask(pf);
>   
>   	/* flush memory to make sure state is correct before next watchdog */
> @@ -13524,6 +13546,137 @@ static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
>   }
>   
>   /**
> + * i40e_check_recovery_mode - check if we are running transition firmware
> + * @pf: board private structure
> + *
> + * Check registers indicating the firmware runs in recovery mode. Sets the
> + * appropriate driver state.
> + *
> + * Returns true if the recovery mode was detected, false otherwise
> + **/
> +static bool i40e_check_recovery_mode(struct i40e_pf *pf)
> +{
> +	u32 val = rd32(&pf->hw, I40E_GL_FWSTS);
> +
> +	if (val & I40E_GL_FWSTS_FWS1B_MASK) {
> +		dev_info(&pf->pdev->dev, "transition FW detected, running in recovery mode\n");
> +		set_bit(__I40E_RECOVERY_MODE, pf->state);
> +
> +		return true;
> +	}
> +	clear_bit(__I40E_RECOVERY_MODE, pf->state);
> +
> +	return false;
> +}
> +
> +/**
> + * i40e_init_recovery_mode - initialize subsystems needed in recovery mode
> + * @pf: board private structure
> + * @hw: ptr to the hardware info
> + *
> + * This function does a minimal setup of all subsystems needed for running
> + * recovery mode.
> + *
> + * Returns 0 on success, negative on failure
> + **/
> +static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
> +{
> +	struct i40e_vsi *vsi;
> +	int err;
> +	int v_idx;
> +
> +	err = i40e_sw_init(pf);
> +	if (err) {
> +		dev_info(&pf->pdev->dev, "sw_init failed: %d\n", err);
> +		goto err_sw_init;
> +	}
> +
> +	/* allow a platform config to override the HW addr */
> +	i40e_get_platform_mac_addr(pf->pdev, pf);
> +
> +	if (!is_valid_ether_addr(hw->mac.addr)) {
> +		/* normally we would return -EIO here */
> +		dev_info(&pf->pdev->dev, "invalid MAC address %pM\n",
> +			 hw->mac.addr);
> +	} else {
> +		dev_info(&pf->pdev->dev, "MAC address: %pM\n", hw->mac.addr);
> +	}
> +	ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
> +	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
> +	if (is_valid_ether_addr(hw->mac.port_addr))
> +		pf->hw_features |= I40E_HW_PORT_ID_VALID;
> +
> +	pci_save_state(pf->pdev);
> +
> +	/* set up periodic task facility */
> +	timer_setup(&pf->service_timer, i40e_service_timer, (unsigned long)pf);
> +	pf->service_timer_period = HZ;
> +
> +	INIT_WORK(&pf->service_task, i40e_service_task);
> +	clear_bit(__I40E_SERVICE_SCHED, pf->state);
> +
> +	err = i40e_init_interrupt_scheme(pf);
> +	if (err)
> +		goto err_switch_setup;
> +
> +	/* The number of VSIs reported by the FW is the minimum guaranteed
> +	 * to us; HW supports far more and we share the remaining pool with
> +	 * the other PFs. We allocate space for more than the guarantee with
> +	 * the understanding that we might not get them all later.
> +	 */
> +	if (pf->hw.func_caps.num_vsis < I40E_MIN_VSI_ALLOC)
> +		pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC;
> +	else
> +		pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
> +
> +	/* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */
> +	pf->vsi = kcalloc(pf->num_alloc_vsi, sizeof(struct i40e_vsi *),
> +			  GFP_KERNEL);
> +	if (!pf->vsi) {
> +		err = -ENOMEM;
> +		goto err_switch_setup;
> +	}
> +
> +	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
> +	if (v_idx < 0)
> +		goto err_switch_setup;
> +	vsi = pf->vsi[v_idx];
> +	if (!vsi)
> +		goto err_switch_setup;
> +	err = i40e_config_netdev(vsi);
> +	if (err)
> +		goto err_switch_setup;
> +	err = register_netdev(vsi->netdev);
> +	if (err)
> +		goto err_switch_setup;
> +	i40e_dbg_pf_init(pf);
> +
> +	/* tell the firmware that we're starting */
> +	i40e_send_version(pf);
> +
> +	/* since everything's happy, start the service_task timer */
> +	mod_timer(&pf->service_timer,
> +		  round_jiffies(jiffies + pf->service_timer_period));
> +
> +	return 0;
> +
> +err_switch_setup:
> +	i40e_reset_interrupt_capability(pf);
> +	del_timer_sync(&pf->service_timer);
> +err_sw_init:
> +	i40e_shutdown_adminq(hw);
> +	iounmap(hw->hw_addr);
> +	kfree(pf);
> +	pci_disable_pcie_error_reporting(pf->pdev);
> +	pci_release_selected_regions(pf->pdev,
> +				     pci_select_bars(pf->pdev,
> +						     IORESOURCE_MEM));
> +	pci_disable_device(pf->pdev);
> +
> +	return err;
> +}
> +
> +/**
>    * i40e_probe - Device initialization routine
>    * @pdev: PCI device information struct
>    * @ent: entry in i40e_pci_tbl
> @@ -13708,6 +13861,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>   		dev_warn(&pdev->dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues with your hardware. If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
>   
>   	i40e_clear_pxe_mode(hw);
> +
> +	if (pf->hw.mac.type == I40E_MAC_X722)
> +		if (i40e_check_recovery_mode(pf))
> +			return i40e_init_recovery_mode(pf, hw);
> +
>   	err = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
>   	if (err)
>   		goto err_adminq_setup;
> @@ -14100,6 +14258,19 @@ static void i40e_remove(struct pci_dev *pdev)
>   	if (pf->service_task.func)
>   		cancel_work_sync(&pf->service_task);
>   
> +	if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
> +		struct i40e_vsi *vsi = pf->vsi[0];
> +
> +		/* We know that we have allocated only one vsi for this PF,
> +		 * * it was just for registering netdevice, so the interface

Funky comment "* *"

> +		 * could be visible in the 'ifconfig' output
> +		 */
> +		unregister_netdev(vsi->netdev);
> +		free_netdev(vsi->netdev);
> +
> +		goto unmap;
> +	}
> +
>   	/* Client close must be called explicitly here because the timer
>   	 * has been stopped.
>   	 */
> @@ -14149,6 +14320,7 @@ static void i40e_remove(struct pci_dev *pdev)
>   				 ret_code);
>   	}
>   
> +unmap:
>   	/* shutdown the adminq */
>   	i40e_shutdown_adminq(hw);
>   
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2018-08-03 16:45 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-02  0:40 [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 02/13] i40e: Add setting pf->lan_vsi in a recovery mode init path Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 03/13] i40e: Don't read MAC address in recovery mode Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 04/13] i40e: Display message when entering and leaving " Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 05/13] i40e: Enable interrupts in " Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 06/13] i40e: Limit initialization when going out of " Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 07/13] i40e: Check for recovery mode before doing PF reset Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 08/13] i40e: Reorder irq and adminq deinitialization in i40e_remove Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 09/13] i40e: Set netdev_registered when registering netdev in recovery mode Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 10/13] i40e: Reinitialize interrupt scheme when going out of " Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 11/13] i40e: Prevent kernel panic when rebooting server while NIC is in recovery Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 12/13] i40e: Lock the rtnl lock when restoring interrupt scheme for recovery mode Alice Michael
2018-08-02  0:40 ` [Intel-wired-lan] [next PATCH S94 13/13] i40e: set vsi->netdev to NULL after free_netdev() Alice Michael
2018-08-03 16:45 ` [Intel-wired-lan] [next PATCH S94 01/13] i40e: Introduce recovery mode support Shannon Nelson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.