Commit b1753c62 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho

iwlwifi: pcie: track rxb status

In MQ environment and new architecture in early stages
we may encounter DMA issues. Track RXB status and bail
out in case we receive index to an RXB that was not
mapped and handed over to HW.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f16c3ebf
...@@ -68,12 +68,14 @@ struct iwl_host_cmd; ...@@ -68,12 +68,14 @@ struct iwl_host_cmd;
* struct iwl_rx_mem_buffer * struct iwl_rx_mem_buffer
* @page_dma: bus address of rxb page * @page_dma: bus address of rxb page
* @page: driver's pointer to the rxb page * @page: driver's pointer to the rxb page
* @invalid: rxb is in driver ownership - not owned by HW
* @vid: index of this rxb in the global table * @vid: index of this rxb in the global table
*/ */
struct iwl_rx_mem_buffer { struct iwl_rx_mem_buffer {
dma_addr_t page_dma; dma_addr_t page_dma;
struct page *page; struct page *page;
u16 vid; u16 vid;
bool invalid;
struct list_head list; struct list_head list;
}; };
......
...@@ -266,7 +266,7 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans, ...@@ -266,7 +266,7 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans,
rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer, rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer,
list); list);
list_del(&rxb->list); list_del(&rxb->list);
rxb->invalid = false;
/* 12 first bits are expected to be empty */ /* 12 first bits are expected to be empty */
WARN_ON(rxb->page_dma & DMA_BIT_MASK(12)); WARN_ON(rxb->page_dma & DMA_BIT_MASK(12));
/* Point to Rx buffer via next RBD in circular buffer */ /* Point to Rx buffer via next RBD in circular buffer */
...@@ -317,6 +317,7 @@ static void iwl_pcie_rxsq_restock(struct iwl_trans *trans, ...@@ -317,6 +317,7 @@ static void iwl_pcie_rxsq_restock(struct iwl_trans *trans,
rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer, rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer,
list); list);
list_del(&rxb->list); list_del(&rxb->list);
rxb->invalid = false;
/* Point to Rx buffer via next RBD in circular buffer */ /* Point to Rx buffer via next RBD in circular buffer */
bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma);
...@@ -961,6 +962,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) ...@@ -961,6 +962,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
list_add(&rxb->list, &def_rxq->rx_used); list_add(&rxb->list, &def_rxq->rx_used);
trans_pcie->global_table[i] = rxb; trans_pcie->global_table[i] = rxb;
rxb->vid = (u16)(i + 1); rxb->vid = (u16)(i + 1);
rxb->invalid = true;
} }
iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq);
...@@ -1256,6 +1258,12 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue) ...@@ -1256,6 +1258,12 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue)
goto out; goto out;
} }
rxb = trans_pcie->global_table[vid - 1]; rxb = trans_pcie->global_table[vid - 1];
if (WARN(rxb->invalid,
"Invalid rxb from HW %u\n", (u32)vid)) {
iwl_force_nmi(trans);
goto out;
}
rxb->invalid = true;
} else { } else {
rxb = rxq->queue[i]; rxb = rxq->queue[i];
rxq->queue[i] = NULL; rxq->queue[i] = NULL;
......
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