qcacld-3.0: Add detection of non-posted rx buffers
Add detection of non posted RX buffers from FW (rx_in_order_ind msgs) by marking the higher(16) unused bits of the 64-bit physical addresses. On reception, if the paddr received does not have the markings, assert, otherwise clean the markings and proceed. Duplicate rx-buffers will be detected in the FW. CRs-Fixed: 2000844 Change-Id: I9c50cce182a12f3edd3c5b2606836d62f684f816
此提交包含在:
@@ -345,6 +345,74 @@ htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc)
|
|||||||
|
|
||||||
#ifndef CONFIG_HL_SUPPORT
|
#ifndef CONFIG_HL_SUPPORT
|
||||||
|
|
||||||
|
#define RX_PADDR_MAGIC_PATTERN 0xDEAD0000
|
||||||
|
static qdf_dma_addr_t
|
||||||
|
htt_rx_paddr_mark_high_bits(qdf_dma_addr_t paddr)
|
||||||
|
{
|
||||||
|
#ifdef HELIUMPLUS_PADDR64
|
||||||
|
if (sizeof(qdf_dma_addr_t) > 4) {
|
||||||
|
/* clear high bits, leave lower 37 bits (paddr) */
|
||||||
|
paddr &= 0x01FFFFFFFFF;
|
||||||
|
/* mark upper 16 bits of paddr */
|
||||||
|
paddr |= (((uint64_t)RX_PADDR_MAGIC_PATTERN) << 32);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return paddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HELIUMPLUS_PADDR64
|
||||||
|
static qdf_dma_addr_t
|
||||||
|
htt_rx_paddr_unmark_high_bits(qdf_dma_addr_t paddr)
|
||||||
|
{
|
||||||
|
uint32_t markings;
|
||||||
|
|
||||||
|
if (sizeof(qdf_dma_addr_t) > 4) {
|
||||||
|
markings = (uint32_t)((paddr >> 16) >> 16);
|
||||||
|
/*
|
||||||
|
* check if it is marked correctly:
|
||||||
|
* See the mark_high_bits function above for the expected
|
||||||
|
* pattern.
|
||||||
|
* the LS 5 bits are the high bits of physical address
|
||||||
|
* padded (with 0b0) to 8 bits
|
||||||
|
*/
|
||||||
|
if ((markings & 0xFFFF0000) != RX_PADDR_MAGIC_PATTERN) {
|
||||||
|
qdf_print("%s: paddr not marked correctly: 0x%p!\n",
|
||||||
|
__func__, (void *)paddr);
|
||||||
|
HTT_ASSERT_ALWAYS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear markings for further use */
|
||||||
|
paddr &= (uint64_t)0x1ffffffff; /* LS 37 bits */
|
||||||
|
}
|
||||||
|
return paddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qdf_dma_addr_t
|
||||||
|
htt_rx_in_ord_paddr_get(uint32_t *u32p)
|
||||||
|
{
|
||||||
|
qdf_dma_addr_t paddr = 0;
|
||||||
|
|
||||||
|
paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p);
|
||||||
|
if (sizeof(qdf_dma_addr_t) > 4) {
|
||||||
|
u32p++;
|
||||||
|
paddr |= ((qdf_dma_addr_t)
|
||||||
|
(HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p) << 16) << 16);
|
||||||
|
}
|
||||||
|
paddr = htt_rx_paddr_unmark_high_bits(paddr);
|
||||||
|
|
||||||
|
return paddr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline qdf_dma_addr_t
|
||||||
|
htt_rx_in_ord_paddr_get(uint32_t *u32p)
|
||||||
|
{
|
||||||
|
return HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p);
|
||||||
|
}
|
||||||
|
#endif /* HELIUMPLUS_PADDR64 */
|
||||||
|
#endif /* CONFIG_HL_SUPPORT*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_HL_SUPPORT
|
||||||
|
|
||||||
static int htt_rx_ring_size(struct htt_pdev_t *pdev)
|
static int htt_rx_ring_size(struct htt_pdev_t *pdev)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
@@ -483,6 +551,7 @@ moretofill:
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0);
|
paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0);
|
||||||
|
paddr = htt_rx_paddr_mark_high_bits(paddr);
|
||||||
if (pdev->cfg.is_full_reorder_offload) {
|
if (pdev->cfg.is_full_reorder_offload) {
|
||||||
if (qdf_unlikely(htt_rx_hash_list_insert(
|
if (qdf_unlikely(htt_rx_hash_list_insert(
|
||||||
pdev, (uint32_t)paddr, rx_netbuf))) {
|
pdev, (uint32_t)paddr, rx_netbuf))) {
|
||||||
@@ -503,9 +572,6 @@ moretofill:
|
|||||||
} else {
|
} else {
|
||||||
pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf;
|
pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf;
|
||||||
}
|
}
|
||||||
#if HTT_PADDR64
|
|
||||||
paddr &= 0x1fffffffff; /* trim out higher than 37 bits */
|
|
||||||
#endif /* HTT_PADDR64 */
|
|
||||||
pdev->rx_ring.buf.paddrs_ring[idx] = paddr;
|
pdev->rx_ring.buf.paddrs_ring[idx] = paddr;
|
||||||
pdev->rx_ring.fill_cnt++;
|
pdev->rx_ring.fill_cnt++;
|
||||||
|
|
||||||
@@ -858,11 +924,11 @@ static inline qdf_nbuf_t htt_rx_netbuf_pop(htt_pdev_handle pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline qdf_nbuf_t
|
static inline qdf_nbuf_t
|
||||||
htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, uint32_t paddr)
|
htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, qdf_dma_addr_t paddr)
|
||||||
{
|
{
|
||||||
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
||||||
pdev->rx_ring.fill_cnt--;
|
pdev->rx_ring.fill_cnt--;
|
||||||
return htt_rx_hash_list_lookup(pdev, paddr);
|
return htt_rx_hash_list_lookup(pdev, (uint32_t)(paddr & 0xffffffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIX ME: this function applies only to LL rx descs.
|
/* FIX ME: this function applies only to LL rx descs.
|
||||||
@@ -1417,11 +1483,11 @@ htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev,
|
|||||||
qdf_nbuf_t buf;
|
qdf_nbuf_t buf;
|
||||||
uint32_t *msdu_hdr, msdu_len;
|
uint32_t *msdu_hdr, msdu_len;
|
||||||
uint32_t *curr_msdu;
|
uint32_t *curr_msdu;
|
||||||
uint32_t paddr;
|
qdf_dma_addr_t paddr;
|
||||||
|
|
||||||
curr_msdu =
|
curr_msdu =
|
||||||
msg_word + (msdu_iter * HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS);
|
msg_word + (msdu_iter * HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS);
|
||||||
paddr = HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*curr_msdu);
|
paddr = htt_rx_in_ord_paddr_get(curr_msdu);
|
||||||
*head_buf = *tail_buf = buf = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
*head_buf = *tail_buf = buf = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
|
|
||||||
if (qdf_unlikely(NULL == buf)) {
|
if (qdf_unlikely(NULL == buf)) {
|
||||||
@@ -1491,10 +1557,11 @@ int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev,
|
|||||||
qdf_nbuf_t prev_frag_nbuf;
|
qdf_nbuf_t prev_frag_nbuf;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t last_frag;
|
uint32_t last_frag;
|
||||||
|
qdf_dma_addr_t paddr;
|
||||||
|
|
||||||
*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
||||||
frag_nbuf = htt_rx_in_order_netbuf_pop(pdev,
|
paddr = htt_rx_in_ord_paddr_get(*msg_word);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word));
|
frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
if (qdf_unlikely(NULL == frag_nbuf)) {
|
if (qdf_unlikely(NULL == frag_nbuf)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n", __func__);
|
qdf_print("%s: netbuf pop failed!\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1516,8 +1583,8 @@ int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev,
|
|||||||
prev_frag_nbuf = frag_nbuf;
|
prev_frag_nbuf = frag_nbuf;
|
||||||
while (!last_frag) {
|
while (!last_frag) {
|
||||||
*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
||||||
frag_nbuf = htt_rx_in_order_netbuf_pop(pdev,
|
paddr = htt_rx_in_ord_paddr_get(*msg_word);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word));
|
frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)
|
last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)
|
||||||
*msg_word)->msdu_info;
|
*msg_word)->msdu_info;
|
||||||
|
|
||||||
@@ -1804,6 +1871,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
uint32_t amsdu_len;
|
uint32_t amsdu_len;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t last_frag;
|
uint32_t last_frag;
|
||||||
|
qdf_dma_addr_t paddr;
|
||||||
|
|
||||||
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
||||||
|
|
||||||
@@ -1821,9 +1889,8 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
|
|
||||||
msg_word = (uint32_t *)(rx_ind_data +
|
msg_word = (uint32_t *)(rx_ind_data +
|
||||||
HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES);
|
HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES);
|
||||||
|
paddr = htt_rx_in_ord_paddr_get(msg_word);
|
||||||
(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev,
|
(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
|
|
||||||
|
|
||||||
if (qdf_unlikely(NULL == msdu)) {
|
if (qdf_unlikely(NULL == msdu)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n", __func__);
|
qdf_print("%s: netbuf pop failed!\n", __func__);
|
||||||
@@ -1897,8 +1964,8 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
/* check if this is the last msdu */
|
/* check if this is the last msdu */
|
||||||
if (msdu_count) {
|
if (msdu_count) {
|
||||||
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
||||||
next = htt_rx_in_order_netbuf_pop(pdev,
|
paddr = htt_rx_in_ord_paddr_get(msg_word);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
|
next = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
if (qdf_unlikely(NULL == next)) {
|
if (qdf_unlikely(NULL == next)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n",
|
qdf_print("%s: netbuf pop failed!\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1955,6 +2022,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
uint8_t peer_id;
|
uint8_t peer_id;
|
||||||
struct htt_host_rx_desc_base *rx_desc;
|
struct htt_host_rx_desc_base *rx_desc;
|
||||||
enum rx_pkt_fate status = RX_PKT_FATE_SUCCESS;
|
enum rx_pkt_fate status = RX_PKT_FATE_SUCCESS;
|
||||||
|
qdf_dma_addr_t paddr;
|
||||||
|
|
||||||
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
|
||||||
|
|
||||||
@@ -1983,9 +2051,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(
|
paddr = htt_rx_in_ord_paddr_get(msg_word);
|
||||||
pdev,
|
(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
|
|
||||||
|
|
||||||
if (qdf_unlikely(NULL == msdu)) {
|
if (qdf_unlikely(NULL == msdu)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n", __func__);
|
qdf_print("%s: netbuf pop failed!\n", __func__);
|
||||||
@@ -2077,10 +2144,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
} else { /* if this is not the last msdu */
|
} else { /* if this is not the last msdu */
|
||||||
/* get the next msdu */
|
/* get the next msdu */
|
||||||
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
||||||
next = htt_rx_in_order_netbuf_pop(
|
paddr = htt_rx_in_ord_paddr_get(msg_word);
|
||||||
pdev,
|
next = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(
|
|
||||||
*msg_word));
|
|
||||||
if (qdf_unlikely(NULL == next)) {
|
if (qdf_unlikely(NULL == next)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n",
|
qdf_print("%s: netbuf pop failed!\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -2110,9 +2175,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
|
|||||||
/* check if this is the last msdu */
|
/* check if this is the last msdu */
|
||||||
if (msdu_count) {
|
if (msdu_count) {
|
||||||
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
|
||||||
next = htt_rx_in_order_netbuf_pop(
|
paddr = htt_rx_in_ord_paddr_get(msg_word);
|
||||||
pdev,
|
next = htt_rx_in_order_netbuf_pop(pdev, paddr);
|
||||||
HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
|
|
||||||
if (qdf_unlikely(NULL == next)) {
|
if (qdf_unlikely(NULL == next)) {
|
||||||
qdf_print("%s: netbuf pop failed!\n",
|
qdf_print("%s: netbuf pop failed!\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
新增問題並參考
封鎖使用者