|
@@ -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));
|