qcacmn: fix RX desc is using but freed back to pool

Crash scenario:
(1) frag data A is dropped and related RX desc A is replenished
and reused, but pdev->free_list_tail is still pointed to RX desc A.
(2) frag data B/C is coming, defrag fails then pdev->free_list_head
will point to B-->C RX desc, but pdev->free_list_tail still point to A.
(3) for defrag failing case, host only will replenish 1 RX buffer for
current case, RX desc B is replenished, while C will be free back to
RX desc pool.
(4) dp_rx_add_desc_list_to_free_list will set RX desc A-->next =
free_list, free_list point to C insted.
(5) when step (1) RX desc A replenished buffer indicated to host by
REO2Dst ring, RX desc A -->nbuf actually is pointed to another RX
desc, invalid skb accessing will happen.

Solution:
a. reset tail pointer in dp_rx_add_desc_list_to_free_list at last.
b. reset tail pointer same as head in dp_rx_add_to_free_desc_list
if head->next is NULL.
c. set correct rx_bufs number for replenish when dp_rx_defrag fails.

Change-Id: Ib297baea3605a09dd7d85d1f5ceb95db48a2e1f1
CRs-Fixed: 2603676
这个提交包含在:
Jinwei Chen
2020-01-16 19:52:41 +08:00
提交者 nshrivas
父节点 acb460015b
当前提交 3222184e14
修改 3 个文件,包含 9 行新增7 行删除

查看文件

@@ -582,7 +582,8 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head,
((union dp_rx_desc_list_elem_t *)new)->next = *head;
*head = (union dp_rx_desc_list_elem_t *)new;
if (!*tail)
/* reset tail if head->next is NULL */
if (!*tail || !(*head)->next)
*tail = *head;
}