get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1174139/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1174139,
    "url": "http://patchwork.ozlabs.org/api/patches/1174139/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191009140953.14087-3-anthony.l.nguyen@intel.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20191009140953.14087-3-anthony.l.nguyen@intel.com>",
    "list_archive_url": null,
    "date": "2019-10-09T14:09:41",
    "name": "[S31,03/15] ice: Add support for FW recovery mode detection",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "0ed1a3734cbfe6314808d4a296a2430fc08c9345",
    "submitter": {
        "id": 68875,
        "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api",
        "name": "Tony Nguyen",
        "email": "anthony.l.nguyen@intel.com"
    },
    "delegate": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/users/68/?format=api",
        "username": "jtkirshe",
        "first_name": "Jeff",
        "last_name": "Kirsher",
        "email": "jeffrey.t.kirsher@intel.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191009140953.14087-3-anthony.l.nguyen@intel.com/mbox/",
    "series": [
        {
            "id": 135203,
            "url": "http://patchwork.ozlabs.org/api/series/135203/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=135203",
            "date": "2019-10-09T14:09:45",
            "name": "[S31,01/15] ice: implement set_eeprom functionality",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/135203/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1174139/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1174139/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.137; helo=fraxinus.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com"
        ],
        "Received": [
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 46pTgW5VvLz9sCJ\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 10 Oct 2019 09:40:07 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 5066884553;\n\tWed,  9 Oct 2019 22:40:06 +0000 (UTC)",
            "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id jKFdKZmpGvHC; Wed,  9 Oct 2019 22:40:03 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 9B674869F6;\n\tWed,  9 Oct 2019 22:40:03 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id BC1B31BF3CC\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed,  9 Oct 2019 22:40:02 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id B34BD883B8\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed,  9 Oct 2019 22:40:02 +0000 (UTC)",
            "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id sqhjUMPpGXII for <intel-wired-lan@lists.osuosl.org>;\n\tWed,  9 Oct 2019 22:40:01 +0000 (UTC)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 1B87988305\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed,  9 Oct 2019 22:40:01 +0000 (UTC)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t09 Oct 2019 15:40:00 -0700",
            "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby orsmga003.jf.intel.com with ESMTP; 09 Oct 2019 15:40:00 -0700"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.67,277,1566889200\"; d=\"scan'208\";a=\"197052252\"",
        "From": "Tony Nguyen <anthony.l.nguyen@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Wed,  9 Oct 2019 07:09:41 -0700",
        "Message-Id": "<20191009140953.14087-3-anthony.l.nguyen@intel.com>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20191009140953.14087-1-anthony.l.nguyen@intel.com>",
        "References": "<20191009140953.14087-1-anthony.l.nguyen@intel.com>",
        "MIME-Version": "1.0",
        "Subject": "[Intel-wired-lan] [PATCH S31 03/15] ice: Add support for FW\n\trecovery mode detection",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>",
        "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>",
        "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"
    },
    "content": "From: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>\n\nThis patch adds support for firmware recovery mode detection.\n\nThe idea behind FW recovery mode is to recover from a bad FW state,\ndue to corruption or misconfiguration. The FW triggers recovery mode\nby setting the right bits in the GL_MNG_FWSM register and issuing\nan EMP reset.\n\nThe driver may or may not be loaded when recovery mode is triggered. So\non module load, the driver first checks if the FW is already in recovery\nmode. If so, it drops into recovery mode as well, where it creates and\nregisters a single netdev that only allows a very small set of repair/\ndiagnostic operations (like updating the FW, checking version, etc.)\nthrough ethtool.\n\nIf recovery mode is triggered when the driver is loaded/operational,\nthe first indication of this in the driver is via the EMP reset event.\nAs part of processing the reset event, the driver checks the GL_MNG_FWSM\nregister to determine if recovery mode was triggered. If so, traffic is\nstopped, peers are closed and the ethtool ops are updated to allow only\nrepair/diagnostic operations.\n\nSigned-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\n---\n drivers/net/ethernet/intel/ice/ice.h          |   3 +\n drivers/net/ethernet/intel/ice/ice_common.c   |  52 ++++-\n drivers/net/ethernet/intel/ice/ice_common.h   |   9 +\n drivers/net/ethernet/intel/ice/ice_ethtool.c  |  20 ++\n .../net/ethernet/intel/ice/ice_hw_autogen.h   |   1 +\n drivers/net/ethernet/intel/ice/ice_main.c     | 179 +++++++++++++++++-\n .../net/ethernet/intel/ice/ice_virtchnl_pf.c  |   6 +\n 7 files changed, 259 insertions(+), 11 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex f48c3ab28ded..54077dc5c028 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -191,6 +191,8 @@ enum ice_state {\n \t__ICE_EMPR_RECV,\t\t/* set by OICR handler */\n \t__ICE_SUSPENDED,\t\t/* set on module remove path */\n \t__ICE_RESET_FAILED,\t\t/* set by reset/rebuild */\n+\t__ICE_RECOVERY_MODE,\t\t/* set when recovery mode is detected */\n+\t__ICE_PREPPED_RECOVERY_MODE,\t/* set on recovery mode transition */\n \t/* When checking for the PF to be in a nominal operating state, the\n \t * bits that are grouped at the beginning of the list need to be\n \t * checked. Bits occurring before __ICE_STATE_NOMINAL_CHECK_BITS will\n@@ -497,6 +499,7 @@ static inline struct ice_vsi *ice_get_main_vsi(struct ice_pf *pf)\n int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);\n int ice_vsi_setup_rx_rings(struct ice_vsi *vsi);\n void ice_set_ethtool_ops(struct net_device *netdev);\n+void ice_set_ethtool_recovery_ops(struct net_device *netdev);\n void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);\n u16 ice_get_avail_txq_count(struct ice_pf *pf);\n u16 ice_get_avail_rxq_count(struct ice_pf *pf);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex eb99ca4099ca..494e51be2eac 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -751,6 +751,25 @@ ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,\n \t*ver_lo = (nvm->ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT;\n }\n \n+/**\n+ * ice_print_rollback_msg - print FW rollback message\n+ * @hw: pointer to the hardware structure\n+ */\n+void ice_print_rollback_msg(struct ice_hw *hw)\n+{\n+\tchar nvm_str[ICE_NVM_VER_LEN] = { 0 };\n+\tu8 oem_ver, oem_patch, ver_hi, ver_lo;\n+\tu16 oem_build;\n+\n+\tice_get_nvm_version(hw, &oem_ver, &oem_build, &oem_patch, &ver_hi,\n+\t\t\t    &ver_lo);\n+\tsnprintf(nvm_str, sizeof(nvm_str), \"%x.%02x 0x%x %d.%d.%d\", ver_hi,\n+\t\t ver_lo, hw->nvm.eetrack, oem_ver, oem_build, oem_patch);\n+\tdev_warn(ice_hw_to_dev(hw),\n+\t\t \"Firmware rollback mode detected. Current version is NVM: %s, FW: %d.%d. Device may exhibit limited functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware rollback mode\\n\",\n+\t\t nvm_str, hw->fw_maj_ver, hw->fw_min_ver);\n+}\n+\n /**\n  * ice_init_hw - main hardware initialization routine\n  * @hw: pointer to the hardware structure\n@@ -786,16 +805,19 @@ enum ice_status ice_init_hw(struct ice_hw *hw)\n \tif (status)\n \t\tice_debug(hw, ICE_DBG_INIT, \"Failed to enable FW logging.\\n\");\n \n-\tstatus = ice_clear_pf_cfg(hw);\n+\tstatus = ice_init_nvm(hw);\n \tif (status)\n \t\tgoto err_unroll_cqinit;\n \n-\tice_clear_pxe_mode(hw);\n+\tif (ice_get_fw_mode(hw) == ICE_FW_MODE_ROLLBACK)\n+\t\tice_print_rollback_msg(hw);\n \n-\tstatus = ice_init_nvm(hw);\n+\tstatus = ice_clear_pf_cfg(hw);\n \tif (status)\n \t\tgoto err_unroll_cqinit;\n \n+\tice_clear_pxe_mode(hw);\n+\n \tstatus = ice_get_caps(hw);\n \tif (status)\n \t\tgoto err_unroll_cqinit;\n@@ -3788,3 +3810,27 @@ ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,\n \t\tice_debug(hw, ICE_DBG_SCHED, \"query element failed\\n\");\n \treturn status;\n }\n+\n+/**\n+ * ice_get_fw_mode - returns FW mode\n+ * @hw: pointer to the HW struct\n+ */\n+enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)\n+{\n+#define ICE_FW_MODE_DBG_M BIT(0)\n+#define ICE_FW_MODE_REC_M BIT(1)\n+#define ICE_FW_MODE_ROLLBACK_M BIT(2)\n+\tu32 fw_mode;\n+\n+\t/* check the current FW mode */\n+\tfw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M;\n+\n+\tif (fw_mode & ICE_FW_MODE_DBG_M)\n+\t\treturn ICE_FW_MODE_DBG;\n+\telse if (fw_mode & ICE_FW_MODE_REC_M)\n+\t\treturn ICE_FW_MODE_REC;\n+\telse if (fw_mode & ICE_FW_MODE_ROLLBACK_M)\n+\t\treturn ICE_FW_MODE_ROLLBACK;\n+\telse\n+\t\treturn ICE_FW_MODE_NORMAL;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h\nindex c469d0db5ddc..e416721f5d9a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.h\n+++ b/drivers/net/ethernet/intel/ice/ice_common.h\n@@ -11,6 +11,13 @@\n #include \"ice_switch.h\"\n #include <linux/avf/virtchnl.h>\n \n+enum ice_fw_modes {\n+\tICE_FW_MODE_NORMAL,\n+\tICE_FW_MODE_DBG,\n+\tICE_FW_MODE_REC,\n+\tICE_FW_MODE_ROLLBACK\n+};\n+\n enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);\n \n void\n@@ -153,6 +160,8 @@ ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,\n void\n ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,\n \t\t    u8 *oem_patch, u8 *ver_hi, u8 *ver_lo);\n+enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw);\n+void ice_print_rollback_msg(struct ice_hw *hw);\n enum ice_status\n ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,\n \t\t     struct ice_aqc_get_elem *buf);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c\nindex 48d13e305d9e..67d884e27ea4 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c\n@@ -174,6 +174,10 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)\n \t\tsizeof(drvinfo->fw_version));\n \tstrlcpy(drvinfo->bus_info, pci_name(pf->pdev),\n \t\tsizeof(drvinfo->bus_info));\n+\n+\tif (test_bit(__ICE_RECOVERY_MODE, pf->state))\n+\t\treturn;\n+\n \tdrvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE;\n }\n \n@@ -3725,6 +3729,13 @@ static const struct ethtool_ops ice_ethtool_ops = {\n \t.get_module_eeprom\t= ice_get_module_eeprom,\n };\n \n+static const struct ethtool_ops ice_ethtool_recovery_ops = {\n+\t.get_drvinfo\t\t= ice_get_drvinfo,\n+\t.get_eeprom_len\t\t= ice_get_eeprom_len,\n+\t.get_eeprom\t\t= ice_get_eeprom,\n+\t.set_eeprom\t\t= ice_set_eeprom,\n+};\n+\n static const struct ethtool_ops ice_ethtool_safe_mode_ops = {\n \t.get_link_ksettings\t= ice_get_link_ksettings,\n \t.set_link_ksettings\t= ice_set_link_ksettings,\n@@ -3744,6 +3755,15 @@ static const struct ethtool_ops ice_ethtool_safe_mode_ops = {\n \t.nway_reset\t\t= ice_nway_reset,\n };\n \n+/**\n+ * ice_set_ethtool_recovery_ops - setup FW recovery ethtool ops\n+ * @netdev: network interface device structure\n+ */\n+void ice_set_ethtool_recovery_ops(struct net_device *netdev)\n+{\n+\tnetdev->ethtool_ops = &ice_ethtool_recovery_ops;\n+}\n+\n /**\n  * ice_set_ethtool_safe_mode_ops - setup safe mode ethtool ops\n  * @netdev: network interface device structure\ndiff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\nindex d541815230de..ffb008be3fa2 100644\n--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n@@ -270,6 +270,7 @@\n #define VP_MDET_TX_TDPU(_VF)\t\t\t(0x00040000 + ((_VF) * 4))\n #define VP_MDET_TX_TDPU_VALID_M\t\t\tBIT(0)\n #define GL_MNG_FWSM\t\t\t\t0x000B6134\n+#define GL_MNG_FWSM_FW_MODES_M\t\t\tICE_M(0x7, 0)\n #define GLNVM_FLA\t\t\t\t0x000B6108\n #define GLNVM_FLA_LOCKED_M\t\t\tBIT(6)\n #define GLNVM_GENS\t\t\t\t0x000B6100\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 88b5941ecf5c..3f8f0ad41258 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -41,6 +41,7 @@ MODULE_PARM_DESC(debug, \"netif level (0=none,...,16=all)\");\n #endif /* !CONFIG_DYNAMIC_DEBUG */\n \n static struct workqueue_struct *ice_wq;\n+static const struct net_device_ops ice_netdev_recovery_ops;\n static const struct net_device_ops ice_netdev_safe_mode_ops;\n static const struct net_device_ops ice_netdev_ops;\n \n@@ -517,6 +518,133 @@ ice_prepare_for_reset(struct ice_pf *pf)\n \tset_bit(__ICE_PREPARED_FOR_RESET, pf->state);\n }\n \n+/**\n+ * ice_print_recovery_msg - print recovery mode message\n+ * @dev: pointer to the device instance\n+ */\n+static void ice_print_recovery_msg(struct device *dev)\n+{\n+\tdev_err(dev,\n+\t\t\"Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode\\n\");\n+}\n+\n+/**\n+ * ice_prepare_for_recovery_mode - prepare the driver for FW recovery mode\n+ * @pf: pointer to the PF instance\n+ */\n+static void ice_prepare_for_recovery_mode(struct ice_pf *pf)\n+{\n+\tenum iidc_close_reason reason;\n+\tstruct ice_vsi *vsi;\n+\n+\tice_print_recovery_msg(&pf->pdev->dev);\n+\tset_bit(__ICE_RECOVERY_MODE, pf->state);\n+\n+\tvsi = ice_get_main_vsi(pf);\n+\tif (vsi && vsi->netdev) {\n+\t\tice_set_ethtool_recovery_ops(vsi->netdev);\n+\t\tnetif_carrier_off(vsi->netdev);\n+\t\tnetif_tx_stop_all_queues(vsi->netdev);\n+\t}\n+\n+\t/* close peer devices */\n+\treason = IIDC_REASON_RECOVERY_MODE;\n+\tice_for_each_peer(pf, &reason, ice_peer_close);\n+\n+\tif (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags))\n+\t\tif (!pci_vfs_assigned(pf->pdev))\n+\t\t\tpci_disable_sriov(pf->pdev);\n+\n+\tset_bit(__ICE_PREPPED_RECOVERY_MODE, pf->state);\n+}\n+\n+/**\n+ * ice_remove_recovery_mode - Unload helper when in FW recovery mode\n+ * @pf: pointer to the PF instance\n+ */\n+static void ice_remove_recovery_mode(struct ice_pf *pf)\n+{\n+\tstruct ice_vsi *vsi = ice_get_main_vsi(pf);\n+\n+\tif (vsi && vsi->netdev) {\n+\t\tunregister_netdev(vsi->netdev);\n+\t\tfree_netdev(vsi->netdev);\n+\t\tdevm_kfree(&pf->pdev->dev, vsi);\n+\t}\n+\n+\tice_reset(&pf->hw, ICE_RESET_PFR);\n+\tpci_disable_pcie_error_reporting(pf->pdev);\n+\tdevm_kfree(&pf->pdev->dev, pf->vsi);\n+\tdevm_kfree(&pf->pdev->dev, pf);\n+}\n+\n+/**\n+ * ice_probe_recovery_mode - Load helper when in FW recovery mode\n+ * @pf: pointer to the PF instance\n+ */\n+static int ice_probe_recovery_mode(struct ice_pf *pf)\n+{\n+\tstruct device *dev = &pf->pdev->dev;\n+\tstruct ice_netdev_priv *np;\n+\tstruct net_device *netdev;\n+\tstruct ice_vsi *vsi;\n+\tint err;\n+\n+\tice_print_recovery_msg(dev);\n+\tset_bit(__ICE_RECOVERY_MODE, pf->state);\n+\n+\t/* create one single VSI instance and netdev to allow for ethtool\n+\t * recovery ops. This VSI cannot be backed by a VSI in the HW as\n+\t * the FW is in recovery mode. Thus, no traffic is possible on this\n+\t * VSI/netdev\n+\t */\n+\tpf->vsi = devm_kcalloc(dev, 1, sizeof(*pf->vsi), GFP_KERNEL);\n+\tif (!pf->vsi)\n+\t\treturn -ENOMEM;\n+\n+\tvsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL);\n+\tif (!vsi) {\n+\t\terr = -ENOMEM;\n+\t\tgoto err_vsi;\n+\t}\n+\n+\tpf->vsi[0] = vsi;\n+\tvsi->back = pf;\n+\n+\t/* allocate an etherdev with 1 queue pair */\n+\tnetdev = alloc_etherdev(sizeof(*np));\n+\tif (!netdev) {\n+\t\terr = -ENOMEM;\n+\t\tgoto err_netdev;\n+\t}\n+\n+\tvsi->netdev = netdev;\n+\tnp = netdev_priv(netdev);\n+\tnp->vsi = vsi;\n+\tSET_NETDEV_DEV(netdev, dev);\n+\teth_hw_addr_random(netdev);\n+\n+\tnetdev->netdev_ops = &ice_netdev_recovery_ops;\n+\tice_set_ethtool_recovery_ops(netdev);\n+\n+\terr = register_netdev(netdev);\n+\tif (err)\n+\t\tgoto err_register;\n+\n+\tnetif_carrier_off(netdev);\n+\tnetif_tx_stop_all_queues(netdev);\n+\n+\treturn 0;\n+\n+err_register:\n+\tfree_netdev(netdev);\n+err_netdev:\n+\tdevm_kfree(dev, vsi);\n+err_vsi:\n+\tdevm_kfree(dev, pf->vsi);\n+\treturn err;\n+}\n+\n /**\n  * ice_do_reset - Initiate one of many types of resets\n  * @pf: board private structure\n@@ -595,21 +723,32 @@ static void ice_reset_subtask(struct ice_pf *pf)\n \t\t/* make sure we are ready to rebuild */\n \t\tif (ice_check_reset(&pf->hw)) {\n \t\t\tset_bit(__ICE_RESET_FAILED, pf->state);\n-\t\t} else {\n-\t\t\t/* done with reset. start rebuild */\n-\t\t\tpf->hw.reset_ongoing = false;\n-\t\t\tice_rebuild(pf, reset_type);\n-\t\t\t/* clear bit to resume normal operations, but\n-\t\t\t * ICE_NEEDS_RESTART bit is set in case rebuild failed\n-\t\t\t */\n \t\t\tclear_bit(__ICE_RESET_OICR_RECV, pf->state);\n \t\t\tclear_bit(__ICE_PREPARED_FOR_RESET, pf->state);\n \t\t\tclear_bit(__ICE_PFR_REQ, pf->state);\n \t\t\tclear_bit(__ICE_CORER_REQ, pf->state);\n \t\t\tclear_bit(__ICE_GLOBR_REQ, pf->state);\n-\t\t\tice_reset_all_vfs(pf, true);\n+\t\t\tif (ice_get_fw_mode(&pf->hw) == ICE_FW_MODE_REC)\n+\t\t\t\tice_prepare_for_recovery_mode(pf);\n+\t\t\treturn;\n \t\t}\n \n+\t\t/* came out of reset. check if an NVM rollback happened */\n+\t\tif (ice_get_fw_mode(&pf->hw) == ICE_FW_MODE_ROLLBACK)\n+\t\t\tice_print_rollback_msg(&pf->hw);\n+\n+\t\t/* done with reset. start rebuild */\n+\t\tpf->hw.reset_ongoing = false;\n+\t\tice_rebuild(pf, reset_type);\n+\t\t/* clear bit to resume normal operations, but\n+\t\t * ICE_NEEDS_RESTART bit is set in case rebuild failed\n+\t\t */\n+\t\tclear_bit(__ICE_RESET_OICR_RECV, pf->state);\n+\t\tclear_bit(__ICE_PREPARED_FOR_RESET, pf->state);\n+\t\tclear_bit(__ICE_PFR_REQ, pf->state);\n+\t\tclear_bit(__ICE_CORER_REQ, pf->state);\n+\t\tclear_bit(__ICE_GLOBR_REQ, pf->state);\n+\t\tice_reset_all_vfs(pf, true);\n \t\treturn;\n \t}\n \n@@ -1161,6 +1300,7 @@ static void ice_service_task_schedule(struct ice_pf *pf)\n {\n \tif (!test_bit(__ICE_SERVICE_DIS, pf->state) &&\n \t    !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) &&\n+\t    !test_bit(__ICE_RECOVERY_MODE, pf->state) &&\n \t    !test_bit(__ICE_NEEDS_RESTART, pf->state))\n \t\tqueue_work(ice_wq, &pf->serv_task);\n }\n@@ -3222,6 +3362,15 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)\n \t\thw->debug_mask = debug;\n #endif\n \n+\t/* check if device FW is in recovery mode */\n+\tif (ice_get_fw_mode(hw) == ICE_FW_MODE_REC) {\n+\t\terr = ice_probe_recovery_mode(pf);\n+\t\tif (err)\n+\t\t\tgoto err_rec_mode;\n+\n+\t\treturn 0;\n+\t}\n+\n \terr = ice_init_hw(hw);\n \tif (err) {\n \t\tdev_err(dev, \"ice_init_hw failed: %d\\n\", err);\n@@ -3394,6 +3543,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)\n \tice_deinit_pf(pf);\n \tice_deinit_hw(hw);\n err_exit_unroll:\n+err_rec_mode:\n \tpci_disable_pcie_error_reporting(pdev);\n \treturn err;\n }\n@@ -3411,6 +3561,19 @@ static void ice_remove(struct pci_dev *pdev)\n \tif (!pf)\n \t\treturn;\n \n+\t/* __ICE_PREPPED_RECOVERY_MODE is set when the up and running\n+\t * driver transitions to recovery mode. If this is not set\n+\t * it means that the driver went into recovery mode on load.\n+\t * For the former case, go through the usual flow for module\n+\t * unload. For the latter, call ice_remove_recovery_mode\n+\t * and return.\n+\t */\n+\tif (!test_bit(__ICE_PREPPED_RECOVERY_MODE, pf->state) &&\n+\t    test_bit(__ICE_RECOVERY_MODE, pf->state)) {\n+\t\tice_remove_recovery_mode(pf);\n+\t\treturn;\n+\t}\n+\n \tfor (i = 0; i < ICE_MAX_RESET_WAIT; i++) {\n \t\tif (!ice_is_reset_in_progress(pf->state))\n \t\t\tbreak;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\nindex 5cb809c58609..6fa929eae789 100644\n--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n@@ -1419,6 +1419,12 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)\n {\n \tstruct ice_pf *pf = pci_get_drvdata(pdev);\n \n+\tif (test_bit(__ICE_RECOVERY_MODE, pf->state)) {\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"SR-IOV cannot be configured - Device is in Recovery Mode\\n\");\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n \tif (ice_is_safe_mode(pf)) {\n \t\tdev_err(&pf->pdev->dev,\n \t\t\t\"SR-IOV cannot be configured - Device is in Safe Mode\\n\");\n",
    "prefixes": [
        "S31",
        "03/15"
    ]
}