get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 945576,
    "url": "http://patchwork.ozlabs.org/api/patches/945576/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20180718081812.15912-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": "<20180718081812.15912-1-sasha.neftin@intel.com>",
    "list_archive_url": null,
    "date": "2018-07-18T08:18:12",
    "name": "[v4,10/11] igc: Add setup link functionality",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "8ebb28c615c15e6b067e1cc2f2e95c4de8af1083",
    "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/20180718081812.15912-1-sasha.neftin@intel.com/mbox/",
    "series": [
        {
            "id": 56158,
            "url": "http://patchwork.ozlabs.org/api/series/56158/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=56158",
            "date": "2018-07-18T08:17:45",
            "name": "[v4,01/11] igc: Add skeletal frame for Intel(R) 2.5G Ethernet Controller support.",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/56158/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/945576/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/945576/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.136; helo=silver.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 silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\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 41Vqm95NtQz9rxx\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 18 Jul 2018 18:18:33 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 497112078D;\n\tWed, 18 Jul 2018 08:18:32 +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 Zj6UOqwWuoPh; Wed, 18 Jul 2018 08:18:25 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id B9DC630797;\n\tWed, 18 Jul 2018 08:18:25 +0000 (UTC)",
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id A67121C094F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 18 Jul 2018 08:18:24 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id A2E6388C23\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 18 Jul 2018 08:18:24 +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 y0jI2BenjYHs for <intel-wired-lan@lists.osuosl.org>;\n\tWed, 18 Jul 2018 08:18:22 +0000 (UTC)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby fraxinus.osuosl.org (Postfix) with ESMTPS id 910A188756\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tWed, 18 Jul 2018 08:18:22 +0000 (UTC)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t18 Jul 2018 01:18:21 -0700",
            "from ccdlinuxdev06.iil.intel.com ([143.185.162.2])\n\tby orsmga002.jf.intel.com with ESMTP; 18 Jul 2018 01:18:13 -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.51,369,1526367600\"; d=\"scan'208\";a=\"75732716\"",
        "From": "Sasha Neftin <sasha.neftin@intel.com>",
        "To": "sasha.neftin@intel.com,\n\tintel-wired-lan@lists.osuosl.org",
        "Date": "Wed, 18 Jul 2018 11:18:12 +0300",
        "Message-Id": "<20180718081812.15912-1-sasha.neftin@intel.com>",
        "X-Mailer": "git-send-email 2.11.0",
        "Subject": "[Intel-wired-lan] [PATCH v4 10/11] igc: Add setup link functionality",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.24",
        "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\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    |  41 ++++\n drivers/net/ethernet/intel/igc/igc_defines.h |  38 +++\n drivers/net/ethernet/intel/igc/igc_mac.c     | 272 +++++++++++++++++++++-\n drivers/net/ethernet/intel/igc/igc_mac.h     |   2 +\n drivers/net/ethernet/intel/igc/igc_main.c    |  33 +++\n drivers/net/ethernet/intel/igc/igc_phy.c     | 332 ++++++++++++++++++++++++++-\n drivers/net/ethernet/intel/igc/igc_phy.h     |   2 +\n 8 files changed, 719 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h\nindex 901048fdf478..c9e83da145df 100644\n--- a/drivers/net/ethernet/intel/igc/igc.h\n+++ b/drivers/net/ethernet/intel/igc/igc.h\n@@ -320,6 +320,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 7215f303278e..4831916f7fc2 100644\n--- a/drivers/net/ethernet/intel/igc/igc_base.c\n+++ b/drivers/net/ethernet/intel/igc/igc_base.c\n@@ -17,6 +17,7 @@ static void igc_release_phy_base(struct igc_hw *);\n static s32 igc_get_phy_id_base(struct igc_hw *);\n static s32 igc_init_hw_base(struct igc_hw *);\n static s32 igc_reset_hw_base(struct igc_hw *);\n+static s32 igc_setup_copper_link_base(struct igc_hw *);\n static s32 igc_set_pcie_completion_timeout(struct igc_hw *hw);\n static s32 igc_read_mac_addr_base(struct igc_hw *hw);\n \n@@ -97,6 +98,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@@ -139,6 +143,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@@ -155,10 +161,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 \n@@ -289,6 +307,29 @@ static s32 igc_init_hw_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_read_mac_addr_base - Read device MAC address\n  *  @hw: pointer to the HW structure\n  **/\ndiff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h\nindex 6b0c5058d897..f05b9e244df1 100644\n--- a/drivers/net/ethernet/intel/igc/igc_defines.h\n+++ b/drivers/net/ethernet/intel/igc/igc_defines.h\n@@ -20,6 +20,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@@ -61,6 +66,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@@ -73,6 +84,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 #define IGC_EECD_REQ\t\t0x00000040 /* NVM Access Request */\n #define IGC_EECD_GNT\t\t0x00000080 /* NVM Access Grant */\n@@ -358,6 +392,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 78941e2a26f0..d6c97b66805f 100644\n--- a/drivers/net/ethernet/intel/igc/igc_mac.c\n+++ b/drivers/net/ethernet/intel/igc/igc_mac.c\n@@ -141,6 +141,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@@ -192,10 +194,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@@ -422,7 +488,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-\t/* TODO ret_val = igc_config_fc_after_link_up(hw); */\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@@ -452,6 +518,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 e61b9c5faa32..d60959f98ebc 100644\n--- a/drivers/net/ethernet/intel/igc/igc_mac.h\n+++ b/drivers/net/ethernet/intel/igc/igc_mac.h\n@@ -14,6 +14,8 @@\n \n /* forward declaration */\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 s32  igc_disable_pcie_master(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);\ndiff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c\nindex 24689854a0a2..e5bd2c5cf02a 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -3429,6 +3429,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@@ -3437,6 +3456,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 = 0x2f;\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@@ -3464,6 +3491,12 @@ 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+\n+\tif (hw->flash_address)\n+\t\tiounmap(hw->flash_address);\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 95c9a30b96a2..9cb55526caac 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@@ -207,7 +211,333 @@ s32 igc_phy_hw_reset(struct igc_hw *hw)\n \n \tphy->ops.release(hw);\n \n-\tret_val = phy->ops.get_cfg_done(hw);\n+out:\n+\treturn ret_val;\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}\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;\ndiff --git a/drivers/net/ethernet/intel/igc/igc_phy.h b/drivers/net/ethernet/intel/igc/igc_phy.h\nindex deac52297052..8fc8873f0b2e 100644\n--- a/drivers/net/ethernet/intel/igc/igc_phy.h\n+++ b/drivers/net/ethernet/intel/igc/igc_phy.h\n@@ -12,8 +12,10 @@ 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+\n s32  igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);\n s32  igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data);\n \n",
    "prefixes": [
        "v4",
        "10/11"
    ]
}