Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/982294/?format=api
{ "id": 982294, "url": "http://patchwork.ozlabs.org/api/patches/982294/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20181011071734.1996-1-sasha.neftin@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": "<20181011071734.1996-1-sasha.neftin@intel.com>", "list_archive_url": null, "date": "2018-10-11T07:17:34", "name": "[v8,10/11] igc: Add setup link functionality", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "b257e0a0699bb6241eb6677aba2be67038bd9070", "submitter": { "id": 69860, "url": "http://patchwork.ozlabs.org/api/people/69860/?format=api", "name": "Sasha Neftin", "email": "sasha.neftin@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/20181011071734.1996-1-sasha.neftin@intel.com/mbox/", "series": [ { "id": 70170, "url": "http://patchwork.ozlabs.org/api/series/70170/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=70170", "date": "2018-10-11T07:17:13", "name": "[v8,01/11] igc: Add skeletal frame for Intel(R) 2.5G Ethernet Controller support.", "version": 8, "mbox": "http://patchwork.ozlabs.org/series/70170/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/982294/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/982294/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 42W2Ny4NbPz9s8F\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 11 Oct 2018 18:17:54 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id F08F886A01;\n\tThu, 11 Oct 2018 07:17:52 +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 NLoHagDVOzYW; Thu, 11 Oct 2018 07:17:50 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 0A7FD85BDF;\n\tThu, 11 Oct 2018 07:17:50 +0000 (UTC)", "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\tby ash.osuosl.org (Postfix) with ESMTP id 25F3F1C1507\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 11 Oct 2018 07:17:48 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 221EE8705D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 11 Oct 2018 07:17:48 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id pCyfi6crixPk for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 11 Oct 2018 07:17:46 +0000 (UTC)", "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby whitealder.osuosl.org (Postfix) with ESMTPS id 2E05D8546D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 11 Oct 2018 07:17:46 +0000 (UTC)", "from fmsmga007.fm.intel.com ([10.253.24.52])\n\tby fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t11 Oct 2018 00:17:45 -0700", "from ccdlinuxdev08.iil.intel.com ([143.185.161.150])\n\tby fmsmga007.fm.intel.com with ESMTP; 11 Oct 2018 00:17:34 -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.54,367,1534834800\"; d=\"scan'208\";a=\"77163484\"", "From": "Sasha Neftin <sasha.neftin@intel.com>", "To": "sasha.neftin@intel.com,\n\tintel-wired-lan@lists.osuosl.org", "Date": "Thu, 11 Oct 2018 10:17:34 +0300", "Message-Id": "<20181011071734.1996-1-sasha.neftin@intel.com>", "X-Mailer": "git-send-email 2.11.0", "Subject": "[Intel-wired-lan] [PATCH v8 10/11] igc: Add setup link functionality", "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>", "MIME-Version": "1.0", "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": "Add link establishment methods\nAdd auto negotiation methods\nAdd read MAC address method\n\nSasha Neftin (v2):\nminor cosmetic changes\n\nSasha Neftin (v3):\nremove not addressed methods\n\nSasha Neftin (v4):\naddress comments\nremove improperly insertion of method from a patch\nreplace e1000_ prefix with igc_ prefix\nremove duplicate PHY MII defines\n\nSasha Neftin (v5):\ncode clean\nremove obsolete flash_address reference\nfix initial autoneg advertisement and add 2.5G option\nadd option to clear the 2.5 Gbps advertising bit and disable 2.5 Gbps speed\n\nSasha Neftin (v6):\nminor cosmetic changes\n\nSasha Neftin (v7):\nno changes\n\nSasha Neftin (v8):\nfix whitespaces in comments\nremove unneeded forward declarations\n\nSigned-off-by: Sasha Neftin <sasha.neftin@intel.com>\n---\n drivers/net/ethernet/intel/igc/igc.h | 1 +\n drivers/net/ethernet/intel/igc/igc_base.c | 40 ++++\n drivers/net/ethernet/intel/igc/igc_defines.h | 38 +++\n drivers/net/ethernet/intel/igc/igc_mac.c | 271 ++++++++++++++++++++++\n drivers/net/ethernet/intel/igc/igc_mac.h | 2 +\n drivers/net/ethernet/intel/igc/igc_main.c | 30 +++\n drivers/net/ethernet/intel/igc/igc_phy.c | 334 +++++++++++++++++++++++++++\n drivers/net/ethernet/intel/igc/igc_phy.h | 1 +\n 8 files changed, 717 insertions(+)", "diff": "diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h\nindex 7cfbd83d25e4..86fa889b4ab6 100644\n--- a/drivers/net/ethernet/intel/igc/igc.h\n+++ b/drivers/net/ethernet/intel/igc/igc.h\n@@ -314,6 +314,7 @@ struct igc_adapter {\n \tstruct work_struct reset_task;\n \tstruct work_struct watchdog_task;\n \tstruct work_struct dma_err_task;\n+\tbool fc_autoneg;\n \n \tu8 tx_timeout_factor;\n \ndiff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c\nindex 55faef987479..832da609d9a7 100644\n--- a/drivers/net/ethernet/intel/igc/igc_base.c\n+++ b/drivers/net/ethernet/intel/igc/igc_base.c\n@@ -178,6 +178,29 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw)\n }\n \n /**\n+ * igc_setup_copper_link_base - Configure copper link settings\n+ * @hw: pointer to the HW structure\n+ *\n+ * Configures the link for auto-neg or forced speed and duplex. Then we check\n+ * for link, once link is established calls to configure collision distance\n+ * and flow control are called.\n+ */\n+static s32 igc_setup_copper_link_base(struct igc_hw *hw)\n+{\n+\ts32 ret_val = 0;\n+\tu32 ctrl;\n+\n+\tctrl = rd32(IGC_CTRL);\n+\tctrl |= IGC_CTRL_SLU;\n+\tctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);\n+\twr32(IGC_CTRL, ctrl);\n+\n+\tret_val = igc_setup_copper_link(hw);\n+\n+\treturn ret_val;\n+}\n+\n+/**\n * igc_init_mac_params_base - Init MAC func ptrs.\n * @hw: pointer to the HW structure\n */\n@@ -200,6 +223,9 @@ static s32 igc_init_mac_params_base(struct igc_hw *hw)\n \tif (mac->type == igc_i225)\n \t\tdev_spec->clear_semaphore_once = true;\n \n+\t/* physical interface link setup */\n+\tmac->ops.setup_physical_interface = igc_setup_copper_link_base;\n+\n \treturn 0;\n }\n \n@@ -242,6 +268,8 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw)\n \tif (ret_val)\n \t\treturn ret_val;\n \n+\tigc_check_for_link_base(hw);\n+\n \t/* Verify phy id and set remaining function pointers */\n \tswitch (phy->id) {\n \tcase I225_I_PHY_ID:\n@@ -258,10 +286,22 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw)\n \n static s32 igc_get_invariants_base(struct igc_hw *hw)\n {\n+\tstruct igc_mac_info *mac = &hw->mac;\n \tu32 link_mode = 0;\n \tu32 ctrl_ext = 0;\n \ts32 ret_val = 0;\n \n+\tswitch (hw->device_id) {\n+\tcase IGC_DEV_ID_I225_LM:\n+\tcase IGC_DEV_ID_I225_V:\n+\t\tmac->type = igc_i225;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -IGC_ERR_MAC_INIT;\n+\t}\n+\n+\thw->phy.media_type = igc_media_type_copper;\n+\n \tctrl_ext = rd32(IGC_CTRL_EXT);\n \tlink_mode = ctrl_ext & IGC_CTRL_EXT_LINK_MODE_MASK;\n \ndiff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h\nindex d271671e6825..70275a0e85d7 100644\n--- a/drivers/net/ethernet/intel/igc/igc_defines.h\n+++ b/drivers/net/ethernet/intel/igc/igc_defines.h\n@@ -13,6 +13,11 @@\n /* Physical Func Reset Done Indication */\n #define IGC_CTRL_EXT_LINK_MODE_MASK\t0x00C00000\n \n+/* Loop limit on how long we wait for auto-negotiation to complete */\n+#define COPPER_LINK_UP_LIMIT\t\t10\n+#define PHY_AUTO_NEG_LIMIT\t\t45\n+#define PHY_FORCE_LIMIT\t\t\t20\n+\n /* Number of 100 microseconds we wait for PCI Express master disable */\n #define MASTER_DISABLE_TIMEOUT\t\t800\n /*Blocks new Master requests */\n@@ -54,6 +59,12 @@\n #define IGC_CTRL_RST\t\t0x04000000 /* Global reset */\n \n #define IGC_CTRL_PHY_RST\t0x80000000 /* PHY Reset */\n+#define IGC_CTRL_SLU\t\t0x00000040 /* Set link up (Force Link) */\n+#define IGC_CTRL_FRCSPD\t\t0x00000800 /* Force Speed */\n+#define IGC_CTRL_FRCDPX\t\t0x00001000 /* Force Duplex */\n+\n+#define IGC_CTRL_RFCE\t\t0x08000000 /* Receive Flow Control enable */\n+#define IGC_CTRL_TFCE\t\t0x10000000 /* Transmit flow control enable */\n \n /* PBA constants */\n #define IGC_PBA_34K\t\t0x0022\n@@ -66,6 +77,29 @@\n #define IGC_SWFW_EEP_SM\t\t0x1\n #define IGC_SWFW_PHY0_SM\t0x2\n \n+/* Autoneg Advertisement Register */\n+#define NWAY_AR_10T_HD_CAPS\t0x0020 /* 10T Half Duplex Capable */\n+#define NWAY_AR_10T_FD_CAPS\t0x0040 /* 10T Full Duplex Capable */\n+#define NWAY_AR_100TX_HD_CAPS\t0x0080 /* 100TX Half Duplex Capable */\n+#define NWAY_AR_100TX_FD_CAPS\t0x0100 /* 100TX Full Duplex Capable */\n+#define NWAY_AR_PAUSE\t\t0x0400 /* Pause operation desired */\n+#define NWAY_AR_ASM_DIR\t\t0x0800 /* Asymmetric Pause Direction bit */\n+\n+/* Link Partner Ability Register (Base Page) */\n+#define NWAY_LPAR_PAUSE\t\t0x0400 /* LP Pause operation desired */\n+#define NWAY_LPAR_ASM_DIR\t0x0800 /* LP Asymmetric Pause Direction bit */\n+\n+/* 1000BASE-T Control Register */\n+#define CR_1000T_ASYM_PAUSE\t0x0080 /* Advertise asymmetric pause bit */\n+#define CR_1000T_HD_CAPS\t0x0100 /* Advertise 1000T HD capability */\n+#define CR_1000T_FD_CAPS\t0x0200 /* Advertise 1000T FD capability */\n+\n+/* PHY GPY 211 registers */\n+#define STANDARD_AN_REG_MASK\t0x0007 /* MMD */\n+#define ANEG_MULTIGBT_AN_CTRL\t0x0020 /* MULTI GBT AN Control Register */\n+#define MMD_DEVADDR_SHIFT\t16 /* Shift MMD to higher bits */\n+#define CR_2500T_FD_CAPS\t0x0080 /* Advertise 2500T FD capability */\n+\n /* NVM Control */\n /* Number of milliseconds for NVM auto read done after MAC reset. */\n #define AUTO_READ_DONE_TIMEOUT\t\t10\n@@ -318,6 +352,10 @@\n #define PHY_STATUS\t\t0x01 /* Status Register */\n #define PHY_ID1\t\t\t0x02 /* Phy Id Reg (word 1) */\n #define PHY_ID2\t\t\t0x03 /* Phy Id Reg (word 2) */\n+#define PHY_AUTONEG_ADV\t\t0x04 /* Autoneg Advertisement */\n+#define PHY_LP_ABILITY\t\t0x05 /* Link Partner Ability (Base Page) */\n+#define PHY_1000T_CTRL\t\t0x09 /* 1000Base-T Control Reg */\n+#define PHY_1000T_STATUS\t0x0A /* 1000Base-T Status Reg */\n \n /* Bit definitions for valid PHY IDs. I = Integrated E = External */\n #define I225_I_PHY_ID\t\t0x67C9DC00\ndiff --git a/drivers/net/ethernet/intel/igc/igc_mac.c b/drivers/net/ethernet/intel/igc/igc_mac.c\nindex fce7f7f5aa46..f7683d3ae47c 100644\n--- a/drivers/net/ethernet/intel/igc/igc_mac.c\n+++ b/drivers/net/ethernet/intel/igc/igc_mac.c\n@@ -92,6 +92,8 @@ s32 igc_setup_link(struct igc_hw *hw)\n \t/* In the case of the phy reset being blocked, we already have a link.\n \t * We do not need to set it up again.\n \t */\n+\tif (igc_check_reset_block(hw))\n+\t\tgoto out;\n \n \t/* If requested flow control is set to default, set flow control\n \t * based on the EEPROM flow control settings.\n@@ -142,10 +144,74 @@ s32 igc_setup_link(struct igc_hw *hw)\n */\n static s32 igc_set_default_fc(struct igc_hw *hw)\n {\n+\thw->fc.requested_mode = igc_fc_full;\n \treturn 0;\n }\n \n /**\n+ * igc_force_mac_fc - Force the MAC's flow control settings\n+ * @hw: pointer to the HW structure\n+ *\n+ * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the\n+ * device control register to reflect the adapter settings. TFCE and RFCE\n+ * need to be explicitly set by software when a copper PHY is used because\n+ * autonegotiation is managed by the PHY rather than the MAC. Software must\n+ * also configure these bits when link is forced on a fiber connection.\n+ */\n+s32 igc_force_mac_fc(struct igc_hw *hw)\n+{\n+\ts32 ret_val = 0;\n+\tu32 ctrl;\n+\n+\tctrl = rd32(IGC_CTRL);\n+\n+\t/* Because we didn't get link via the internal auto-negotiation\n+\t * mechanism (we either forced link or we got link via PHY\n+\t * auto-neg), we have to manually enable/disable transmit an\n+\t * receive flow control.\n+\t *\n+\t * The \"Case\" statement below enables/disable flow control\n+\t * according to the \"hw->fc.current_mode\" parameter.\n+\t *\n+\t * The possible values of the \"fc\" parameter are:\n+\t * 0: Flow control is completely disabled\n+\t * 1: Rx flow control is enabled (we can receive pause\n+\t * frames but not send pause frames).\n+\t * 2: Tx flow control is enabled (we can send pause frames\n+\t * frames but we do not receive pause frames).\n+\t * 3: Both Rx and TX flow control (symmetric) is enabled.\n+\t * other: No other values should be possible at this point.\n+\t */\n+\thw_dbg(\"hw->fc.current_mode = %u\\n\", hw->fc.current_mode);\n+\n+\tswitch (hw->fc.current_mode) {\n+\tcase igc_fc_none:\n+\t\tctrl &= (~(IGC_CTRL_TFCE | IGC_CTRL_RFCE));\n+\t\tbreak;\n+\tcase igc_fc_rx_pause:\n+\t\tctrl &= (~IGC_CTRL_TFCE);\n+\t\tctrl |= IGC_CTRL_RFCE;\n+\t\tbreak;\n+\tcase igc_fc_tx_pause:\n+\t\tctrl &= (~IGC_CTRL_RFCE);\n+\t\tctrl |= IGC_CTRL_TFCE;\n+\t\tbreak;\n+\tcase igc_fc_full:\n+\t\tctrl |= (IGC_CTRL_TFCE | IGC_CTRL_RFCE);\n+\t\tbreak;\n+\tdefault:\n+\t\thw_dbg(\"Flow control param set incorrectly\\n\");\n+\t\tret_val = -IGC_ERR_CONFIG;\n+\t\tgoto out;\n+\t}\n+\n+\twr32(IGC_CTRL, ctrl);\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/**\n * igc_set_fc_watermarks - Set flow control high/low watermarks\n * @hw: pointer to the HW structure\n *\n@@ -371,6 +437,7 @@ s32 igc_check_for_copper_link(struct igc_hw *hw)\n \t * settings because we may have had to re-autoneg with a\n \t * different link partner.\n \t */\n+\tret_val = igc_config_fc_after_link_up(hw);\n \tif (ret_val)\n \t\thw_dbg(\"Error configuring flow control\\n\");\n \n@@ -400,6 +467,210 @@ void igc_config_collision_dist(struct igc_hw *hw)\n }\n \n /**\n+ * igc_config_fc_after_link_up - Configures flow control after link\n+ * @hw: pointer to the HW structure\n+ *\n+ * Checks the status of auto-negotiation after link up to ensure that the\n+ * speed and duplex were not forced. If the link needed to be forced, then\n+ * flow control needs to be forced also. If auto-negotiation is enabled\n+ * and did not fail, then we configure flow control based on our link\n+ * partner.\n+ */\n+s32 igc_config_fc_after_link_up(struct igc_hw *hw)\n+{\n+\tu16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;\n+\tstruct igc_mac_info *mac = &hw->mac;\n+\tu16 speed, duplex;\n+\ts32 ret_val = 0;\n+\n+\t/* Check for the case where we have fiber media and auto-neg failed\n+\t * so we had to force link. In this case, we need to force the\n+\t * configuration of the MAC to match the \"fc\" parameter.\n+\t */\n+\tif (mac->autoneg_failed) {\n+\t\tif (hw->phy.media_type == igc_media_type_copper)\n+\t\t\tret_val = igc_force_mac_fc(hw);\n+\t}\n+\n+\tif (ret_val) {\n+\t\thw_dbg(\"Error forcing flow control settings\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\t/* Check for the case where we have copper media and auto-neg is\n+\t * enabled. In this case, we need to check and see if Auto-Neg\n+\t * has completed, and if so, how the PHY and link partner has\n+\t * flow control configured.\n+\t */\n+\tif (hw->phy.media_type == igc_media_type_copper && mac->autoneg) {\n+\t\t/* Read the MII Status Register and check to see if AutoNeg\n+\t\t * has completed. We read this twice because this reg has\n+\t\t * some \"sticky\" (latched) bits.\n+\t\t */\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,\n+\t\t\t\t\t &mii_status_reg);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,\n+\t\t\t\t\t &mii_status_reg);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\n+\t\tif (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {\n+\t\t\thw_dbg(\"Copper PHY and Auto Neg has not completed.\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\t/* The AutoNeg process has completed, so we now need to\n+\t\t * read both the Auto Negotiation Advertisement\n+\t\t * Register (Address 4) and the Auto_Negotiation Base\n+\t\t * Page Ability Register (Address 5) to determine how\n+\t\t * flow control was negotiated.\n+\t\t */\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,\n+\t\t\t\t\t &mii_nway_adv_reg);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,\n+\t\t\t\t\t &mii_nway_lp_ability_reg);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\t\t/* Two bits in the Auto Negotiation Advertisement Register\n+\t\t * (Address 4) and two bits in the Auto Negotiation Base\n+\t\t * Page Ability Register (Address 5) determine flow control\n+\t\t * for both the PHY and the link partner. The following\n+\t\t * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,\n+\t\t * 1999, describes these PAUSE resolution bits and how flow\n+\t\t * control is determined based upon these settings.\n+\t\t * NOTE: DC = Don't Care\n+\t\t *\n+\t\t * LOCAL DEVICE | LINK PARTNER\n+\t\t * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution\n+\t\t *-------|---------|-------|---------|--------------------\n+\t\t * 0 | 0 | DC | DC | igc_fc_none\n+\t\t * 0 | 1 | 0 | DC | igc_fc_none\n+\t\t * 0 | 1 | 1 | 0 | igc_fc_none\n+\t\t * 0 | 1 | 1 | 1 | igc_fc_tx_pause\n+\t\t * 1 | 0 | 0 | DC | igc_fc_none\n+\t\t * 1 | DC | 1 | DC | igc_fc_full\n+\t\t * 1 | 1 | 0 | 0 | igc_fc_none\n+\t\t * 1 | 1 | 0 | 1 | igc_fc_rx_pause\n+\t\t *\n+\t\t * Are both PAUSE bits set to 1? If so, this implies\n+\t\t * Symmetric Flow Control is enabled at both ends. The\n+\t\t * ASM_DIR bits are irrelevant per the spec.\n+\t\t *\n+\t\t * For Symmetric Flow Control:\n+\t\t *\n+\t\t * LOCAL DEVICE | LINK PARTNER\n+\t\t * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result\n+\t\t *-------|---------|-------|---------|--------------------\n+\t\t * 1 | DC | 1 | DC | IGC_fc_full\n+\t\t *\n+\t\t */\n+\t\tif ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&\n+\t\t (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {\n+\t\t\t/* Now we need to check if the user selected RX ONLY\n+\t\t\t * of pause frames. In this case, we had to advertise\n+\t\t\t * FULL flow control because we could not advertise RX\n+\t\t\t * ONLY. Hence, we must now check to see if we need to\n+\t\t\t * turn OFF the TRANSMISSION of PAUSE frames.\n+\t\t\t */\n+\t\t\tif (hw->fc.requested_mode == igc_fc_full) {\n+\t\t\t\thw->fc.current_mode = igc_fc_full;\n+\t\t\t\thw_dbg(\"Flow Control = FULL.\\n\");\n+\t\t\t} else {\n+\t\t\t\thw->fc.current_mode = igc_fc_rx_pause;\n+\t\t\t\thw_dbg(\"Flow Control = RX PAUSE frames only.\\n\");\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* For receiving PAUSE frames ONLY.\n+\t\t *\n+\t\t * LOCAL DEVICE | LINK PARTNER\n+\t\t * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result\n+\t\t *-------|---------|-------|---------|--------------------\n+\t\t * 0 | 1 | 1 | 1 | igc_fc_tx_pause\n+\t\t */\n+\t\telse if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&\n+\t\t\t (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&\n+\t\t\t (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&\n+\t\t\t (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {\n+\t\t\thw->fc.current_mode = igc_fc_tx_pause;\n+\t\t\thw_dbg(\"Flow Control = TX PAUSE frames only.\\n\");\n+\t\t}\n+\t\t/* For transmitting PAUSE frames ONLY.\n+\t\t *\n+\t\t * LOCAL DEVICE | LINK PARTNER\n+\t\t * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result\n+\t\t *-------|---------|-------|---------|--------------------\n+\t\t * 1 | 1 | 0 | 1 | igc_fc_rx_pause\n+\t\t */\n+\t\telse if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&\n+\t\t\t (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&\n+\t\t\t !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&\n+\t\t\t (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {\n+\t\t\thw->fc.current_mode = igc_fc_rx_pause;\n+\t\t\thw_dbg(\"Flow Control = RX PAUSE frames only.\\n\");\n+\t\t}\n+\t\t/* Per the IEEE spec, at this point flow control should be\n+\t\t * disabled. However, we want to consider that we could\n+\t\t * be connected to a legacy switch that doesn't advertise\n+\t\t * desired flow control, but can be forced on the link\n+\t\t * partner. So if we advertised no flow control, that is\n+\t\t * what we will resolve to. If we advertised some kind of\n+\t\t * receive capability (Rx Pause Only or Full Flow Control)\n+\t\t * and the link partner advertised none, we will configure\n+\t\t * ourselves to enable Rx Flow Control only. We can do\n+\t\t * this safely for two reasons: If the link partner really\n+\t\t * didn't want flow control enabled, and we enable Rx, no\n+\t\t * harm done since we won't be receiving any PAUSE frames\n+\t\t * anyway. If the intent on the link partner was to have\n+\t\t * flow control enabled, then by us enabling RX only, we\n+\t\t * can at least receive pause frames and process them.\n+\t\t * This is a good idea because in most cases, since we are\n+\t\t * predominantly a server NIC, more times than not we will\n+\t\t * be asked to delay transmission of packets than asking\n+\t\t * our link partner to pause transmission of frames.\n+\t\t */\n+\t\telse if ((hw->fc.requested_mode == igc_fc_none) ||\n+\t\t\t (hw->fc.requested_mode == igc_fc_tx_pause) ||\n+\t\t\t (hw->fc.strict_ieee)) {\n+\t\t\thw->fc.current_mode = igc_fc_none;\n+\t\t\thw_dbg(\"Flow Control = NONE.\\n\");\n+\t\t} else {\n+\t\t\thw->fc.current_mode = igc_fc_rx_pause;\n+\t\t\thw_dbg(\"Flow Control = RX PAUSE frames only.\\n\");\n+\t\t}\n+\n+\t\t/* Now we need to do one last check... If we auto-\n+\t\t * negotiated to HALF DUPLEX, flow control should not be\n+\t\t * enabled per IEEE 802.3 spec.\n+\t\t */\n+\t\tret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);\n+\t\tif (ret_val) {\n+\t\t\thw_dbg(\"Error getting link speed and duplex\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (duplex == HALF_DUPLEX)\n+\t\t\thw->fc.current_mode = igc_fc_none;\n+\n+\t\t/* Now we call a subroutine to actually force the MAC\n+\t\t * controller to use the correct flow control settings.\n+\t\t */\n+\t\tret_val = igc_force_mac_fc(hw);\n+\t\tif (ret_val) {\n+\t\t\thw_dbg(\"Error forcing flow control settings\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+out:\n+\treturn 0;\n+}\n+\n+/**\n * igc_get_auto_rd_done - Check for auto read completion\n * @hw: pointer to the HW structure\n *\ndiff --git a/drivers/net/ethernet/intel/igc/igc_mac.h b/drivers/net/ethernet/intel/igc/igc_mac.h\nindex c842cc561123..782bc995badc 100644\n--- a/drivers/net/ethernet/intel/igc/igc_mac.h\n+++ b/drivers/net/ethernet/intel/igc/igc_mac.h\n@@ -15,6 +15,8 @@\n /* forward declaration */\n s32 igc_disable_pcie_master(struct igc_hw *hw);\n s32 igc_check_for_copper_link(struct igc_hw *hw);\n+s32 igc_config_fc_after_link_up(struct igc_hw *hw);\n+s32 igc_force_mac_fc(struct igc_hw *hw);\n void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count);\n s32 igc_setup_link(struct igc_hw *hw);\n void igc_clear_hw_cntrs_base(struct igc_hw *hw);\ndiff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c\nindex 14f324826604..e1a078e084f0 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -3403,6 +3403,25 @@ static int igc_probe(struct pci_dev *pdev,\n \tnetdev->min_mtu = ETH_MIN_MTU;\n \tnetdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;\n \n+\t/* before reading the NVM, reset the controller to put the device in a\n+\t * known good starting state\n+\t */\n+\thw->mac.ops.reset_hw(hw);\n+\n+\tif (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) {\n+\t\t/* copy the MAC address out of the NVM */\n+\t\tif (hw->mac.ops.read_mac_addr(hw))\n+\t\t\tdev_err(&pdev->dev, \"NVM Read Error\\n\");\n+\t}\n+\n+\tmemcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);\n+\n+\tif (!is_valid_ether_addr(netdev->dev_addr)) {\n+\t\tdev_err(&pdev->dev, \"Invalid MAC Address\\n\");\n+\t\terr = -EIO;\n+\t\tgoto err_eeprom;\n+\t}\n+\n \t/* configure RXPBSIZE and TXPBSIZE */\n \twr32(IGC_RXPBS, I225_RXPBSIZE_DEFAULT);\n \twr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);\n@@ -3411,6 +3430,14 @@ static int igc_probe(struct pci_dev *pdev,\n \n \tINIT_WORK(&adapter->reset_task, igc_reset_task);\n \n+\t/* Initialize link properties that are user-changeable */\n+\tadapter->fc_autoneg = true;\n+\thw->mac.autoneg = true;\n+\thw->phy.autoneg_advertised = 0xaf;\n+\n+\thw->fc.requested_mode = igc_fc_default;\n+\thw->fc.current_mode = igc_fc_default;\n+\n \t/* reset the hardware with the new settings */\n \tigc_reset(adapter);\n \n@@ -3438,6 +3465,9 @@ static int igc_probe(struct pci_dev *pdev,\n \n err_register:\n \tigc_release_hw_control(adapter);\n+err_eeprom:\n+\tif (!igc_check_reset_block(hw))\n+\t\tigc_reset_phy(hw);\n err_sw_init:\n \tigc_clear_interrupt_scheme(adapter);\n \tiounmap(adapter->io_addr);\ndiff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c\nindex 88583c1d4970..38e43e6fc1c7 100644\n--- a/drivers/net/ethernet/intel/igc/igc_phy.c\n+++ b/drivers/net/ethernet/intel/igc/igc_phy.c\n@@ -3,6 +3,10 @@\n \n #include \"igc_phy.h\"\n \n+/* forward declaration */\n+static s32 igc_phy_setup_autoneg(struct igc_hw *hw);\n+static s32 igc_wait_autoneg(struct igc_hw *hw);\n+\n /**\n * igc_check_reset_block - Check if PHY reset is blocked\n * @hw: pointer to the HW structure\n@@ -212,6 +216,336 @@ s32 igc_phy_hw_reset(struct igc_hw *hw)\n }\n \n /**\n+ * igc_copper_link_autoneg - Setup/Enable autoneg for copper link\n+ * @hw: pointer to the HW structure\n+ *\n+ * Performs initial bounds checking on autoneg advertisement parameter, then\n+ * configure to advertise the full capability. Setup the PHY to autoneg\n+ * and restart the negotiation process between the link partner. If\n+ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.\n+ */\n+static s32 igc_copper_link_autoneg(struct igc_hw *hw)\n+{\n+\tstruct igc_phy_info *phy = &hw->phy;\n+\tu16 phy_ctrl;\n+\ts32 ret_val;\n+\n+\t/* Perform some bounds checking on the autoneg advertisement\n+\t * parameter.\n+\t */\n+\tphy->autoneg_advertised &= phy->autoneg_mask;\n+\n+\t/* If autoneg_advertised is zero, we assume it was not defaulted\n+\t * by the calling code so we set to advertise full capability.\n+\t */\n+\tif (phy->autoneg_advertised == 0)\n+\t\tphy->autoneg_advertised = phy->autoneg_mask;\n+\n+\thw_dbg(\"Reconfiguring auto-neg advertisement params\\n\");\n+\tret_val = igc_phy_setup_autoneg(hw);\n+\tif (ret_val) {\n+\t\thw_dbg(\"Error Setting up Auto-Negotiation\\n\");\n+\t\tgoto out;\n+\t}\n+\thw_dbg(\"Restarting Auto-Neg\\n\");\n+\n+\t/* Restart auto-negotiation by setting the Auto Neg Enable bit and\n+\t * the Auto Neg Restart bit in the PHY control register.\n+\t */\n+\tret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);\n+\tif (ret_val)\n+\t\tgoto out;\n+\n+\tphy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);\n+\tret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);\n+\tif (ret_val)\n+\t\tgoto out;\n+\n+\t/* Does the user want to wait for Auto-Neg to complete here, or\n+\t * check at a later time (for example, callback routine).\n+\t */\n+\tif (phy->autoneg_wait_to_complete) {\n+\t\tret_val = igc_wait_autoneg(hw);\n+\t\tif (ret_val) {\n+\t\t\thw_dbg(\"Error while waiting for autoneg to complete\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\thw->mac.get_link_status = true;\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/**\n+ * igc_wait_autoneg - Wait for auto-neg completion\n+ * @hw: pointer to the HW structure\n+ *\n+ * Waits for auto-negotiation to complete or for the auto-negotiation time\n+ * limit to expire, which ever happens first.\n+ */\n+static s32 igc_wait_autoneg(struct igc_hw *hw)\n+{\n+\tu16 i, phy_status;\n+\ts32 ret_val = 0;\n+\n+\t/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */\n+\tfor (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);\n+\t\tif (ret_val)\n+\t\t\tbreak;\n+\t\tret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);\n+\t\tif (ret_val)\n+\t\t\tbreak;\n+\t\tif (phy_status & MII_SR_AUTONEG_COMPLETE)\n+\t\t\tbreak;\n+\t\tmsleep(100);\n+\t}\n+\n+\t/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation\n+\t * has completed.\n+\t */\n+\treturn ret_val;\n+}\n+\n+/**\n+ * igc_phy_setup_autoneg - Configure PHY for auto-negotiation\n+ * @hw: pointer to the HW structure\n+ *\n+ * Reads the MII auto-neg advertisement register and/or the 1000T control\n+ * register and if the PHY is already setup for auto-negotiation, then\n+ * return successful. Otherwise, setup advertisement and flow control to\n+ * the appropriate values for the wanted auto-negotiation.\n+ */\n+static s32 igc_phy_setup_autoneg(struct igc_hw *hw)\n+{\n+\tstruct igc_phy_info *phy = &hw->phy;\n+\tu16 aneg_multigbt_an_ctrl = 0;\n+\tu16 mii_1000t_ctrl_reg = 0;\n+\tu16 mii_autoneg_adv_reg;\n+\ts32 ret_val;\n+\n+\tphy->autoneg_advertised &= phy->autoneg_mask;\n+\n+\t/* Read the MII Auto-Neg Advertisement Register (Address 4). */\n+\tret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\tif (phy->autoneg_mask & ADVERTISE_1000_FULL) {\n+\t\t/* Read the MII 1000Base-T Control Register (Address 9). */\n+\t\tret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,\n+\t\t\t\t\t &mii_1000t_ctrl_reg);\n+\t\tif (ret_val)\n+\t\t\treturn ret_val;\n+\t}\n+\n+\tif ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&\n+\t hw->phy.id == I225_I_PHY_ID) {\n+\t\t/* Read the MULTI GBT AN Control Register - reg 7.32 */\n+\t\tret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<\n+\t\t\t\t\t MMD_DEVADDR_SHIFT) |\n+\t\t\t\t\t ANEG_MULTIGBT_AN_CTRL,\n+\t\t\t\t\t &aneg_multigbt_an_ctrl);\n+\n+\t\tif (ret_val)\n+\t\t\treturn ret_val;\n+\t}\n+\n+\t/* Need to parse both autoneg_advertised and fc and set up\n+\t * the appropriate PHY registers. First we will parse for\n+\t * autoneg_advertised software override. Since we can advertise\n+\t * a plethora of combinations, we need to check each bit\n+\t * individually.\n+\t */\n+\n+\t/* First we clear all the 10/100 mb speed bits in the Auto-Neg\n+\t * Advertisement Register (Address 4) and the 1000 mb speed bits in\n+\t * the 1000Base-T Control Register (Address 9).\n+\t */\n+\tmii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |\n+\t\t\t\t NWAY_AR_100TX_HD_CAPS |\n+\t\t\t\t NWAY_AR_10T_FD_CAPS |\n+\t\t\t\t NWAY_AR_10T_HD_CAPS);\n+\tmii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);\n+\n+\thw_dbg(\"autoneg_advertised %x\\n\", phy->autoneg_advertised);\n+\n+\t/* Do we want to advertise 10 Mb Half Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_10_HALF) {\n+\t\thw_dbg(\"Advertise 10mb Half duplex\\n\");\n+\t\tmii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;\n+\t}\n+\n+\t/* Do we want to advertise 10 Mb Full Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_10_FULL) {\n+\t\thw_dbg(\"Advertise 10mb Full duplex\\n\");\n+\t\tmii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;\n+\t}\n+\n+\t/* Do we want to advertise 100 Mb Half Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_100_HALF) {\n+\t\thw_dbg(\"Advertise 100mb Half duplex\\n\");\n+\t\tmii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;\n+\t}\n+\n+\t/* Do we want to advertise 100 Mb Full Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_100_FULL) {\n+\t\thw_dbg(\"Advertise 100mb Full duplex\\n\");\n+\t\tmii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;\n+\t}\n+\n+\t/* We do not allow the Phy to advertise 1000 Mb Half Duplex */\n+\tif (phy->autoneg_advertised & ADVERTISE_1000_HALF)\n+\t\thw_dbg(\"Advertise 1000mb Half duplex request denied!\\n\");\n+\n+\t/* Do we want to advertise 1000 Mb Full Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_1000_FULL) {\n+\t\thw_dbg(\"Advertise 1000mb Full duplex\\n\");\n+\t\tmii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;\n+\t}\n+\n+\t/* We do not allow the Phy to advertise 2500 Mb Half Duplex */\n+\tif (phy->autoneg_advertised & ADVERTISE_2500_HALF)\n+\t\thw_dbg(\"Advertise 2500mb Half duplex request denied!\\n\");\n+\n+\t/* Do we want to advertise 2500 Mb Full Duplex? */\n+\tif (phy->autoneg_advertised & ADVERTISE_2500_FULL) {\n+\t\thw_dbg(\"Advertise 2500mb Full duplex\\n\");\n+\t\taneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;\n+\t} else {\n+\t\taneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS;\n+\t}\n+\n+\t/* Check for a software override of the flow control settings, and\n+\t * setup the PHY advertisement registers accordingly. If\n+\t * auto-negotiation is enabled, then software will have to set the\n+\t * \"PAUSE\" bits to the correct value in the Auto-Negotiation\n+\t * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-\n+\t * negotiation.\n+\t *\n+\t * The possible values of the \"fc\" parameter are:\n+\t * 0: Flow control is completely disabled\n+\t * 1: Rx flow control is enabled (we can receive pause frames\n+\t * but not send pause frames).\n+\t * 2: Tx flow control is enabled (we can send pause frames\n+\t * but we do not support receiving pause frames).\n+\t * 3: Both Rx and Tx flow control (symmetric) are enabled.\n+\t * other: No software override. The flow control configuration\n+\t * in the EEPROM is used.\n+\t */\n+\tswitch (hw->fc.current_mode) {\n+\tcase igc_fc_none:\n+\t\t/* Flow control (Rx & Tx) is completely disabled by a\n+\t\t * software over-ride.\n+\t\t */\n+\t\tmii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);\n+\t\tbreak;\n+\tcase igc_fc_rx_pause:\n+\t\t/* Rx Flow control is enabled, and Tx Flow control is\n+\t\t * disabled, by a software over-ride.\n+\t\t *\n+\t\t * Since there really isn't a way to advertise that we are\n+\t\t * capable of Rx Pause ONLY, we will advertise that we\n+\t\t * support both symmetric and asymmetric Rx PAUSE. Later\n+\t\t * (in igc_config_fc_after_link_up) we will disable the\n+\t\t * hw's ability to send PAUSE frames.\n+\t\t */\n+\t\tmii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);\n+\t\tbreak;\n+\tcase igc_fc_tx_pause:\n+\t\t/* Tx Flow control is enabled, and Rx Flow control is\n+\t\t * disabled, by a software over-ride.\n+\t\t */\n+\t\tmii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;\n+\t\tmii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;\n+\t\tbreak;\n+\tcase igc_fc_full:\n+\t\t/* Flow control (both Rx and Tx) is enabled by a software\n+\t\t * over-ride.\n+\t\t */\n+\t\tmii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);\n+\t\tbreak;\n+\tdefault:\n+\t\thw_dbg(\"Flow control param set incorrectly\\n\");\n+\t\treturn -IGC_ERR_CONFIG;\n+\t}\n+\n+\tret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\thw_dbg(\"Auto-Neg Advertising %x\\n\", mii_autoneg_adv_reg);\n+\n+\tif (phy->autoneg_mask & ADVERTISE_1000_FULL)\n+\t\tret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,\n+\t\t\t\t\t mii_1000t_ctrl_reg);\n+\n+\tif ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&\n+\t hw->phy.id == I225_I_PHY_ID)\n+\t\tret_val = phy->ops.write_reg(hw,\n+\t\t\t\t\t (STANDARD_AN_REG_MASK <<\n+\t\t\t\t\t MMD_DEVADDR_SHIFT) |\n+\t\t\t\t\t ANEG_MULTIGBT_AN_CTRL,\n+\t\t\t\t\t aneg_multigbt_an_ctrl);\n+\n+\treturn ret_val;\n+}\n+\n+/**\n+ * igc_setup_copper_link - Configure copper link settings\n+ * @hw: pointer to the HW structure\n+ *\n+ * Calls the appropriate function to configure the link for auto-neg or forced\n+ * speed and duplex. Then we check for link, once link is established calls\n+ * to configure collision distance and flow control are called. If link is\n+ * not established, we return -IGC_ERR_PHY (-2).\n+ */\n+s32 igc_setup_copper_link(struct igc_hw *hw)\n+{\n+\ts32 ret_val = 0;\n+\tbool link;\n+\n+\tif (hw->mac.autoneg) {\n+\t\t/* Setup autoneg and flow control advertisement and perform\n+\t\t * autonegotiation.\n+\t\t */\n+\t\tret_val = igc_copper_link_autoneg(hw);\n+\t\tif (ret_val)\n+\t\t\tgoto out;\n+\t} else {\n+\t\t/* PHY will be set to 10H, 10F, 100H or 100F\n+\t\t * depending on user settings.\n+\t\t */\n+\t\thw_dbg(\"Forcing Speed and Duplex\\n\");\n+\t\tret_val = hw->phy.ops.force_speed_duplex(hw);\n+\t\tif (ret_val) {\n+\t\t\thw_dbg(\"Error Forcing Speed and Duplex\\n\");\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\t/* Check link status. Wait up to 100 microseconds for link to become\n+\t * valid.\n+\t */\n+\tret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);\n+\tif (ret_val)\n+\t\tgoto out;\n+\n+\tif (link) {\n+\t\thw_dbg(\"Valid link established!!!\\n\");\n+\t\tigc_config_collision_dist(hw);\n+\t\tret_val = igc_config_fc_after_link_up(hw);\n+\t} else {\n+\t\thw_dbg(\"Unable to establish link!!!\\n\");\n+\t}\n+\n+out:\n+\treturn ret_val;\n+}\n+\n+/**\n * igc_read_phy_reg_mdic - Read MDI control register\n * @hw: pointer to the HW structure\n * @offset: register offset to be read\ndiff --git a/drivers/net/ethernet/intel/igc/igc_phy.h b/drivers/net/ethernet/intel/igc/igc_phy.h\nindex 6a62f381559d..25cba33de7e2 100644\n--- a/drivers/net/ethernet/intel/igc/igc_phy.h\n+++ b/drivers/net/ethernet/intel/igc/igc_phy.h\n@@ -12,6 +12,7 @@ s32 igc_get_phy_id(struct igc_hw *hw);\n s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations,\n \t\t u32 usec_interval, bool *success);\n s32 igc_check_downshift(struct igc_hw *hw);\n+s32 igc_setup_copper_link(struct igc_hw *hw);\n void igc_power_up_phy_copper(struct igc_hw *hw);\n void igc_power_down_phy_copper(struct igc_hw *hw);\n s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);\n", "prefixes": [ "v8", "10/11" ] }