get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 704207,
    "url": "http://patchwork.ozlabs.org/api/patches/704207/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/148122413035.21095.11451446349343203950.stgit@mdrustad-wks.jf.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": "<148122413035.21095.11451446349343203950.stgit@mdrustad-wks.jf.intel.com>",
    "list_archive_url": null,
    "date": "2016-12-08T19:08:50",
    "name": "[V4,4/4] ixgbe: Implement support for firmware-controlled PHYs",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "23d501ef05b362f0136102ef91a29610facdb8ae",
    "submitter": {
        "id": 13252,
        "url": "http://patchwork.ozlabs.org/api/people/13252/?format=api",
        "name": "Rustad, Mark D",
        "email": "mark.d.rustad@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/148122413035.21095.11451446349343203950.stgit@mdrustad-wks.jf.intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/704207/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/704207/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@lists.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"
        ],
        "Received": [
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3tZPzb4K3gz9t2G\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  9 Dec 2016 06:08:59 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 314E489CAC;\n\tThu,  8 Dec 2016 19:08:58 +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 Y7Qc5bMCFr+d; Thu,  8 Dec 2016 19:08:54 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id A0F0189C3A;\n\tThu,  8 Dec 2016 19:08:54 +0000 (UTC)",
            "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 09C7D1BFF09\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu,  8 Dec 2016 19:08:53 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 040D12D935\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu,  8 Dec 2016 19:08:53 +0000 (UTC)",
            "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 29UkfgnqMUol for <intel-wired-lan@lists.osuosl.org>;\n\tThu,  8 Dec 2016 19:08:50 +0000 (UTC)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby silver.osuosl.org (Postfix) with ESMTPS id CDEB62CE77\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu,  8 Dec 2016 19:08:50 +0000 (UTC)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP; 08 Dec 2016 11:08:50 -0800",
            "from mdrustad-wks.jf.intel.com ([134.134.3.111])\n\tby orsmga002.jf.intel.com with ESMTP; 08 Dec 2016 11:08:50 -0800"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.33,320,1477983600\"; d=\"scan'208\";a=\"15561010\"",
        "From": "Mark D Rustad <mark.d.rustad@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Thu, 08 Dec 2016 11:08:50 -0800",
        "Message-ID": "<148122413035.21095.11451446349343203950.stgit@mdrustad-wks.jf.intel.com>",
        "In-Reply-To": "<148122398559.21095.12042361999753164317.stgit@mdrustad-wks.jf.intel.com>",
        "References": "<148122398559.21095.12042361999753164317.stgit@mdrustad-wks.jf.intel.com>",
        "User-Agent": "StGit/unknown-version",
        "MIME-Version": "1.0",
        "Subject": "[Intel-wired-lan] [PATCH V4 4/4] ixgbe: Implement support for\n\tfirmware-controlled PHYs",
        "X-BeenThere": "intel-wired-lan@lists.osuosl.org",
        "X-Mailman-Version": "2.1.18-1",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>",
        "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>",
        "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>"
    },
    "content": "Implement support for devices that have firmware-controlled PHYs.\n\nSigned-off-by: Mark Rustad <mark.d.rustad@intel.com>\n---\nChanges in V2:\n- Fixed some oversights primarily related to 10M support\nChanges in V3:\n- Use the correct ops to blink the LED\nChanges in V4:\n- Actually get the right content into the patch\n---\n drivers/net/ethernet/intel/ixgbe/ixgbe.h         |    4 \n drivers/net/ethernet/intel/ixgbe/ixgbe_common.c  |    7 \n drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |  156 ++++++++\n drivers/net/ethernet/intel/ixgbe/ixgbe_main.c    |   45 ++\n drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c     |    3 \n drivers/net/ethernet/intel/ixgbe/ixgbe_type.h    |    7 \n drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c    |  408 ++++++++++++++++++++++\n 7 files changed, 624 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h\nindex ef81c3d8c295..53fb427b1c29 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h\n@@ -661,6 +661,8 @@ struct ixgbe_adapter {\n #define IXGBE_FLAG2_PHY_INTERRUPT\t\tBIT(11)\n #define IXGBE_FLAG2_UDP_TUN_REREG_NEEDED\tBIT(12)\n #define IXGBE_FLAG2_VLAN_PROMISC\t\tBIT(13)\n+#define IXGBE_FLAG2_EEE_CAPABLE\t\t\tBIT(14)\n+#define IXGBE_FLAG2_EEE_ENABLED\t\t\tBIT(15)\n \n \t/* Tx fast path data */\n \tint num_tx_queues;\n@@ -862,6 +864,7 @@ enum ixgbe_boards {\n \tboard_X550,\n \tboard_X550EM_x,\n \tboard_x550em_a,\n+\tboard_x550em_a_fw,\n };\n \n extern const struct ixgbe_info ixgbe_82598_info;\n@@ -870,6 +873,7 @@ extern const struct ixgbe_info ixgbe_X540_info;\n extern const struct ixgbe_info ixgbe_X550_info;\n extern const struct ixgbe_info ixgbe_X550EM_x_info;\n extern const struct ixgbe_info ixgbe_x550em_a_info;\n+extern const struct ixgbe_info ixgbe_x550em_a_fw_info;\n #ifdef CONFIG_IXGBE_DCB\n extern const struct dcbnl_rtnl_ops dcbnl_ops;\n #endif\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c\nindex 851f48555506..08eb4fddb8fd 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c\n@@ -3382,6 +3382,13 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,\n \t\telse\n \t\t\t*speed = IXGBE_LINK_SPEED_100_FULL;\n \t\tbreak;\n+\tcase IXGBE_LINKS_SPEED_10_X550EM_A:\n+\t\t*speed = IXGBE_LINK_SPEED_UNKNOWN;\n+\t\tif (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||\n+\t\t    hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {\n+\t\t\t*speed = IXGBE_LINK_SPEED_10_FULL;\n+\t\t}\n+\t\tbreak;\n \tdefault:\n \t\t*speed = IXGBE_LINK_SPEED_UNKNOWN;\n \t}\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\nindex fd192bf29b26..f19cbc761748 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\n@@ -197,15 +197,17 @@ static int ixgbe_get_settings(struct net_device *netdev,\n \t\t\t\t   SUPPORTED_1000baseKX_Full :\n \t\t\t\t   SUPPORTED_1000baseT_Full;\n \tif (supported_link & IXGBE_LINK_SPEED_100_FULL)\n-\t\tecmd->supported |= ixgbe_isbackplane(hw->phy.media_type) ?\n-\t\t\t\t   SUPPORTED_1000baseKX_Full :\n-\t\t\t\t   SUPPORTED_1000baseT_Full;\n+\t\tecmd->supported |= SUPPORTED_100baseT_Full;\n+\tif (supported_link & IXGBE_LINK_SPEED_10_FULL)\n+\t\tecmd->supported |= SUPPORTED_10baseT_Full;\n \n \t/* default advertised speed if phy.autoneg_advertised isn't set */\n \tecmd->advertising = ecmd->supported;\n \t/* set the advertised speeds */\n \tif (hw->phy.autoneg_advertised) {\n \t\tecmd->advertising = 0;\n+\t\tif (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL)\n+\t\t\tecmd->advertising |= ADVERTISED_10baseT_Full;\n \t\tif (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)\n \t\t\tecmd->advertising |= ADVERTISED_100baseT_Full;\n \t\tif (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)\n@@ -237,6 +239,7 @@ static int ixgbe_get_settings(struct net_device *netdev,\n \tcase ixgbe_phy_tn:\n \tcase ixgbe_phy_aq:\n \tcase ixgbe_phy_x550em_ext_t:\n+\tcase ixgbe_phy_fw:\n \tcase ixgbe_phy_cu_unknown:\n \t\tecmd->supported |= SUPPORTED_TP;\n \t\tecmd->advertising |= ADVERTISED_TP;\n@@ -337,6 +340,9 @@ static int ixgbe_get_settings(struct net_device *netdev,\n \t\tcase IXGBE_LINK_SPEED_10GB_FULL:\n \t\t\tethtool_cmd_speed_set(ecmd, SPEED_10000);\n \t\t\tbreak;\n+\t\tcase IXGBE_LINK_SPEED_5GB_FULL:\n+\t\t\tethtool_cmd_speed_set(ecmd, SPEED_5000);\n+\t\t\tbreak;\n \t\tcase IXGBE_LINK_SPEED_2_5GB_FULL:\n \t\t\tethtool_cmd_speed_set(ecmd, SPEED_2500);\n \t\t\tbreak;\n@@ -346,6 +352,9 @@ static int ixgbe_get_settings(struct net_device *netdev,\n \t\tcase IXGBE_LINK_SPEED_100_FULL:\n \t\t\tethtool_cmd_speed_set(ecmd, SPEED_100);\n \t\t\tbreak;\n+\t\tcase IXGBE_LINK_SPEED_10_FULL:\n+\t\t\tethtool_cmd_speed_set(ecmd, SPEED_10);\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n \t\t}\n@@ -394,6 +403,9 @@ static int ixgbe_set_settings(struct net_device *netdev,\n \t\tif (ecmd->advertising & ADVERTISED_100baseT_Full)\n \t\t\tadvertised |= IXGBE_LINK_SPEED_100_FULL;\n \n+\t\tif (ecmd->advertising & ADVERTISED_10baseT_Full)\n+\t\t\tadvertised |= IXGBE_LINK_SPEED_10_FULL;\n+\n \t\tif (old == advertised)\n \t\t\treturn err;\n \t\t/* this sets the link speed and restarts auto-neg */\n@@ -3173,6 +3185,9 @@ static int ixgbe_get_module_info(struct net_device *dev,\n \tu8 sff8472_rev, addr_mode;\n \tbool page_swap = false;\n \n+\tif (hw->phy.type == ixgbe_phy_fw)\n+\t\treturn -ENXIO;\n+\n \t/* Check whether we support SFF-8472 or not */\n \tstatus = hw->phy.ops.read_i2c_eeprom(hw,\n \t\t\t\t\t     IXGBE_SFF_SFF_8472_COMP,\n@@ -3218,6 +3233,9 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,\n \tif (ee->len == 0)\n \t\treturn -EINVAL;\n \n+\tif (hw->phy.type == ixgbe_phy_fw)\n+\t\treturn -ENXIO;\n+\n \tfor (i = ee->offset; i < ee->offset + ee->len; i++) {\n \t\t/* I2C reads can take long time */\n \t\tif (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))\n@@ -3237,6 +3255,136 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,\n \treturn 0;\n }\n \n+static const struct {\n+\tixgbe_link_speed mac_speed;\n+\tu32 supported;\n+} ixgbe_ls_map[] = {\n+\t{ IXGBE_LINK_SPEED_10_FULL, SUPPORTED_10baseT_Full },\n+\t{ IXGBE_LINK_SPEED_100_FULL, SUPPORTED_100baseT_Full },\n+\t{ IXGBE_LINK_SPEED_1GB_FULL, SUPPORTED_1000baseT_Full },\n+\t{ IXGBE_LINK_SPEED_2_5GB_FULL, SUPPORTED_2500baseX_Full },\n+\t{ IXGBE_LINK_SPEED_10GB_FULL, SUPPORTED_10000baseT_Full },\n+};\n+\n+static const struct {\n+\tu32 lp_advertised;\n+\tu32 mac_speed;\n+} ixgbe_lp_map[] = {\n+\t{ FW_PHY_ACT_UD_2_100M_TX_EEE, SUPPORTED_100baseT_Full },\n+\t{ FW_PHY_ACT_UD_2_1G_T_EEE, SUPPORTED_1000baseT_Full },\n+\t{ FW_PHY_ACT_UD_2_10G_T_EEE, SUPPORTED_10000baseT_Full },\n+\t{ FW_PHY_ACT_UD_2_1G_KX_EEE, SUPPORTED_1000baseKX_Full },\n+\t{ FW_PHY_ACT_UD_2_10G_KX4_EEE, SUPPORTED_10000baseKX4_Full },\n+\t{ FW_PHY_ACT_UD_2_10G_KR_EEE, SUPPORTED_10000baseKR_Full},\n+};\n+\n+static int\n+ixgbe_get_eee_fw(struct ixgbe_adapter *adapter, struct ethtool_eee *edata)\n+{\n+\tu32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\tstruct ixgbe_hw *hw = &adapter->hw;\n+\ts32 rc;\n+\tu16 i;\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_UD_2, &info);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tedata->lp_advertised = 0;\n+\tfor (i = 0; i < ARRAY_SIZE(ixgbe_lp_map); ++i) {\n+\t\tif (info[0] & ixgbe_lp_map[i].lp_advertised)\n+\t\t\tedata->lp_advertised |= ixgbe_lp_map[i].mac_speed;\n+\t}\n+\n+\tedata->supported = 0;\n+\tfor (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) {\n+\t\tif (hw->phy.eee_speeds_supported & ixgbe_ls_map[i].mac_speed)\n+\t\t\tedata->supported |= ixgbe_ls_map[i].supported;\n+\t}\n+\n+\tedata->advertised = 0;\n+\tfor (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) {\n+\t\tif (hw->phy.eee_speeds_advertised & ixgbe_ls_map[i].mac_speed)\n+\t\t\tedata->advertised |= ixgbe_ls_map[i].supported;\n+\t}\n+\n+\tedata->eee_enabled = !!edata->advertised;\n+\tedata->tx_lpi_enabled = edata->eee_enabled;\n+\tif (edata->advertised & edata->lp_advertised)\n+\t\tedata->eee_active = true;\n+\n+\treturn 0;\n+}\n+\n+static int ixgbe_get_eee(struct net_device *netdev, struct ethtool_eee *edata)\n+{\n+\tstruct ixgbe_adapter *adapter = netdev_priv(netdev);\n+\tstruct ixgbe_hw *hw = &adapter->hw;\n+\n+\tif (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (hw->phy.eee_speeds_supported && hw->phy.type == ixgbe_phy_fw)\n+\t\treturn ixgbe_get_eee_fw(adapter, edata);\n+\n+\treturn -EOPNOTSUPP;\n+}\n+\n+static int ixgbe_set_eee(struct net_device *netdev, struct ethtool_eee *edata)\n+{\n+\tstruct ixgbe_adapter *adapter = netdev_priv(netdev);\n+\tstruct ixgbe_hw *hw = &adapter->hw;\n+\tstruct ethtool_eee eee_data;\n+\ts32 ret_val;\n+\n+\tif (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tmemset(&eee_data, 0, sizeof(struct ethtool_eee));\n+\n+\tret_val = ixgbe_get_eee(netdev, &eee_data);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\tif (eee_data.eee_enabled && !edata->eee_enabled) {\n+\t\tif (eee_data.tx_lpi_enabled != edata->tx_lpi_enabled) {\n+\t\t\te_err(drv, \"Setting EEE tx-lpi is not supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (eee_data.tx_lpi_timer != edata->tx_lpi_timer) {\n+\t\t\te_err(drv,\n+\t\t\t      \"Setting EEE Tx LPI timer is not supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (eee_data.advertised != edata->advertised) {\n+\t\t\te_err(drv,\n+\t\t\t      \"Setting EEE advertised speeds is not supported\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tif (eee_data.eee_enabled != edata->eee_enabled) {\n+\t\tif (edata->eee_enabled) {\n+\t\t\tadapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED;\n+\t\t\thw->phy.eee_speeds_advertised =\n+\t\t\t\t\t\t   hw->phy.eee_speeds_supported;\n+\t\t} else {\n+\t\t\tadapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED;\n+\t\t\thw->phy.eee_speeds_advertised = 0;\n+\t\t}\n+\n+\t\t/* reset link */\n+\t\tif (netif_running(netdev))\n+\t\t\tixgbe_reinit_locked(adapter);\n+\t\telse\n+\t\t\tixgbe_reset(adapter);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static const struct ethtool_ops ixgbe_ethtool_ops = {\n \t.get_settings           = ixgbe_get_settings,\n \t.set_settings           = ixgbe_set_settings,\n@@ -3269,6 +3417,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {\n \t.get_rxfh_key_size\t= ixgbe_get_rxfh_key_size,\n \t.get_rxfh\t\t= ixgbe_get_rxfh,\n \t.set_rxfh\t\t= ixgbe_set_rxfh,\n+\t.get_eee\t\t= ixgbe_get_eee,\n+\t.set_eee\t\t= ixgbe_set_eee,\n \t.get_channels\t\t= ixgbe_get_channels,\n \t.set_channels\t\t= ixgbe_set_channels,\n \t.get_ts_info\t\t= ixgbe_get_ts_info,\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\nindex 0b1fa5d557ba..0da6381ca800 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n@@ -86,6 +86,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {\n \t[board_X550]\t\t= &ixgbe_X550_info,\n \t[board_X550EM_x]\t= &ixgbe_X550EM_x_info,\n \t[board_x550em_a]\t= &ixgbe_x550em_a_info,\n+\t[board_x550em_a_fw]\t= &ixgbe_x550em_a_fw_info,\n };\n \n /* ixgbe_pci_tbl - PCI Device ID Table\n@@ -140,6 +141,8 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {\n \t{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SGMII_L), board_x550em_a },\n \t{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_10G_T), board_x550em_a},\n \t{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP), board_x550em_a },\n+\t{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T), board_x550em_a_fw },\n+\t{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T_L), board_x550em_a_fw },\n \t/* required last entry */\n \t{0, }\n };\n@@ -180,6 +183,7 @@ MODULE_VERSION(DRV_VERSION);\n static struct workqueue_struct *ixgbe_wq;\n \n static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);\n+static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *);\n \n static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,\n \t\t\t\t\t  u32 reg, u16 *value)\n@@ -5294,6 +5298,8 @@ void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)\n \n \twhile (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))\n \t\tusleep_range(1000, 2000);\n+\tif (adapter->hw.phy.type == ixgbe_phy_fw)\n+\t\tixgbe_watchdog_link_is_down(adapter);\n \tixgbe_down(adapter);\n \t/*\n \t * If SR-IOV enabled then wait a bit before bringing the adapter\n@@ -5554,6 +5560,31 @@ void ixgbe_down(struct ixgbe_adapter *adapter)\n }\n \n /**\n+ * ixgbe_eee_capable - helper function to determine EEE support on X550\n+ * @adapter: board private structure\n+ */\n+static void ixgbe_set_eee_capable(struct ixgbe_adapter *adapter)\n+{\n+\tstruct ixgbe_hw *hw = &adapter->hw;\n+\n+\tswitch (hw->device_id) {\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T:\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T_L:\n+\t\tif (!hw->phy.eee_speeds_supported)\n+\t\t\tbreak;\n+\t\tadapter->flags2 |= IXGBE_FLAG2_EEE_CAPABLE;\n+\t\tif (!hw->phy.eee_speeds_advertised)\n+\t\t\tbreak;\n+\t\tadapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED;\n+\t\tbreak;\n+\tdefault:\n+\t\tadapter->flags2 &= ~IXGBE_FLAG2_EEE_CAPABLE;\n+\t\tadapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED;\n+\t\tbreak;\n+\t}\n+}\n+\n+/**\n  * ixgbe_tx_timeout - Respond to a Tx Hang\n  * @netdev: network interface device structure\n  **/\n@@ -5717,6 +5748,14 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,\n \t\tbreak;\n \tcase ixgbe_mac_x550em_a:\n \t\tadapter->flags |= IXGBE_FLAG_GENEVE_OFFLOAD_CAPABLE;\n+\t\tswitch (hw->device_id) {\n+\t\tcase IXGBE_DEV_ID_X550EM_A_1G_T:\n+\t\tcase IXGBE_DEV_ID_X550EM_A_1G_T_L:\n+\t\t\tadapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n \t/* fall through */\n \tcase ixgbe_mac_X550EM_x:\n #ifdef CONFIG_IXGBE_DCB\n@@ -5730,6 +5769,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,\n #endif /* IXGBE_FCOE */\n \t/* Fall Through */\n \tcase ixgbe_mac_X550:\n+\t\tif (hw->mac.type == ixgbe_mac_X550)\n+\t\t\tadapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;\n #ifdef CONFIG_IXGBE_DCA\n \t\tadapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;\n #endif\n@@ -6807,6 +6848,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)\n \tcase IXGBE_LINK_SPEED_100_FULL:\n \t\tspeed_str = \"100 Mbps\";\n \t\tbreak;\n+\tcase IXGBE_LINK_SPEED_10_FULL:\n+\t\tspeed_str = \"10 Mbps\";\n+\t\tbreak;\n \tdefault:\n \t\tspeed_str = \"unknown speed\";\n \t\tbreak;\n@@ -9591,6 +9635,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \thw->phy.reset_if_overtemp = true;\n \terr = hw->mac.ops.reset_hw(hw);\n \thw->phy.reset_if_overtemp = false;\n+\tixgbe_set_eee_capable(adapter);\n \tif (err == IXGBE_ERR_SFP_NOT_PRESENT) {\n \t\terr = 0;\n \t} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c\nindex 989a3b19d209..92dc4699b8c7 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c\n@@ -784,6 +784,9 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,\n \tif (speed & IXGBE_LINK_SPEED_100_FULL)\n \t\thw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;\n \n+\tif (speed & IXGBE_LINK_SPEED_10_FULL)\n+\t\thw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10_FULL;\n+\n \t/* Setup link based on the new speed settings */\n \tif (hw->phy.ops.setup_link)\n \t\thw->phy.ops.setup_link(hw);\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h\nindex acdbd81df3a4..4200f7450bcd 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h\n@@ -92,6 +92,8 @@\n #define IXGBE_DEV_ID_X550EM_A_SGMII_L\t0x15C7\n #define IXGBE_DEV_ID_X550EM_A_10G_T\t0x15C8\n #define IXGBE_DEV_ID_X550EM_A_SFP\t0x15CE\n+#define IXGBE_DEV_ID_X550EM_A_1G_T\t0x15E4\n+#define IXGBE_DEV_ID_X550EM_A_1G_T_L\t0x15E5\n \n /* VF Device IDs */\n #define IXGBE_DEV_ID_82599_VF\t\t0x10ED\n@@ -1914,6 +1916,7 @@ enum {\n #define IXGBE_LINKS_SPEED_10G_82599 0x30000000\n #define IXGBE_LINKS_SPEED_1G_82599  0x20000000\n #define IXGBE_LINKS_SPEED_100_82599 0x10000000\n+#define IXGBE_LINKS_SPEED_10_X550EM_A 0\n #define IXGBE_LINK_UP_TIME      90 /* 9.0 Seconds */\n #define IXGBE_AUTO_NEG_TIME     45 /* 4.5 Seconds */\n \n@@ -2926,6 +2929,7 @@ typedef u32 ixgbe_autoneg_advertised;\n /* Link speed */\n typedef u32 ixgbe_link_speed;\n #define IXGBE_LINK_SPEED_UNKNOWN\t0\n+#define IXGBE_LINK_SPEED_10_FULL\t0x0002\n #define IXGBE_LINK_SPEED_100_FULL\t0x0008\n #define IXGBE_LINK_SPEED_1GB_FULL\t0x0020\n #define IXGBE_LINK_SPEED_2_5GB_FULL\t0x0400\n@@ -3141,6 +3145,7 @@ enum ixgbe_phy_type {\n \tixgbe_phy_qsfp_unknown,\n \tixgbe_phy_sfp_unsupported,\n \tixgbe_phy_sgmii,\n+\tixgbe_phy_fw,\n \tixgbe_phy_generic\n };\n \n@@ -3555,6 +3560,8 @@ struct ixgbe_phy_info {\n \tbool                            reset_disable;\n \tixgbe_autoneg_advertised        autoneg_advertised;\n \tixgbe_link_speed\t\tspeeds_supported;\n+\tixgbe_link_speed\t\teee_speeds_supported;\n+\tixgbe_link_speed\t\teee_speeds_advertised;\n \tenum ixgbe_smart_speed          smart_speed;\n \tbool                            smart_speed_active;\n \tbool                            multispeed_fiber;\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c\nindex 9284b8f0178d..afccc9f5f9c1 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c\n@@ -63,6 +63,18 @@ static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)\n \treturn 0;\n }\n \n+static s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw)\n+{\n+\tstruct ixgbe_phy_info *phy = &hw->phy;\n+\n+\t/* Start with X540 invariants, since so similar */\n+\tixgbe_get_invariants_X540(hw);\n+\n+\tphy->ops.set_phy_power = NULL;\n+\n+\treturn 0;\n+}\n+\n /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control\n  *  @hw: pointer to hardware structure\n  **/\n@@ -447,6 +459,159 @@ s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity,\n \treturn IXGBE_ERR_HOST_INTERFACE_COMMAND;\n }\n \n+static const struct {\n+\tu16 fw_speed;\n+\tixgbe_link_speed phy_speed;\n+} ixgbe_fw_map[] = {\n+\t{ FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL },\n+\t{ FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL },\n+\t{ FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL },\n+\t{ FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL },\n+\t{ FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL },\n+\t{ FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL },\n+};\n+\n+/**\n+ * ixgbe_get_phy_id_fw - Get the phy ID via firmware command\n+ * @hw: pointer to hardware structure\n+ *\n+ * Returns error code\n+ */\n+static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw)\n+{\n+\tu32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\tu16 phy_speeds;\n+\tu16 phy_id_lo;\n+\ts32 rc;\n+\tu16 i;\n+\n+\tif (hw->phy.id)\n+\t\treturn 0;\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, &info);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\thw->phy.speeds_supported = 0;\n+\tphy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK;\n+\tfor (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {\n+\t\tif (phy_speeds & ixgbe_fw_map[i].fw_speed)\n+\t\t\thw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;\n+\t}\n+\n+\thw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;\n+\tphy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;\n+\thw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;\n+\thw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;\n+\tif (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)\n+\t\treturn IXGBE_ERR_PHY_ADDR_INVALID;\n+\n+\thw->phy.autoneg_advertised = hw->phy.speeds_supported;\n+\thw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |\n+\t\t\t\t       IXGBE_LINK_SPEED_1GB_FULL;\n+\thw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;\n+\treturn 0;\n+}\n+\n+/**\n+ * ixgbe_identify_phy_fw - Get PHY type based on firmware command\n+ * @hw: pointer to hardware structure\n+ *\n+ * Returns error code\n+ */\n+static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw)\n+{\n+\tif (hw->bus.lan_id)\n+\t\thw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;\n+\telse\n+\t\thw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;\n+\n+\thw->phy.type = ixgbe_phy_fw;\n+\thw->phy.ops.read_reg = NULL;\n+\thw->phy.ops.write_reg = NULL;\n+\treturn ixgbe_get_phy_id_fw(hw);\n+}\n+\n+/**\n+ * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY\n+ * @hw: pointer to hardware structure\n+ *\n+ * Returns error code\n+ */\n+static s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw)\n+{\n+\tu32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\n+\tsetup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF;\n+\treturn ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup);\n+}\n+\n+/**\n+ * ixgbe_setup_fw_link - Setup firmware-controlled PHYs\n+ * @hw: pointer to hardware structure\n+ */\n+static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw)\n+{\n+\tu32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\ts32 rc;\n+\tu16 i;\n+\n+\tif (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))\n+\t\treturn 0;\n+\n+\tif (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {\n+\t\thw_err(hw, \"rx_pause not valid in strict IEEE mode\\n\");\n+\t\treturn IXGBE_ERR_INVALID_LINK_SETTINGS;\n+\t}\n+\n+\tswitch (hw->fc.requested_mode) {\n+\tcase ixgbe_fc_full:\n+\t\tsetup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX <<\n+\t\t\t    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;\n+\t\tbreak;\n+\tcase ixgbe_fc_rx_pause:\n+\t\tsetup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX <<\n+\t\t\t    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;\n+\t\tbreak;\n+\tcase ixgbe_fc_tx_pause:\n+\t\tsetup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX <<\n+\t\t\t    FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tfor (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) {\n+\t\tif (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed)\n+\t\t\tsetup[0] |= ixgbe_fw_map[i].fw_speed;\n+\t}\n+\tsetup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN;\n+\n+\tif (hw->phy.eee_speeds_advertised)\n+\t\tsetup[0] |= FW_PHY_ACT_SETUP_LINK_EEE;\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);\n+\tif (rc)\n+\t\treturn rc;\n+\tif (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)\n+\t\treturn IXGBE_ERR_OVERTEMP;\n+\treturn 0;\n+}\n+\n+/**\n+ * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs\n+ * @hw: pointer to hardware structure\n+ *\n+ * Called at init time to set up flow control.\n+ */\n+static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)\n+{\n+\tif (hw->fc.requested_mode == ixgbe_fc_default)\n+\t\thw->fc.requested_mode = ixgbe_fc_full;\n+\n+\treturn ixgbe_setup_fw_link(hw);\n+}\n+\n /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params\n  *  @hw: pointer to hardware structure\n  *\n@@ -1794,6 +1959,125 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed,\n \treturn rc;\n }\n \n+/**\n+ * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs\n+ * @hw: pointer to hardware structure\n+ */\n+static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,\n+\t\t\t\tbool autoneg_wait)\n+{\n+\tstruct ixgbe_mac_info *mac = &hw->mac;\n+\tu32 lval, sval, flx_val;\n+\ts32 rc;\n+\n+\trc = mac->ops.read_iosf_sb_reg(hw,\n+\t\t\t\t       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),\n+\t\t\t\t       IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tlval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;\n+\tlval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;\n+\tlval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;\n+\tlval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;\n+\tlval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;\n+\trc = mac->ops.write_iosf_sb_reg(hw,\n+\t\t\t\t\tIXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),\n+\t\t\t\t\tIXGBE_SB_IOSF_TARGET_KR_PHY, lval);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\trc = mac->ops.read_iosf_sb_reg(hw,\n+\t\t\t\t       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),\n+\t\t\t\t       IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tsval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;\n+\tsval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;\n+\trc = mac->ops.write_iosf_sb_reg(hw,\n+\t\t\t\t\tIXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),\n+\t\t\t\t\tIXGBE_SB_IOSF_TARGET_KR_PHY, sval);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\trc = mac->ops.write_iosf_sb_reg(hw,\n+\t\t\t\t\tIXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),\n+\t\t\t\t\tIXGBE_SB_IOSF_TARGET_KR_PHY, lval);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\trc = mac->ops.read_iosf_sb_reg(hw,\n+\t\t\t\t    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),\n+\t\t\t\t    IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tflx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;\n+\tflx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;\n+\tflx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;\n+\tflx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;\n+\tflx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;\n+\n+\trc = mac->ops.write_iosf_sb_reg(hw,\n+\t\t\t\t    IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),\n+\t\t\t\t    IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tixgbe_restart_an_internal_phy_x550em(hw);\n+\n+\treturn hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);\n+}\n+\n+/**\n+ * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37\n+ * @hw: pointer to hardware structure\n+ *\n+ * Enable flow control according to IEEE clause 37.\n+ */\n+static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)\n+{\n+\ts32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;\n+\tu32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\tixgbe_link_speed speed;\n+\tbool link_up;\n+\n+\t/* AN should have completed when the cable was plugged in.\n+\t * Look for reasons to bail out.  Bail out if:\n+\t * - FC autoneg is disabled, or if\n+\t * - link is not up.\n+\t */\n+\tif (hw->fc.disable_fc_autoneg)\n+\t\tgoto out;\n+\n+\thw->mac.ops.check_link(hw, &speed, &link_up, false);\n+\tif (!link_up)\n+\t\tgoto out;\n+\n+\t/* Check if auto-negotiation has completed */\n+\tstatus = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);\n+\tif (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {\n+\t\tstatus = IXGBE_ERR_FC_NOT_NEGOTIATED;\n+\t\tgoto out;\n+\t}\n+\n+\t/* Negotiate the flow control */\n+\tstatus = ixgbe_negotiate_fc(hw, info[0], info[0],\n+\t\t\t\t    FW_PHY_ACT_GET_LINK_INFO_FC_RX,\n+\t\t\t\t    FW_PHY_ACT_GET_LINK_INFO_FC_TX,\n+\t\t\t\t    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,\n+\t\t\t\t    FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX);\n+\n+out:\n+\tif (!status) {\n+\t\thw->fc.fc_was_autonegged = true;\n+\t} else {\n+\t\thw->fc.fc_was_autonegged = false;\n+\t\thw->fc.current_mode = hw->fc.requested_mode;\n+\t}\n+}\n+\n /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers\n  *  @hw: pointer to hardware structure\n  **/\n@@ -1806,6 +2090,17 @@ static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)\n \t\tmac->ops.setup_fc = NULL;\n \t\tmac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;\n \t\tbreak;\n+\tcase ixgbe_media_type_copper:\n+\t\tif (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T &&\n+\t\t    hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) {\n+\t\t\tmac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;\n+\t\t\tbreak;\n+\t\t}\n+\t\tmac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;\n+\t\tmac->ops.setup_fc = ixgbe_fc_autoneg_fw;\n+\t\tmac->ops.setup_link = ixgbe_setup_sgmii_fw;\n+\t\tmac->ops.check_link = ixgbe_check_mac_link_generic;\n+\t\tbreak;\n \tcase ixgbe_media_type_backplane:\n \t\tmac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;\n \t\tmac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;\n@@ -1853,7 +2148,7 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)\n \t\tmac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;\n \t\tmac->ops.setup_fc = ixgbe_setup_fc_generic;\n \t\tmac->ops.check_link = ixgbe_check_link_t_X550em;\n-\t\treturn;\n+\t\tbreak;\n \tcase ixgbe_media_type_backplane:\n \t\tif (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||\n \t\t    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)\n@@ -1896,6 +2191,12 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,\n \t\t\t\t\t      ixgbe_link_speed *speed,\n \t\t\t\t\t      bool *autoneg)\n {\n+\tif (hw->phy.type == ixgbe_phy_fw) {\n+\t\t*autoneg = true;\n+\t\t*speed = hw->phy.speeds_supported;\n+\t\treturn 0;\n+\t}\n+\n \t/* SFP */\n \tif (hw->phy.media_type == ixgbe_media_type_fiber) {\n \t\t/* CS4227 SFP must not enable auto-negotiation */\n@@ -2697,6 +2998,50 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)\n }\n \n /**\n+ * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs\n+ * @hw: pointer to hardware structure\n+ */\n+static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw)\n+{\n+\tu32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\ts32 rc;\n+\n+\tif (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw))\n+\t\treturn 0;\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store);\n+\tif (rc)\n+\t\treturn rc;\n+\tmemset(store, 0, sizeof(store));\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\treturn ixgbe_setup_fw_link(hw);\n+}\n+\n+/**\n+ * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp\n+ * @hw: pointer to hardware structure\n+ */\n+static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)\n+{\n+\tu32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };\n+\ts32 rc;\n+\n+\trc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);\n+\tif (rc)\n+\t\treturn rc;\n+\n+\tif (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {\n+\t\tixgbe_shutdown_fw_phy(hw);\n+\t\treturn IXGBE_ERR_OVERTEMP;\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n  * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register\n  * @hw: pointer to hardware structure\n  *\n@@ -2782,6 +3127,10 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)\n \t\tphy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;\n \t\tphy->ops.reset = ixgbe_reset_phy_t_X550em;\n \t\tbreak;\n+\tcase ixgbe_phy_fw:\n+\t\tphy->ops.setup_link = ixgbe_setup_fw_link;\n+\t\tphy->ops.reset = ixgbe_reset_phy_fw;\n+\t\tbreak;\n \tdefault:\n \t\tbreak;\n \t}\n@@ -2819,6 +3168,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)\n \tcase IXGBE_DEV_ID_X550EM_X_1G_T:\n \tcase IXGBE_DEV_ID_X550EM_X_10G_T:\n \tcase IXGBE_DEV_ID_X550EM_A_10G_T:\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T:\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T_L:\n \t\tmedia_type = ixgbe_media_type_copper;\n \t\tbreak;\n \tdefault:\n@@ -2886,6 +3237,13 @@ static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw)\n \t\thlreg0 &= ~IXGBE_HLREG0_MDCSPD;\n \t\tIXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);\n \t\tbreak;\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T:\n+\tcase IXGBE_DEV_ID_X550EM_A_1G_T_L:\n+\t\t/* Select fast MDIO clock speed for these devices */\n+\t\thlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);\n+\t\thlreg0 |= IXGBE_HLREG0_MDCSPD;\n+\t\tIXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);\n+\t\tbreak;\n \tdefault:\n \t\tbreak;\n \t}\n@@ -3397,6 +3755,27 @@ static struct ixgbe_mac_operations mac_ops_x550em_a = {\n \t.write_iosf_sb_reg\t= ixgbe_write_iosf_sb_reg_x550a,\n };\n \n+static struct ixgbe_mac_operations mac_ops_x550em_a_fw = {\n+\tX550_COMMON_MAC\n+\t.led_on\t\t\t= ixgbe_led_on_generic,\n+\t.led_off\t\t= ixgbe_led_off_generic,\n+\t.init_led_link_act\t= ixgbe_init_led_link_act_generic,\n+\t.reset_hw\t\t= ixgbe_reset_hw_X550em,\n+\t.get_media_type\t\t= ixgbe_get_media_type_X550em,\n+\t.get_san_mac_addr\t= NULL,\n+\t.get_wwn_prefix\t\t= NULL,\n+\t.setup_link\t\t= NULL, /* defined later */\n+\t.get_link_capabilities\t= ixgbe_get_link_capabilities_X550em,\n+\t.get_bus_info\t\t= ixgbe_get_bus_info_X550em,\n+\t.setup_sfp\t\t= ixgbe_setup_sfp_modules_X550em,\n+\t.acquire_swfw_sync\t= ixgbe_acquire_swfw_sync_x550em_a,\n+\t.release_swfw_sync\t= ixgbe_release_swfw_sync_x550em_a,\n+\t.setup_fc\t\t= ixgbe_setup_fc_x550em,\n+\t.fc_autoneg\t\t= ixgbe_fc_autoneg,\n+\t.read_iosf_sb_reg\t= ixgbe_read_iosf_sb_reg_x550a,\n+\t.write_iosf_sb_reg\t= ixgbe_write_iosf_sb_reg_x550a,\n+};\n+\n #define X550_COMMON_EEP \\\n \t.read\t\t\t= &ixgbe_read_ee_hostif_X550, \\\n \t.read_buffer\t\t= &ixgbe_read_ee_hostif_buffer_X550, \\\n@@ -3426,11 +3805,11 @@ static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {\n \t.read_i2c_eeprom\t= &ixgbe_read_i2c_eeprom_generic, \\\n \t.write_i2c_eeprom\t= &ixgbe_write_i2c_eeprom_generic, \\\n \t.setup_link\t\t= &ixgbe_setup_phy_link_generic, \\\n-\t.set_phy_power\t\t= NULL, \\\n-\t.check_overtemp\t\t= &ixgbe_tn_check_overtemp,\n+\t.set_phy_power\t\t= NULL,\n \n static const struct ixgbe_phy_operations phy_ops_X550 = {\n \tX550_COMMON_PHY\n+\t.check_overtemp\t\t= &ixgbe_tn_check_overtemp,\n \t.init\t\t\t= NULL,\n \t.identify\t\t= &ixgbe_identify_phy_generic,\n \t.read_reg\t\t= &ixgbe_read_phy_reg_generic,\n@@ -3439,6 +3818,7 @@ static const struct ixgbe_phy_operations phy_ops_X550 = {\n \n static const struct ixgbe_phy_operations phy_ops_X550EM_x = {\n \tX550_COMMON_PHY\n+\t.check_overtemp\t\t= &ixgbe_tn_check_overtemp,\n \t.init\t\t\t= &ixgbe_init_phy_ops_X550em,\n \t.identify\t\t= &ixgbe_identify_phy_x550em,\n \t.read_reg\t\t= &ixgbe_read_phy_reg_generic,\n@@ -3447,6 +3827,7 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = {\n \n static const struct ixgbe_phy_operations phy_ops_x550em_a = {\n \tX550_COMMON_PHY\n+\t.check_overtemp\t\t= &ixgbe_tn_check_overtemp,\n \t.init\t\t\t= &ixgbe_init_phy_ops_X550em,\n \t.identify\t\t= &ixgbe_identify_phy_x550em,\n \t.read_reg\t\t= &ixgbe_read_phy_reg_x550a,\n@@ -3455,6 +3836,17 @@ static const struct ixgbe_phy_operations phy_ops_x550em_a = {\n \t.write_reg_mdi\t\t= &ixgbe_write_phy_reg_mdi,\n };\n \n+static const struct ixgbe_phy_operations phy_ops_x550em_a_fw = {\n+\tX550_COMMON_PHY\n+\t.check_overtemp\t\t= ixgbe_check_overtemp_fw,\n+\t.init\t\t\t= ixgbe_init_phy_ops_X550em,\n+\t.identify\t\t= ixgbe_identify_phy_fw,\n+\t.read_reg\t\t= NULL,\n+\t.write_reg\t\t= NULL,\n+\t.read_reg_mdi\t\t= NULL,\n+\t.write_reg_mdi\t\t= NULL,\n+};\n+\n static const struct ixgbe_link_operations link_ops_x550em_x = {\n \t.read_link\t\t= &ixgbe_read_i2c_combined_generic,\n \t.read_link_unlocked\t= &ixgbe_read_i2c_combined_generic_unlocked,\n@@ -3504,3 +3896,13 @@ const struct ixgbe_info ixgbe_x550em_a_info = {\n \t.mbx_ops\t\t= &mbx_ops_generic,\n \t.mvals\t\t\t= ixgbe_mvals_x550em_a,\n };\n+\n+const struct ixgbe_info ixgbe_x550em_a_fw_info = {\n+\t.mac\t\t\t= ixgbe_mac_x550em_a,\n+\t.get_invariants\t\t= ixgbe_get_invariants_X550_a_fw,\n+\t.mac_ops\t\t= &mac_ops_x550em_a_fw,\n+\t.eeprom_ops\t\t= &eeprom_ops_X550EM_x,\n+\t.phy_ops\t\t= &phy_ops_x550em_a_fw,\n+\t.mbx_ops\t\t= &mbx_ops_generic,\n+\t.mvals\t\t\t= ixgbe_mvals_x550em_a,\n+};\n",
    "prefixes": [
        "V4",
        "4/4"
    ]
}