Received: by 10.223.185.116 with SMTP id b49csp3267920wrg; Mon, 5 Mar 2018 17:57:44 -0800 (PST) X-Google-Smtp-Source: AG47ELv68A+E2wesTv5z25Jp0FcUQs2eLTDkA6GNbZO27AKS6yP9yTVxv6+USacf9Sk7UZHfiAm0 X-Received: by 10.167.129.195 with SMTP id c3mr17185264pfn.14.1520301463949; Mon, 05 Mar 2018 17:57:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520301463; cv=none; d=google.com; s=arc-20160816; b=C+LLLjFnWWb8HJfMzamqwDjNpC4MVhioWswideEkvI8UeI2P/2aTktYwrJOy6vYbtm 6DDl6X4XRl1FoePMPAh1GN6LXbXxP/JWce3Xm+ARiaWZqvLb9kDOh+pWlk8WfQy7N+Of tbVd2n8iAna9274n1fHJtecvKdILWimxQoaTnlvuoRQEHHrU06NMBCOEF4nuwLKE7lW9 IJ7GLYdDf2fxxpgDJLtKxJnTpQuO1wwSyKvJTdFTGQ9++ZQz/rdJoo3vScHR29VJ0uyy hXxFol/sIShGnofMffeNryAggVm2OGonGFfOX6uFTRHCmv1xpb9aGEz+T14jqOnddEup FKSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=Hi2jNuW1UVGpdTXYtcLr9tpQA8rWqly+tudhKPVM4aU=; b=y22+ahbcuSIT3vyGzkguu/tjTBtsVA1C94ag8U2/vls9LS0/g/EqJJ4J62cEApne6r ke2E4/zqzE2PdoKFK6znRJQsZZpnhDQjUpbjJjyb59znNcOPKAh5V9ttmxMl2GwcuSKC mu2ycNUZIYU8//4L/aWPIFFbE1quz+jYqmWGsiKk8crD7I3WY2B8oLvLcdST9lIo1tP2 5AnuODKnu+dvfWP5r7oviabf1PRFX+hg+wzXAybkTQP2luY8VRCyH1HjT1aWb6d8e6Yi 5fwh5mcsbkNZBdp/uimI9euSxfFcEfv9pW4OyyWnpO3HSl6t7QjRFvDSyDLf5toBI+ss 4uWw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e92-v6si10264852plb.82.2018.03.05.17.57.30; Mon, 05 Mar 2018 17:57:43 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932500AbeCFB42 (ORCPT + 99 others); Mon, 5 Mar 2018 20:56:28 -0500 Received: from mx2.suse.de ([195.135.220.15]:58107 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932406AbeCFB4Z (ORCPT ); Mon, 5 Mar 2018 20:56:25 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 0EBEFAF80; Tue, 6 Mar 2018 01:56:24 +0000 (UTC) From: Benjamin Poirier To: Jeff Kirsher Cc: Alexander Duyck , Lennart Sorensen , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] e1000e: Fix link check race condition Date: Tue, 6 Mar 2018 10:55:53 +0900 Message-Id: <20180306015553.10441-2-bpoirier@suse.com> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180306015553.10441-1-bpoirier@suse.com> References: <20180306015553.10441-1-bpoirier@suse.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Alex reported the following race condition: /* link goes up... interrupt... schedule watchdog */ \ e1000_watchdog_task \ e1000e_has_link \ hw->mac.ops.check_for_link() === e1000e_check_for_copper_link \ e1000e_phy_has_link_generic(..., &link) link = true /* link goes down... interrupt */ \ e1000_msix_other hw->mac.get_link_status = true /* link is up */ mac->get_link_status = false link_active = true /* link_active is true, wrongly, and stays so because * get_link_status is false */ Avoid this problem by making sure that we don't set get_link_status = false after having checked the link. It seems this problem has been present since the introduction of e1000e. Link: https://lkml.org/lkml/2018/1/29/338 Reported-by: Alexander Duyck Signed-off-by: Benjamin Poirier --- drivers/net/ethernet/intel/e1000e/ich8lan.c | 31 ++++++++++++++++------------- drivers/net/ethernet/intel/e1000e/mac.c | 14 ++++++------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index d6d4ed7acf03..1dddfb7b2de6 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1383,6 +1383,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ if (!mac->get_link_status) return 0; + mac->get_link_status = false; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -1390,12 +1391,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) - return ret_val; + goto out; if (hw->mac.type == e1000_pchlan) { ret_val = e1000_k1_gig_workaround_hv(hw, link); if (ret_val) - return ret_val; + goto out; } /* When connected at 10Mbps half-duplex, some parts are excessively @@ -1428,7 +1429,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; if (hw->mac.type == e1000_pch2lan) emi_addr = I82579_RX_CONFIG; @@ -1450,7 +1451,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; if (hw->mac.type >= e1000_pch_spt) { u16 data; @@ -1459,14 +1460,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (speed == SPEED_1000) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; ret_val = e1e_rphy_locked(hw, PHY_REG(776, 20), &data); if (ret_val) { hw->phy.ops.release(hw); - return ret_val; + goto out; } ptr_gap = (data & (0x3FF << 2)) >> 2; @@ -1480,18 +1481,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) } hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; } else { ret_val = hw->phy.ops.acquire(hw); if (ret_val) - return ret_val; + goto out; ret_val = e1e_wphy_locked(hw, PHY_REG(776, 20), 0xC023); hw->phy.ops.release(hw); if (ret_val) - return ret_val; + goto out; } } @@ -1518,7 +1519,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) { ret_val = e1000_k1_workaround_lpt_lp(hw, link); if (ret_val) - return ret_val; + goto out; } if (hw->mac.type >= e1000_pch_lpt) { /* Set platform power management values for @@ -1526,7 +1527,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ ret_val = e1000_platform_pm_pch_lpt(hw, link); if (ret_val) - return ret_val; + goto out; } /* Clear link partner's EEE ability */ @@ -1549,9 +1550,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) } if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; + goto out; switch (hw->mac.type) { case e1000_pch2lan: @@ -1617,6 +1616,10 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) e_dbg("Error configuring flow control\n"); return ret_val; + +out: + mac->get_link_status = true; + return ret_val; } static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index b322011ec282..5bdc3a2d4fd7 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -424,19 +424,15 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) */ if (!mac->get_link_status) return 0; + mac->get_link_status = false; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; + if (ret_val || !link) + goto out; /* Check if there was DownShift, must be checked * immediately after link-up @@ -465,6 +461,10 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) e_dbg("Error configuring flow control\n"); return ret_val; + +out: + mac->get_link_status = true; + return ret_val; } /** -- 2.16.2