mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-17 20:54:10 +00:00
net: hns3: Add timeout process in hns3_enet
This patch add timeout handler in hns3_enet.c to handle TX side timeout event, when TX timeout event occur, it will triger NIC driver into reset process. Signed-off-by: qumingguang <qumingguang@huawei.com> Signed-off-by: Lipeng <lipeng321@huawei.com> Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4ed340ab8f
commit
f8fa222ca5
2 changed files with 88 additions and 0 deletions
|
@ -258,6 +258,7 @@ out_start_err:
|
||||||
|
|
||||||
static int hns3_nic_net_open(struct net_device *netdev)
|
static int hns3_nic_net_open(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
|
@ -273,6 +274,7 @@ static int hns3_nic_net_open(struct net_device *netdev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->last_reset_time = jiffies;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1322,10 +1324,91 @@ static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
|
||||||
|
{
|
||||||
|
struct hns3_nic_priv *priv = netdev_priv(ndev);
|
||||||
|
struct hns3_enet_ring *tx_ring = NULL;
|
||||||
|
int timeout_queue = 0;
|
||||||
|
int hw_head, hw_tail;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Find the stopped queue the same way the stack does */
|
||||||
|
for (i = 0; i < ndev->real_num_tx_queues; i++) {
|
||||||
|
struct netdev_queue *q;
|
||||||
|
unsigned long trans_start;
|
||||||
|
|
||||||
|
q = netdev_get_tx_queue(ndev, i);
|
||||||
|
trans_start = q->trans_start;
|
||||||
|
if (netif_xmit_stopped(q) &&
|
||||||
|
time_after(jiffies,
|
||||||
|
(trans_start + ndev->watchdog_timeo))) {
|
||||||
|
timeout_queue = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ndev->num_tx_queues) {
|
||||||
|
netdev_info(ndev,
|
||||||
|
"no netdev TX timeout queue found, timeout count: %llu\n",
|
||||||
|
priv->tx_timeout_count);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_ring = priv->ring_data[timeout_queue].ring;
|
||||||
|
|
||||||
|
hw_head = readl_relaxed(tx_ring->tqp->io_base +
|
||||||
|
HNS3_RING_TX_RING_HEAD_REG);
|
||||||
|
hw_tail = readl_relaxed(tx_ring->tqp->io_base +
|
||||||
|
HNS3_RING_TX_RING_TAIL_REG);
|
||||||
|
netdev_info(ndev,
|
||||||
|
"tx_timeout count: %llu, queue id: %d, SW_NTU: 0x%x, SW_NTC: 0x%x, HW_HEAD: 0x%x, HW_TAIL: 0x%x, INT: 0x%x\n",
|
||||||
|
priv->tx_timeout_count,
|
||||||
|
timeout_queue,
|
||||||
|
tx_ring->next_to_use,
|
||||||
|
tx_ring->next_to_clean,
|
||||||
|
hw_head,
|
||||||
|
hw_tail,
|
||||||
|
readl(tx_ring->tqp_vector->mask_addr));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hns3_nic_net_timeout(struct net_device *ndev)
|
||||||
|
{
|
||||||
|
struct hns3_nic_priv *priv = netdev_priv(ndev);
|
||||||
|
unsigned long last_reset_time = priv->last_reset_time;
|
||||||
|
struct hnae3_handle *h = priv->ae_handle;
|
||||||
|
|
||||||
|
if (!hns3_get_tx_timeo_queue_info(ndev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->tx_timeout_count++;
|
||||||
|
|
||||||
|
/* This timeout is far away enough from last timeout,
|
||||||
|
* if timeout again,set the reset type to PF reset
|
||||||
|
*/
|
||||||
|
if (time_after(jiffies, (last_reset_time + 20 * HZ)))
|
||||||
|
priv->reset_level = HNAE3_FUNC_RESET;
|
||||||
|
|
||||||
|
/* Don't do any new action before the next timeout */
|
||||||
|
else if (time_before(jiffies, (last_reset_time + ndev->watchdog_timeo)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->last_reset_time = jiffies;
|
||||||
|
|
||||||
|
if (h->ae_algo->ops->reset_event)
|
||||||
|
h->ae_algo->ops->reset_event(h, priv->reset_level);
|
||||||
|
|
||||||
|
priv->reset_level++;
|
||||||
|
if (priv->reset_level > HNAE3_GLOBAL_RESET)
|
||||||
|
priv->reset_level = HNAE3_GLOBAL_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct net_device_ops hns3_nic_netdev_ops = {
|
static const struct net_device_ops hns3_nic_netdev_ops = {
|
||||||
.ndo_open = hns3_nic_net_open,
|
.ndo_open = hns3_nic_net_open,
|
||||||
.ndo_stop = hns3_nic_net_stop,
|
.ndo_stop = hns3_nic_net_stop,
|
||||||
.ndo_start_xmit = hns3_nic_net_xmit,
|
.ndo_start_xmit = hns3_nic_net_xmit,
|
||||||
|
.ndo_tx_timeout = hns3_nic_net_timeout,
|
||||||
.ndo_set_mac_address = hns3_nic_net_set_mac_address,
|
.ndo_set_mac_address = hns3_nic_net_set_mac_address,
|
||||||
.ndo_change_mtu = hns3_nic_change_mtu,
|
.ndo_change_mtu = hns3_nic_change_mtu,
|
||||||
.ndo_set_features = hns3_nic_set_features,
|
.ndo_set_features = hns3_nic_set_features,
|
||||||
|
@ -2763,6 +2846,9 @@ static int hns3_client_init(struct hnae3_handle *handle)
|
||||||
priv->dev = &pdev->dev;
|
priv->dev = &pdev->dev;
|
||||||
priv->netdev = netdev;
|
priv->netdev = netdev;
|
||||||
priv->ae_handle = handle;
|
priv->ae_handle = handle;
|
||||||
|
priv->last_reset_time = jiffies;
|
||||||
|
priv->reset_level = HNAE3_FUNC_RESET;
|
||||||
|
priv->tx_timeout_count = 0;
|
||||||
|
|
||||||
handle->kinfo.netdev = netdev;
|
handle->kinfo.netdev = netdev;
|
||||||
handle->priv = (void *)priv;
|
handle->priv = (void *)priv;
|
||||||
|
|
|
@ -518,6 +518,8 @@ struct hns3_nic_priv {
|
||||||
/* The most recently read link state */
|
/* The most recently read link state */
|
||||||
int link;
|
int link;
|
||||||
u64 tx_timeout_count;
|
u64 tx_timeout_count;
|
||||||
|
enum hnae3_reset_type reset_level;
|
||||||
|
unsigned long last_reset_time;
|
||||||
|
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue