Received: by 10.223.185.116 with SMTP id b49csp3270102wrg; Sun, 25 Feb 2018 18:32:42 -0800 (PST) X-Google-Smtp-Source: AH8x224F7Yde6hToipjF7WGk3juIZbVOJ1ucq6p4FZSXYJRuOaU1jCSXeadYpcKoXxvinKSszuU4 X-Received: by 2002:a17:902:5a5:: with SMTP id f34-v6mr9273687plf.134.1519612362111; Sun, 25 Feb 2018 18:32:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519612362; cv=none; d=google.com; s=arc-20160816; b=zeGVe/vK84ejEUyy5Aq8M9rR0HbsFNQbIyPclZk+FgowtAV09TqGaM+YwPHQzQa3u9 7GV6n5+LYd+bHfAEgSJY1VUdVjEu6O+6wWNV6z3LnZxJXbZv4+SffLiNZxYFAmG3nxv0 aCyno9Ni64QTY/bIDhhNNrpGI1Q1fhqoOVE7Dihvotd2YfwVuXzv7OH2HUvbfT0mqM5J sNnp26RZ21V9jKHLmj2pRcNs5IFcbJv0pwF8ytQWc9+kD/Dg88K9Bvgy1iXP+yz+4M2r 3ZfOxfQfq0h1bGZ79HLPkj94HROsF+0e34kAC5EufQTIkpflx4SliiQWIIeeSkqzmN5f nTvg== 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=ePol7v1Ni2CCtM9As/GenqYghuTqWEe0VSURmYNp5Kg=; b=a4G1gQEIL+dufGsrauopetw0UNelEcXKT/i8/NrpHHIin9mnC6qMOrvVWIycHrsLTH Fs6YkAhAJdQ+6uonzlEuueTIJkQa/isRjXuTz3Mvcor2kgascj2TifxhW95XoMq4SyLP IYtx2IY8vkcNQsdc/lwbfUQ6LH3PszhWOS84BaJw/hcFbhXwPUlLpVw76eooPoY/Mzgi MIpOuzaJQmRO4qv6N0h5f2aJcuWghb1k8pGlwta9Ry+re/Yu9r46wa/rnp80NFbKshL6 cLG8N+dKoXNUv7THrzJiN1QR10537swVGBMEbKkKBdw5aqABfXQW30fBlTAHW5ioS9NP aimA== 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 bf3-v6si2120530plb.477.2018.02.25.18.32.27; Sun, 25 Feb 2018 18:32:42 -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 S1752048AbeBZCbs (ORCPT + 99 others); Sun, 25 Feb 2018 21:31:48 -0500 Received: from mx2.suse.de ([195.135.220.15]:57142 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751931AbeBZCbo (ORCPT ); Sun, 25 Feb 2018 21:31:44 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id A4327AB9F; Mon, 26 Feb 2018 02:31:42 +0000 (UTC) From: Benjamin Poirier To: Jeff Kirsher Cc: Alexander Duyck , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH] e1000e: Fix link check race condition. Date: Mon, 26 Feb 2018 11:31:18 +0900 Message-Id: <20180226023118.17439-1-bpoirier@suse.com> X-Mailer: git-send-email 2.16.1 In-Reply-To: References: 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 | 41 ++++++++++++++++------------- drivers/net/ethernet/intel/e1000e/mac.c | 14 +++++++--- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index ff308b05d68c..3c2c4f87e075 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1386,6 +1386,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) */ if (!mac->get_link_status) return 1; + 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 @@ -1393,12 +1394,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 @@ -1431,7 +1432,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; @@ -1453,7 +1454,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; @@ -1462,14 +1463,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; @@ -1483,18 +1484,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; } } @@ -1521,7 +1522,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 @@ -1529,7 +1530,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 */ @@ -1551,22 +1552,22 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ew32(FEXTNVM6, fextnvm6); } - if (!link) + if (!link) { + mac->get_link_status = true; return 0; /* No link detected */ - - mac->get_link_status = false; + } switch (hw->mac.type) { case e1000_pch2lan: ret_val = e1000_k1_workaround_lv(hw); if (ret_val) - return ret_val; + goto out; /* fall-thru */ case e1000_pchlan: if (hw->phy.type == e1000_phy_82578) { ret_val = e1000_link_stall_workaround_hv(hw); if (ret_val) - return ret_val; + goto out; } /* Workaround for PCHx parts in half-duplex: @@ -1595,7 +1596,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (hw->phy.type > e1000_phy_82579) { ret_val = e1000_set_eee_pchlan(hw); if (ret_val) - return ret_val; + goto out; } /* If we are forcing speed/duplex, then we simply return since @@ -1618,10 +1619,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val) { e_dbg("Error configuring flow control\n"); - return ret_val; + goto out; } return 1; + +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 db735644b312..60c8beaf5cb3 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -427,6 +427,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) */ if (!mac->get_link_status) return 1; + 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 @@ -434,12 +435,13 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) */ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) - return ret_val; + goto out; - if (!link) + if (!link) { + mac->get_link_status = true; return 0; /* No link detected */ + } - mac->get_link_status = false; /* Check if there was DownShift, must be checked * immediately after link-up @@ -466,10 +468,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) ret_val = e1000e_config_fc_after_link_up(hw); if (ret_val) { e_dbg("Error configuring flow control\n"); - return ret_val; + goto out; } return 1; + +out: + mac->get_link_status = true; + return ret_val; } /** -- 2.16.1