Skip to content

Commit

Permalink
r8169: disable ASPM in case of tx timeout
Browse files Browse the repository at this point in the history
There are still single reports of systems where ASPM incompatibilities
cause tx timeouts. It's not clear whom to blame, so let's disable
ASPM in case of a tx timeout.

v2:
- add one-time warning for informing the user

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/92369a92-dc32-4529-0509-11459ba0e391@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Heiner Kallweit authored and Jakub Kicinski committed Jan 12, 2023
1 parent 62cd667 commit 80c0576
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion drivers/net/ethernet/realtek/r8169_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ struct rtl8169_tc_offsets {
enum rtl_flag {
RTL_FLAG_TASK_ENABLED = 0,
RTL_FLAG_TASK_RESET_PENDING,
RTL_FLAG_TASK_TX_TIMEOUT,
RTL_FLAG_MAX
};

Expand Down Expand Up @@ -3931,7 +3932,7 @@ static void rtl8169_tx_timeout(struct net_device *dev, unsigned int txqueue)
{
struct rtl8169_private *tp = netdev_priv(dev);

rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
rtl_schedule_task(tp, RTL_FLAG_TASK_TX_TIMEOUT);
}

static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len,
Expand Down Expand Up @@ -4525,14 +4526,25 @@ static void rtl_task(struct work_struct *work)
{
struct rtl8169_private *tp =
container_of(work, struct rtl8169_private, wk.work);
int ret;

rtnl_lock();

if (!netif_running(tp->dev) ||
!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
goto out_unlock;

if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
/* ASPM compatibility issues are a typical reason for tx timeouts */
ret = pci_disable_link_state(tp->pci_dev, PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_L0S);
if (!ret)
netdev_warn_once(tp->dev, "ASPM disabled on Tx timeout\n");
goto reset;
}

if (test_and_clear_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags)) {
reset:
rtl_reset_work(tp);
netif_wake_queue(tp->dev);
}
Expand Down

0 comments on commit 80c0576

Please sign in to comment.