Commit 3ff50490 authored by Huazhong Tan's avatar Huazhong Tan Committed by David S. Miller

net: hns3: fix a dead loop in hclge_cmd_csq_clean

If head has invlid value then a dead loop can be triggered in
hclge_cmd_csq_clean. This patch adds sanity check for this case.

Fixes: 68c0a5c7 ("net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd
Interface Support")
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@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>
parent 0c963e8c
...@@ -31,6 +31,17 @@ static int hclge_ring_space(struct hclge_cmq_ring *ring) ...@@ -31,6 +31,17 @@ static int hclge_ring_space(struct hclge_cmq_ring *ring)
return ring->desc_num - used - 1; return ring->desc_num - used - 1;
} }
static int is_valid_csq_clean_head(struct hclge_cmq_ring *ring, int h)
{
int u = ring->next_to_use;
int c = ring->next_to_clean;
if (unlikely(h >= ring->desc_num))
return 0;
return u > c ? (h > c && h <= u) : (h > c || h <= u);
}
static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring) static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
{ {
int size = ring->desc_num * sizeof(struct hclge_desc); int size = ring->desc_num * sizeof(struct hclge_desc);
...@@ -141,6 +152,7 @@ static void hclge_cmd_init_regs(struct hclge_hw *hw) ...@@ -141,6 +152,7 @@ static void hclge_cmd_init_regs(struct hclge_hw *hw)
static int hclge_cmd_csq_clean(struct hclge_hw *hw) static int hclge_cmd_csq_clean(struct hclge_hw *hw)
{ {
struct hclge_dev *hdev = (struct hclge_dev *)hw->back;
struct hclge_cmq_ring *csq = &hw->cmq.csq; struct hclge_cmq_ring *csq = &hw->cmq.csq;
u16 ntc = csq->next_to_clean; u16 ntc = csq->next_to_clean;
struct hclge_desc *desc; struct hclge_desc *desc;
...@@ -149,6 +161,13 @@ static int hclge_cmd_csq_clean(struct hclge_hw *hw) ...@@ -149,6 +161,13 @@ static int hclge_cmd_csq_clean(struct hclge_hw *hw)
desc = &csq->desc[ntc]; desc = &csq->desc[ntc];
head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG); head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
rmb(); /* Make sure head is ready before touch any data */
if (!is_valid_csq_clean_head(csq, head)) {
dev_warn(&hdev->pdev->dev, "wrong head (%d, %d-%d)\n", head,
csq->next_to_use, csq->next_to_clean);
return 0;
}
while (head != ntc) { while (head != ntc) {
memset(desc, 0, sizeof(*desc)); memset(desc, 0, sizeof(*desc));
......
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