]>
Commit | Line | Data |
---|---|---|
5aef4b01 SL |
1 | From c35d518b4e266d1b7305459759e52390636021bd Mon Sep 17 00:00:00 2001 |
2 | From: Yonglong Liu <liuyonglong@huawei.com> | |
3 | Date: Sat, 15 Dec 2018 11:53:26 +0800 | |
4 | Subject: net: hns: Avoid net reset caused by pause frames storm | |
5 | ||
6 | [ Upstream commit a57275d35576fdd89d8c771eedf1e7cf97e0dfa6 ] | |
7 | ||
8 | There will be a large number of MAC pause frames on the net, | |
9 | which caused tx timeout of net device. And then the net device | |
10 | was reset to try to recover it. So that is not useful, and will | |
11 | cause some other problems. | |
12 | ||
13 | So need doubled ndev->watchdog_timeo if device watchdog occurred | |
14 | until watchdog_timeo up to 40s and then try resetting to recover | |
15 | it. | |
16 | ||
17 | When collecting dfx information such as hardware registers when tx timeout. | |
18 | Some registers for count were cleared when read. So need move this task | |
19 | before update net state which also read the count registers. | |
20 | ||
21 | Signed-off-by: Yonglong Liu <liuyonglong@huawei.com> | |
22 | Signed-off-by: Peng Li <lipeng321@huawei.com> | |
23 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
24 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
25 | --- | |
26 | drivers/net/ethernet/hisilicon/hns/hns_enet.c | 12 ++++++++++-- | |
27 | 1 file changed, 10 insertions(+), 2 deletions(-) | |
28 | ||
29 | diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c | |
30 | index bcd9aaba09b3..f28a639e8393 100644 | |
31 | --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c | |
32 | +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c | |
33 | @@ -1609,11 +1609,19 @@ static int hns_nic_net_stop(struct net_device *ndev) | |
34 | } | |
35 | ||
36 | static void hns_tx_timeout_reset(struct hns_nic_priv *priv); | |
37 | +#define HNS_TX_TIMEO_LIMIT (40 * HZ) | |
38 | static void hns_nic_net_timeout(struct net_device *ndev) | |
39 | { | |
40 | struct hns_nic_priv *priv = netdev_priv(ndev); | |
41 | ||
42 | - hns_tx_timeout_reset(priv); | |
43 | + if (ndev->watchdog_timeo < HNS_TX_TIMEO_LIMIT) { | |
44 | + ndev->watchdog_timeo *= 2; | |
45 | + netdev_info(ndev, "watchdog_timo changed to %d.\n", | |
46 | + ndev->watchdog_timeo); | |
47 | + } else { | |
48 | + ndev->watchdog_timeo = HNS_NIC_TX_TIMEOUT; | |
49 | + hns_tx_timeout_reset(priv); | |
50 | + } | |
51 | } | |
52 | ||
53 | static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr, | |
54 | @@ -2193,11 +2201,11 @@ static void hns_nic_service_task(struct work_struct *work) | |
55 | = container_of(work, struct hns_nic_priv, service_task); | |
56 | struct hnae_handle *h = priv->ae_handle; | |
57 | ||
58 | + hns_nic_reset_subtask(priv); | |
59 | hns_nic_update_link_status(priv->netdev); | |
60 | h->dev->ops->update_led_status(h); | |
61 | hns_nic_update_stats(priv->netdev); | |
62 | ||
63 | - hns_nic_reset_subtask(priv); | |
64 | hns_nic_service_event_complete(priv); | |
65 | } | |
66 | ||
67 | -- | |
68 | 2.19.1 | |
69 |