diff options
author | Lilach Edelstein <lilach.edelstein@intel.com> | 2013-01-16 11:34:49 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-01 11:27:22 +0100 |
commit | e56b04efc1f795da42cf1d9651b52a4a5bebd730 (patch) | |
tree | a9740ffd4d47ffb7b90507691a0a066c20f42a2d /drivers/net/wireless/iwlwifi/pcie/trans.c | |
parent | e139dc4aebf52a9c88552963b9794fd1dff036f1 (diff) |
iwlwifi: move register access lock into transport
Move the reg_lock that protects HW register access
into the transport implementation. Locking is no
longer exposed, but handled internally in grab and
release NIC access. This simplifies the users.
Signed-off-by: Lilach Edelstein <lilach.edelstein@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/trans.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 8692494c1c48..56d4f72500bc 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -806,11 +806,12 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) } #endif /* CONFIG_PM_SLEEP */ -static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) +static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, + unsigned long *flags) { int ret; - - lockdep_assert_held(&trans->reg_lock); + struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); + spin_lock_irqsave(&pcie_trans->reg_lock, *flags); /* this bit wakes up the NIC */ __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, @@ -846,16 +847,32 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) WARN_ONCE(1, "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", val); + spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); return false; } } + /* + * Fool sparse by faking we release the lock - sparse will + * track nic_access anyway. + */ + __release(&pcie_trans->reg_lock); return true; } -static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) +static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, + unsigned long *flags) { - lockdep_assert_held(&trans->reg_lock); + struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); + + lockdep_assert_held(&pcie_trans->reg_lock); + + /* + * Fool sparse by faking we acquiring the lock - sparse will + * track nic_access anyway. + */ + __acquire(&pcie_trans->reg_lock); + __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* @@ -865,6 +882,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) * scheduled on different CPUs (after we drop reg_lock). */ mmiowb(); + spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); } static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, @@ -874,16 +892,14 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, int offs, ret = 0; u32 *vals = buf; - spin_lock_irqsave(&trans->reg_lock, flags); - if (iwl_trans_grab_nic_access(trans, false)) { + if (iwl_trans_grab_nic_access(trans, false, &flags)) { iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); for (offs = 0; offs < dwords; offs++) vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); - iwl_trans_release_nic_access(trans); + iwl_trans_release_nic_access(trans, &flags); } else { ret = -EBUSY; } - spin_unlock_irqrestore(&trans->reg_lock, flags); return ret; } @@ -894,17 +910,15 @@ static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, int offs, ret = 0; u32 *vals = buf; - spin_lock_irqsave(&trans->reg_lock, flags); - if (iwl_trans_grab_nic_access(trans, false)) { + if (iwl_trans_grab_nic_access(trans, false, &flags)) { iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); for (offs = 0; offs < dwords; offs++) iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals ? vals[offs] : 0); - iwl_trans_release_nic_access(trans); + iwl_trans_release_nic_access(trans, &flags); } else { ret = -EBUSY; } - spin_unlock_irqrestore(&trans->reg_lock, flags); return ret; } @@ -982,11 +996,12 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; - spin_lock_irqsave(&trans->reg_lock, flags); + spin_lock_irqsave(&trans_pcie->reg_lock, flags); __iwl_trans_pcie_set_bits_mask(trans, reg, mask, value); - spin_unlock_irqrestore(&trans->reg_lock, flags); + spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); } static const char *get_fh_string(int cmd) @@ -1467,6 +1482,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans->cfg = cfg; trans_pcie->trans = trans; spin_lock_init(&trans_pcie->irq_lock); + spin_lock_init(&trans_pcie->reg_lock); init_waitqueue_head(&trans_pcie->ucode_write_waitq); /* W/A - seems to solve weird behavior. We need to remove this if we @@ -1533,7 +1549,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); - spin_lock_init(&trans->reg_lock); snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); |