Commit f995b2ef authored by Yunsheng Lin's avatar Yunsheng Lin Committed by Greg Kroah-Hartman

net: hns3: Fix for loopback selftest failed problem

[ Upstream commit 0f29fc23 ]

Tqp and mac need to be enabled when doing loopback selftest,
ae_algo->ops->start/stop is used to do the job, there is a
time window between ae_algo->ops->start/stop and loopback setup,
which will cause selftest failed problem when there is frame
coming in during that time window.

This patch fixes it by enabling the tqp and mac during loopback
setup process.

Fixes: c39c4d98 ("net: hns3: Add mac loopback selftest support in hns3 driver")
Signed-off-by: default avatarYunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent d01caf35
...@@ -100,41 +100,26 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode) ...@@ -100,41 +100,26 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode)
struct hnae3_handle *h = hns3_get_handle(ndev); struct hnae3_handle *h = hns3_get_handle(ndev);
int ret; int ret;
if (!h->ae_algo->ops->start)
return -EOPNOTSUPP;
ret = hns3_nic_reset_all_ring(h); ret = hns3_nic_reset_all_ring(h);
if (ret) if (ret)
return ret; return ret;
ret = h->ae_algo->ops->start(h);
if (ret) {
netdev_err(ndev,
"hns3_lb_up ae start return error: %d\n", ret);
return ret;
}
ret = hns3_lp_setup(ndev, loop_mode, true); ret = hns3_lp_setup(ndev, loop_mode, true);
usleep_range(10000, 20000); usleep_range(10000, 20000);
return ret; return 0;
} }
static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode) static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode)
{ {
struct hnae3_handle *h = hns3_get_handle(ndev);
int ret; int ret;
if (!h->ae_algo->ops->stop)
return -EOPNOTSUPP;
ret = hns3_lp_setup(ndev, loop_mode, false); ret = hns3_lp_setup(ndev, loop_mode, false);
if (ret) { if (ret) {
netdev_err(ndev, "lb_setup return error: %d\n", ret); netdev_err(ndev, "lb_setup return error: %d\n", ret);
return ret; return ret;
} }
h->ae_algo->ops->stop(h);
usleep_range(10000, 20000); usleep_range(10000, 20000);
return 0; return 0;
......
...@@ -3666,6 +3666,8 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en) ...@@ -3666,6 +3666,8 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en)
/* 2 Then setup the loopback flag */ /* 2 Then setup the loopback flag */
loop_en = le32_to_cpu(req->txrx_pad_fcs_loop_en); loop_en = le32_to_cpu(req->txrx_pad_fcs_loop_en);
hnae3_set_bit(loop_en, HCLGE_MAC_APP_LP_B, en ? 1 : 0); hnae3_set_bit(loop_en, HCLGE_MAC_APP_LP_B, en ? 1 : 0);
hnae3_set_bit(loop_en, HCLGE_MAC_TX_EN_B, en ? 1 : 0);
hnae3_set_bit(loop_en, HCLGE_MAC_RX_EN_B, en ? 1 : 0);
req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en); req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
...@@ -3726,15 +3728,36 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en) ...@@ -3726,15 +3728,36 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en)
return -EIO; return -EIO;
} }
hclge_cfg_mac_mode(hdev, en);
return 0; return 0;
} }
static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id,
int stream_id, bool enable)
{
struct hclge_desc desc;
struct hclge_cfg_com_tqp_queue_cmd *req =
(struct hclge_cfg_com_tqp_queue_cmd *)desc.data;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
req->tqp_id = cpu_to_le16(tqp_id & HCLGE_RING_ID_MASK);
req->stream_id = cpu_to_le16(stream_id);
req->enable |= enable << HCLGE_TQP_ENABLE_B;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"Tqp enable fail, status =%d.\n", ret);
return ret;
}
static int hclge_set_loopback(struct hnae3_handle *handle, static int hclge_set_loopback(struct hnae3_handle *handle,
enum hnae3_loop loop_mode, bool en) enum hnae3_loop loop_mode, bool en)
{ {
struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back; struct hclge_dev *hdev = vport->back;
int ret; int i, ret;
switch (loop_mode) { switch (loop_mode) {
case HNAE3_MAC_INTER_LOOP_MAC: case HNAE3_MAC_INTER_LOOP_MAC:
...@@ -3750,27 +3773,13 @@ static int hclge_set_loopback(struct hnae3_handle *handle, ...@@ -3750,27 +3773,13 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
break; break;
} }
return ret; for (i = 0; i < vport->alloc_tqps; i++) {
} ret = hclge_tqp_enable(hdev, i, 0, en);
if (ret)
static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id, return ret;
int stream_id, bool enable) }
{
struct hclge_desc desc;
struct hclge_cfg_com_tqp_queue_cmd *req =
(struct hclge_cfg_com_tqp_queue_cmd *)desc.data;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
req->tqp_id = cpu_to_le16(tqp_id & HCLGE_RING_ID_MASK);
req->stream_id = cpu_to_le16(stream_id);
req->enable |= enable << HCLGE_TQP_ENABLE_B;
ret = hclge_cmd_send(&hdev->hw, &desc, 1); return 0;
if (ret)
dev_err(&hdev->pdev->dev,
"Tqp enable fail, status =%d.\n", ret);
return ret;
} }
static void hclge_reset_tqp_stats(struct hnae3_handle *handle) static void hclge_reset_tqp_stats(struct hnae3_handle *handle)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment