Skip to content

Commit 3ff5049

Browse files
Huazhong Tandavem330
authored andcommitted
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: 68c0a5c ("net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support") Signed-off-by: Huazhong Tan <[email protected]> Signed-off-by: Peng Li <[email protected]> Signed-off-by: Salil Mehta <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0c963e8 commit 3ff5049

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ static int hclge_ring_space(struct hclge_cmq_ring *ring)
3131
return ring->desc_num - used - 1;
3232
}
3333

34+
static int is_valid_csq_clean_head(struct hclge_cmq_ring *ring, int h)
35+
{
36+
int u = ring->next_to_use;
37+
int c = ring->next_to_clean;
38+
39+
if (unlikely(h >= ring->desc_num))
40+
return 0;
41+
42+
return u > c ? (h > c && h <= u) : (h > c || h <= u);
43+
}
44+
3445
static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
3546
{
3647
int size = ring->desc_num * sizeof(struct hclge_desc);
@@ -141,6 +152,7 @@ static void hclge_cmd_init_regs(struct hclge_hw *hw)
141152

142153
static int hclge_cmd_csq_clean(struct hclge_hw *hw)
143154
{
155+
struct hclge_dev *hdev = (struct hclge_dev *)hw->back;
144156
struct hclge_cmq_ring *csq = &hw->cmq.csq;
145157
u16 ntc = csq->next_to_clean;
146158
struct hclge_desc *desc;
@@ -149,6 +161,13 @@ static int hclge_cmd_csq_clean(struct hclge_hw *hw)
149161

150162
desc = &csq->desc[ntc];
151163
head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
164+
rmb(); /* Make sure head is ready before touch any data */
165+
166+
if (!is_valid_csq_clean_head(csq, head)) {
167+
dev_warn(&hdev->pdev->dev, "wrong head (%d, %d-%d)\n", head,
168+
csq->next_to_use, csq->next_to_clean);
169+
return 0;
170+
}
152171

153172
while (head != ntc) {
154173
memset(desc, 0, sizeof(*desc));

0 commit comments

Comments
 (0)