| From 165ae7a8feb53dc47fb041357e4b253bfc927cf9 Mon Sep 17 00:00:00 2001 |
| From: Kai-Heng Feng <kai.heng.feng@canonical.com> |
| Date: Tue, 5 May 2020 12:01:54 +0800 |
| Subject: igb: Report speed and duplex as unknown when device is runtime suspended |
| |
| From: Kai-Heng Feng <kai.heng.feng@canonical.com> |
| |
| commit 165ae7a8feb53dc47fb041357e4b253bfc927cf9 upstream. |
| |
| igb device gets runtime suspended when there's no link partner. We can't |
| get correct speed under that state: |
| $ cat /sys/class/net/enp3s0/speed |
| 1000 |
| |
| In addition to that, an error can also be spotted in dmesg: |
| [ 385.991957] igb 0000:03:00.0 enp3s0: PCIe link lost |
| |
| Since device can only be runtime suspended when there's no link partner, |
| we can skip reading register and let the following logic set speed and |
| duplex with correct status. |
| |
| The more generic approach will be wrap get_link_ksettings() with begin() |
| and complete() callbacks. However, for this particular issue, begin() |
| calls igb_runtime_resume() , which tries to rtnl_lock() while the lock |
| is already hold by upper ethtool layer. |
| |
| So let's take this approach until the igb_runtime_resume() no longer |
| needs to hold rtnl_lock. |
| |
| CC: stable <stable@vger.kernel.org> |
| Suggested-by: Alexander Duyck <alexander.duyck@gmail.com> |
| Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> |
| Tested-by: Aaron Brown <aaron.f.brown@intel.com> |
| Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/ethernet/intel/igb/igb_ethtool.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c |
| +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c |
| @@ -153,7 +153,8 @@ static int igb_get_settings(struct net_d |
| u32 status; |
| u32 speed; |
| |
| - status = rd32(E1000_STATUS); |
| + status = pm_runtime_suspended(&adapter->pdev->dev) ? |
| + 0 : rd32(E1000_STATUS); |
| if (hw->phy.media_type == e1000_media_type_copper) { |
| |
| ecmd->supported = (SUPPORTED_10baseT_Half | |