Skip to content

Commit

Permalink
iwlwifi: pcie: clarify RX queue need_update handling and locking
Browse files Browse the repository at this point in the history
When shadow registers are enabled, then need_update never needs
to be set, so move the need_update handling into the function
that really needs to do it (iwl_pcie_rxq_inc_wr_ptr) and also
separate the check when it woke up. While at it, convert it to
bool.

This also clarifies the locking and means the irq_lock needs to
no longer be held for any such updates.

The irq_lock also doesn't have to be held for restocking since
everything else locks the RX queue properly, so remove that and
finally disentangle the two locks entirely so there aren't any
dependencies between the two left.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
  • Loading branch information
Johannes Berg authored and Emmanuel Grumbach committed Apr 13, 2014
1 parent f14d6b3 commit 5d63f92
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ struct iwl_rxq {
u32 write_actual;
struct list_head rx_free;
struct list_head rx_used;
int need_update;
bool need_update;
struct iwl_rb_status *rb_stts;
dma_addr_t rb_stts_dma;
spinlock_t lock;
Expand Down
44 changes: 25 additions & 19 deletions drivers/net/wireless/iwlwifi/pcie/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,13 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
/*
* iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue
*/
static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
struct iwl_rxq *rxq)
static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
u32 reg;

spin_lock(&rxq->lock);

if (rxq->need_update == 0)
goto exit_unlock;
lockdep_assert_held(&rxq->lock);

/*
* explicitly wake up the NIC if:
Expand All @@ -169,13 +167,27 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
reg);
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
goto exit_unlock;
rxq->need_update = true;
return;
}
}

rxq->write_actual = round_down(rxq->write, 8);
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
rxq->need_update = 0;
}

static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;

spin_lock(&rxq->lock);

if (!rxq->need_update)
goto exit_unlock;

iwl_pcie_rxq_inc_wr_ptr(trans);
rxq->need_update = false;

exit_unlock:
spin_unlock(&rxq->lock);
Expand Down Expand Up @@ -236,9 +248,8 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
* Increment device's write pointer in multiples of 8. */
if (rxq->write_actual != (rxq->write & ~0x7)) {
spin_lock(&rxq->lock);
rxq->need_update = 1;
iwl_pcie_rxq_inc_wr_ptr(trans);
spin_unlock(&rxq->lock);
iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
}
}

Expand Down Expand Up @@ -364,13 +375,9 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
*/
static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);

iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);

spin_lock(&trans_pcie->irq_lock);
iwl_pcie_rxq_restock(trans);
spin_unlock(&trans_pcie->irq_lock);
}

static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
Expand Down Expand Up @@ -525,10 +532,9 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)

iwl_pcie_rx_hw_init(trans, rxq);

spin_lock(&trans_pcie->irq_lock);
rxq->need_update = 1;
iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
spin_unlock(&trans_pcie->irq_lock);
spin_lock(&rxq->lock);
iwl_pcie_rxq_inc_wr_ptr(trans);
spin_unlock(&rxq->lock);

return 0;
}
Expand Down Expand Up @@ -1035,7 +1041,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* uCode wakes up after power-down sleep */
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
iwl_pcie_rxq_inc_wr_ptr(trans, &trans_pcie->rxq);
iwl_pcie_rxq_check_wrptr(trans);
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++)
iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]);

Expand Down

0 comments on commit 5d63f92

Please sign in to comment.