All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/10] make iwlwifi RT friendly
@ 2013-12-11  8:33 Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                   ` (12 more replies)
  0 siblings, 13 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

RT folks have raised issues with iwlwifi wrt. RT kernel some time
ago. Johannes had a few patches to address this, but I had a few
concerns with them. This series tries to address the RT concerns:
* we don't do anything in hard-irq context besides stopping the
  interrupts in the device.
* the interrupt cause is read from the irq handler and is handled
  there.

This allows us to avoid the usage of _irqsave all over the driver
and also avoids any kind of locks in the hard-irq context.
We still have some work to do with the locks in the handler.
I believe the locking model can be improved there.

This patch series is split is very small patches. While this can
annoy the reader - it helped me much to make sure I don't do anything
wrong (well - I am still not sure) - and IMHO, it makes the review easier.
For example, in patch 
    iwlwifi: pcie: move the ICT / non-ICT handling functions
I just copy code from place to place without changing a bit. This makes
the significant diff smaller.

Emmanuel Grumbach (10):
  iwlwifi: pcie: clean up ICT allocation code
  iwlwifi: pcie: track interrupt mask in SW
  iwlwifi: pcie: re-organize the PCIe ISR code
  iwlwifi: pcie: move the ICT / non-ICT handling functions
  iwlwifi: pcie: read the interrupt cause from the handler
  iwlwifi: pcie: determine the interrupt type in the handler
  iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
  iwlwifi: pcie: no need to save inta in trans_pcie
  iwlwifi: pcie: move interrupt prints to the common handler
  iwlwifi: pcie: stop using _irqsave

 drivers/net/wireless/iwlwifi/iwl-csr.h       |   3 +-
 drivers/net/wireless/iwlwifi/pcie/internal.h |   9 +-
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 389 +++++++++++----------------
 drivers/net/wireless/iwlwifi/pcie/trans.c    |  27 +-
 drivers/net/wireless/iwlwifi/pcie/tx.c       |  10 +-
 5 files changed, 185 insertions(+), 253 deletions(-)

-- 
1.8.3.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [RFC 01/10] iwlwifi: pcie: clean up ICT allocation code
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

Since iwl_trans_pcie_alloc_ict is called in the PCIe
allocation code, we always set CSR_INT_BIT_RX_PERIODIC.
Move that bit to the default list of interrupts we enable
and simplify the code.
Also use dma_zalloc_ and avoid to memset the memory
afterwards.
trans_pcie->ict_index is 0 since trans_pcie has just been
kzalloced, remove the redundant assignment.

Change-Id: I1612bafb2c93d8a796cdd42444102e39199d4869
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-csr.h |  3 ++-
 drivers/net/wireless/iwlwifi/pcie/rx.c | 15 ++++-----------
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index da4eca8..bbab26e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -198,7 +198,8 @@
 				 CSR_INT_BIT_RF_KILL | \
 				 CSR_INT_BIT_SW_RX   | \
 				 CSR_INT_BIT_WAKEUP  | \
-				 CSR_INT_BIT_ALIVE)
+				 CSR_INT_BIT_ALIVE   | \
+				 CSR_INT_BIT_RX_PERIODIC)
 
 /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
 #define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 7aeec5c..b3e6564 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1048,7 +1048,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	trans_pcie->ict_tbl =
-		dma_alloc_coherent(trans->dev, ICT_SIZE,
+		dma_zalloc_coherent(trans->dev, ICT_SIZE,
 				   &trans_pcie->ict_tbl_dma,
 				   GFP_KERNEL);
 	if (!trans_pcie->ict_tbl)
@@ -1060,17 +1060,10 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
 		return -EINVAL;
 	}
 
-	IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
-		      (unsigned long long)trans_pcie->ict_tbl_dma);
+	IWL_DEBUG_ISR(trans, "ict dma addr %Lx ict vir addr %p\n",
+		      (unsigned long long)trans_pcie->ict_tbl_dma,
+		      trans_pcie->ict_tbl);
 
-	IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
-
-	/* reset table and index to all 0 */
-	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
-	trans_pcie->ict_index = 0;
-
-	/* add periodic RX interrupt */
-	trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 01/10] iwlwifi: pcie: clean up ICT allocation code
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Emmanuel Grumbach

Since iwl_trans_pcie_alloc_ict is called in the PCIe
allocation code, we always set CSR_INT_BIT_RX_PERIODIC.
Move that bit to the default list of interrupts we enable
and simplify the code.
Also use dma_zalloc_ and avoid to memset the memory
afterwards.
trans_pcie->ict_index is 0 since trans_pcie has just been
kzalloced, remove the redundant assignment.

Change-Id: I1612bafb2c93d8a796cdd42444102e39199d4869
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/net/wireless/iwlwifi/iwl-csr.h |  3 ++-
 drivers/net/wireless/iwlwifi/pcie/rx.c | 15 ++++-----------
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index da4eca8..bbab26e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -198,7 +198,8 @@
 				 CSR_INT_BIT_RF_KILL | \
 				 CSR_INT_BIT_SW_RX   | \
 				 CSR_INT_BIT_WAKEUP  | \
-				 CSR_INT_BIT_ALIVE)
+				 CSR_INT_BIT_ALIVE   | \
+				 CSR_INT_BIT_RX_PERIODIC)
 
 /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
 #define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 7aeec5c..b3e6564 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1048,7 +1048,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	trans_pcie->ict_tbl =
-		dma_alloc_coherent(trans->dev, ICT_SIZE,
+		dma_zalloc_coherent(trans->dev, ICT_SIZE,
 				   &trans_pcie->ict_tbl_dma,
 				   GFP_KERNEL);
 	if (!trans_pcie->ict_tbl)
@@ -1060,17 +1060,10 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
 		return -EINVAL;
 	}
 
-	IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
-		      (unsigned long long)trans_pcie->ict_tbl_dma);
+	IWL_DEBUG_ISR(trans, "ict dma addr %Lx ict vir addr %p\n",
+		      (unsigned long long)trans_pcie->ict_tbl_dma,
+		      trans_pcie->ict_tbl);
 
-	IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
-
-	/* reset table and index to all 0 */
-	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
-	trans_pcie->ict_index = 0;

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 02/10] iwlwifi: pcie: track interrupt mask in SW
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

trans_pcie->inta_mask is now exactly what we have
configured in the interrupt mask register in the hardware.
This allows not to access the register from the interrupt
handler. This was the case for ICT interrupt already, but
not for non-ICT interrupt.

Change-Id: I28748fe7c896afc251a6b077bc4504df7008120a
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  6 +++++-
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 13 ++++++-------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 9bb1046..c9821ca 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -400,13 +400,17 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
 
 	IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
 	set_bit(STATUS_INT_ENABLED, &trans->status);
+	trans_pcie->inta_mask = CSR_INI_SET_MASK;
 	iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
 	IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-	iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+	trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
+	iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index b3e6564..7e4836f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1115,7 +1115,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 {
 	struct iwl_trans *trans = data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 inta, inta_mask;
+	u32 inta;
 
 	lockdep_assert_held(&trans_pcie->irq_lock);
 
@@ -1125,18 +1125,17 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 	 *    back-to-back ISRs and sporadic interrupts from our NIC.
 	 * If we have something to service, the irq thread will re-enable ints.
 	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(trans, CSR_INT_MASK);
 	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
 
 	/* Discover which interrupts are active/pending */
 	inta = iwl_read32(trans, CSR_INT);
 
-	if (inta & (~inta_mask)) {
+	if (inta & (~trans_pcie->inta_mask)) {
 		IWL_DEBUG_ISR(trans,
 			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-			      inta & (~inta_mask));
-		iwl_write32(trans, CSR_INT, inta & (~inta_mask));
-		inta &= inta_mask;
+			      inta & (~trans_pcie->inta_mask));
+		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
+		inta &= trans_pcie->inta_mask;
 	}
 
 	/* Ignore interrupt if there's nothing in NIC to service.
@@ -1166,7 +1165,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 	if (iwl_have_debug_level(IWL_DL_ISR))
 		IWL_DEBUG_ISR(trans,
 			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, inta_mask,
+			      inta, trans_pcie->inta_mask,
 			      iwl_read32(trans, CSR_FH_INT_STATUS));
 
 	trans_pcie->inta |= inta;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 02/10] iwlwifi: pcie: track interrupt mask in SW
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Emmanuel Grumbach

trans_pcie->inta_mask is now exactly what we have
configured in the interrupt mask register in the hardware.
This allows not to access the register from the interrupt
handler. This was the case for ICT interrupt already, but
not for non-ICT interrupt.

Change-Id: I28748fe7c896afc251a6b077bc4504df7008120a
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  6 +++++-
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 13 ++++++-------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 9bb1046..c9821ca 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -400,13 +400,17 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
 
 	IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
 	set_bit(STATUS_INT_ENABLED, &trans->status);
+	trans_pcie->inta_mask = CSR_INI_SET_MASK;
 	iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
 	IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-	iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+	trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL;
+	iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index b3e6564..7e4836f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1115,7 +1115,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 {
 	struct iwl_trans *trans = data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 inta, inta_mask;
+	u32 inta;
 
 	lockdep_assert_held(&trans_pcie->irq_lock);
 
@@ -1125,18 +1125,17 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 	 *    back-to-back ISRs and sporadic interrupts from our NIC.
 	 * If we have something to service, the irq thread will re-enable ints.
 	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(trans, CSR_INT_MASK);
 	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
 
 	/* Discover which interrupts are active/pending */
 	inta = iwl_read32(trans, CSR_INT);
 
-	if (inta & (~inta_mask)) {
+	if (inta & (~trans_pcie->inta_mask)) {
 		IWL_DEBUG_ISR(trans,
 			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-			      inta & (~inta_mask));
-		iwl_write32(trans, CSR_INT, inta & (~inta_mask));
-		inta &= inta_mask;
+			      inta & (~trans_pcie->inta_mask));
+		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
+		inta &= trans_pcie->inta_mask;
 	}
 
 	/* Ignore interrupt if there's nothing in NIC to service.
@@ -1166,7 +1165,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 	if (iwl_have_debug_level(IWL_DL_ISR))
 		IWL_DEBUG_ISR(trans,
 			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, inta_mask,
+			      inta, trans_pcie->inta_mask,
 			      iwl_read32(trans, CSR_FH_INT_STATUS));
 
 	trans_pcie->inta |= inta;
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 03/10] iwlwifi: pcie: re-organize the PCIe ISR code
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
@ 2013-12-11  8:33 ` Emmanuel Grumbach
  2013-12-11  9:49   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

Separate the code that simply disables interrupt in the
hardware and the code that checks what interrupt fired.
This will be useful to move the second part in the threaded
handler which will be done in a future patch.

Change-Id: Iec42aa577c9de5c5a13a6030a1d8a69b4da37f43
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  2 +-
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 49 +++++++++++++---------------
 drivers/net/wireless/iwlwifi/pcie/trans.c    |  4 +--
 3 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index c9821ca..c790df6 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -346,7 +346,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans);
 /*****************************************************
 * ICT - interrupt handling
 ******************************************************/
-irqreturn_t iwl_pcie_isr_ict(int irq, void *data);
+irqreturn_t iwl_pcie_isr(int irq, void *data);
 int iwl_pcie_alloc_ict(struct iwl_trans *trans);
 void iwl_pcie_free_ict(struct iwl_trans *trans);
 void iwl_pcie_reset_ict(struct iwl_trans *trans);
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 7e4836f..54a2f4a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1111,9 +1111,8 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans)
 }
 
 /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr(int irq, void *data)
+static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
 {
-	struct iwl_trans *trans = data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
 
@@ -1121,12 +1120,6 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 
 	trace_iwlwifi_dev_irq(trans->dev);
 
-	/* Disable (but don't clear!) interrupts here to avoid
-	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the irq thread will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here. */
-	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
-
 	/* Discover which interrupts are active/pending */
 	inta = iwl_read32(trans, CSR_INT);
 
@@ -1181,20 +1174,14 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
+static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 {
-	struct iwl_trans *trans = data;
-	struct iwl_trans_pcie *trans_pcie;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	unsigned long flags;
+	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
-	unsigned long flags;
-	irqreturn_t ret = IRQ_NONE;
-
-	if (!trans)
-		return IRQ_NONE;
-
-	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
@@ -1202,20 +1189,13 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
 	 * use legacy interrupt.
 	 */
 	if (unlikely(!trans_pcie->use_ict)) {
-		ret = iwl_pcie_isr(irq, data);
+		ret = iwl_pcie_isr_non_ict(trans);
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 		return ret;
 	}
 
 	trace_iwlwifi_dev_irq(trans->dev);
 
-	/* Disable (but don't clear!) interrupts here to avoid
-	 * back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here.
-	 */
-	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
-
 	/* Ignore interrupt if there's nothing in NIC to service.
 	 * This may be due to IRQ shared with another device,
 	 * or due to sporadic interrupts thrown from our NIC. */
@@ -1286,3 +1266,20 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return ret;
 }
+
+irqreturn_t iwl_pcie_isr(int irq, void *data)
+{
+	struct iwl_trans *trans = data;
+
+	if (!trans)
+		return IRQ_NONE;
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 * back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here.
+	 */
+	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
+
+	return iwl_pcie_isr_ict(trans);
+}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index d8ae0ad..af3ec74 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1608,11 +1608,11 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
 	err = compat_request_threaded_irq(&trans_pcie->irq_compat,
-					  pdev->irq, iwl_pcie_isr_ict,
+					  pdev->irq, iwl_pcie_isr,
 					  iwl_pcie_irq_handler,
 					  IRQF_SHARED, DRV_NAME, trans);
 #else
-	err = request_threaded_irq(pdev->irq, iwl_pcie_isr_ict,
+	err = request_threaded_irq(pdev->irq, iwl_pcie_isr,
 				   iwl_pcie_irq_handler,
 				   IRQF_SHARED, DRV_NAME, trans);
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 04/10] iwlwifi: pcie: move the ICT / non-ICT handling functions
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

The purpose of this is to be able to call these functions
from the interrupt handler and not from the upper half.

Change-Id: I0ee9a76ed7d2e396386024b487bfa965b7d0e59d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 324 ++++++++++++++++-----------------
 1 file changed, 162 insertions(+), 162 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 54a2f4a..7085cda 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,6 +807,168 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
+/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
+static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	u32 inta;
+
+	lockdep_assert_held(&trans_pcie->irq_lock);
+
+	trace_iwlwifi_dev_irq(trans->dev);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(trans, CSR_INT);
+
+	if (inta & (~trans_pcie->inta_mask)) {
+		IWL_DEBUG_ISR(trans,
+			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
+			      inta & (~trans_pcie->inta_mask));
+		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
+		inta &= trans_pcie->inta_mask;
+	}
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta) {
+		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+		/*
+		 * Re-enable interrupts here since we don't have anything to
+		 * service, but only in case the handler won't run. Note that
+		 * the handler can be scheduled because of a previous
+		 * interrupt.
+		 */
+		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
+		    !trans_pcie->inta)
+			iwl_enable_interrupts(trans);
+		return IRQ_NONE;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		return IRQ_HANDLED;
+	}
+
+	if (iwl_have_debug_level(IWL_DL_ISR))
+		IWL_DEBUG_ISR(trans,
+			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, trans_pcie->inta_mask,
+			      iwl_read32(trans, CSR_FH_INT_STATUS));
+
+	trans_pcie->inta |= inta;
+	/* the thread will service interrupts and re-enable them */
+	return IRQ_WAKE_THREAD;
+}
+
+/* a device (PCI-E) page is 4096 bytes long */
+#define ICT_SHIFT	12
+#define ICT_SIZE	(1 << ICT_SHIFT)
+#define ICT_COUNT	(ICT_SIZE / sizeof(u32))
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	unsigned long flags;
+	irqreturn_t ret;
+	u32 inta;
+	u32 val = 0;
+	u32 read;
+
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
+	/* dram interrupt table not set yet,
+	 * use legacy interrupt.
+	 */
+	if (unlikely(!trans_pcie->use_ict)) {
+		ret = iwl_pcie_isr_non_ict(trans);
+		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		return ret;
+	}
+
+	trace_iwlwifi_dev_irq(trans->dev);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
+	if (!read) {
+		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	/*
+	 * Collect all entries up to the first 0, starting from ict_index;
+	 * note we already read at ict_index.
+	 */
+	do {
+		val |= read;
+		IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
+				trans_pcie->ict_index, read);
+		trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
+		trans_pcie->ict_index =
+			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+
+		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
+					   read);
+	} while (read);
+
+	/* We should not get this value, just ignore it. */
+	if (val == 0xffffffff)
+		val = 0;
+
+	/*
+	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+	 * (bit 15 before shifting it to 31) to clear when using interrupt
+	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
+	 * so we use them to decide on the real state of the Rx bit.
+	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
+	 */
+	if (val & 0xC0000)
+		val |= 0x8000;
+
+	inta = (0xff & val) | ((0xff00 & val) << 16);
+	IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
+		      inta, trans_pcie->inta_mask, val);
+	if (iwl_have_debug_level(IWL_DL_ISR))
+		IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
+			      iwl_read32(trans, CSR_INT_MASK));
+
+	inta &= trans_pcie->inta_mask;
+	trans_pcie->inta |= inta;
+
+	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
+	if (likely(inta)) {
+		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		return IRQ_WAKE_THREAD;
+	}
+
+	ret = IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service.
+	 * only Re-enable if disabled by irq.
+	 */
+	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
+	    !trans_pcie->inta)
+		iwl_enable_interrupts(trans);
+
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	return ret;
+}
+
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 {
 	struct iwl_trans *trans = dev_id;
@@ -1019,11 +1181,6 @@ out:
  *
  ******************************************************************************/
 
-/* a device (PCI-E) page is 4096 bytes long */
-#define ICT_SHIFT	12
-#define ICT_SIZE	(1 << ICT_SHIFT)
-#define ICT_COUNT	(ICT_SIZE / sizeof(u32))
-
 /* Free dram table */
 void iwl_pcie_free_ict(struct iwl_trans *trans)
 {
@@ -1110,163 +1267,6 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans)
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
-/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 inta;
-
-	lockdep_assert_held(&trans_pcie->irq_lock);
-
-	trace_iwlwifi_dev_irq(trans->dev);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(trans, CSR_INT);
-
-	if (inta & (~trans_pcie->inta_mask)) {
-		IWL_DEBUG_ISR(trans,
-			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-			      inta & (~trans_pcie->inta_mask));
-		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
-		inta &= trans_pcie->inta_mask;
-	}
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		/*
-		 * Re-enable interrupts here since we don't have anything to
-		 * service, but only in case the handler won't run. Note that
-		 * the handler can be scheduled because of a previous
-		 * interrupt.
-		 */
-		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-		    !trans_pcie->inta)
-			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
-	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
-	}
-
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans,
-			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, trans_pcie->inta_mask,
-			      iwl_read32(trans, CSR_FH_INT_STATUS));
-
-	trans_pcie->inta |= inta;
-	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
-	irqreturn_t ret;
-	u32 inta;
-	u32 val = 0;
-	u32 read;
-
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
-	/* dram interrupt table not set yet,
-	 * use legacy interrupt.
-	 */
-	if (unlikely(!trans_pcie->use_ict)) {
-		ret = iwl_pcie_isr_non_ict(trans);
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
-	}
-
-	trace_iwlwifi_dev_irq(trans->dev);
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
-	if (!read) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		goto none;
-	}
-
-	/*
-	 * Collect all entries up to the first 0, starting from ict_index;
-	 * note we already read at ict_index.
-	 */
-	do {
-		val |= read;
-		IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
-				trans_pcie->ict_index, read);
-		trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
-		trans_pcie->ict_index =
-			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
-
-		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
-					   read);
-	} while (read);
-
-	/* We should not get this value, just ignore it. */
-	if (val == 0xffffffff)
-		val = 0;
-
-	/*
-	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
-	 * (bit 15 before shifting it to 31) to clear when using interrupt
-	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
-	 * so we use them to decide on the real state of the Rx bit.
-	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
-	 */
-	if (val & 0xC0000)
-		val |= 0x8000;
-
-	inta = (0xff & val) | ((0xff00 & val) << 16);
-	IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
-		      inta, trans_pcie->inta_mask, val);
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
-			      iwl_read32(trans, CSR_INT_MASK));
-
-	inta &= trans_pcie->inta_mask;
-	trans_pcie->inta |= inta;
-
-	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
-	if (likely(inta)) {
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return IRQ_WAKE_THREAD;
-	}
-
-	ret = IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service.
-	 * only Re-enable if disabled by irq.
-	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-	    !trans_pcie->inta)
-		iwl_enable_interrupts(trans);
-
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-	return ret;
-}
-
 irqreturn_t iwl_pcie_isr(int irq, void *data)
 {
 	struct iwl_trans *trans = data;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 04/10] iwlwifi: pcie: move the ICT / non-ICT handling functions
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

The purpose of this is to be able to call these functions
from the interrupt handler and not from the upper half.

Change-Id: I0ee9a76ed7d2e396386024b487bfa965b7d0e59d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 324 ++++++++++++++++-----------------
 1 file changed, 162 insertions(+), 162 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 54a2f4a..7085cda 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,6 +807,168 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
+/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
+static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	u32 inta;
+
+	lockdep_assert_held(&trans_pcie->irq_lock);
+
+	trace_iwlwifi_dev_irq(trans->dev);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(trans, CSR_INT);
+
+	if (inta & (~trans_pcie->inta_mask)) {
+		IWL_DEBUG_ISR(trans,
+			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
+			      inta & (~trans_pcie->inta_mask));
+		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
+		inta &= trans_pcie->inta_mask;
+	}
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta) {
+		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+		/*
+		 * Re-enable interrupts here since we don't have anything to
+		 * service, but only in case the handler won't run. Note that
+		 * the handler can be scheduled because of a previous
+		 * interrupt.
+		 */
+		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
+		    !trans_pcie->inta)
+			iwl_enable_interrupts(trans);
+		return IRQ_NONE;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		return IRQ_HANDLED;
+	}
+
+	if (iwl_have_debug_level(IWL_DL_ISR))
+		IWL_DEBUG_ISR(trans,
+			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, trans_pcie->inta_mask,
+			      iwl_read32(trans, CSR_FH_INT_STATUS));
+
+	trans_pcie->inta |= inta;
+	/* the thread will service interrupts and re-enable them */
+	return IRQ_WAKE_THREAD;
+}
+
+/* a device (PCI-E) page is 4096 bytes long */
+#define ICT_SHIFT	12
+#define ICT_SIZE	(1 << ICT_SHIFT)
+#define ICT_COUNT	(ICT_SIZE / sizeof(u32))
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	unsigned long flags;
+	irqreturn_t ret;
+	u32 inta;
+	u32 val = 0;
+	u32 read;
+
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
+	/* dram interrupt table not set yet,
+	 * use legacy interrupt.
+	 */
+	if (unlikely(!trans_pcie->use_ict)) {
+		ret = iwl_pcie_isr_non_ict(trans);
+		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		return ret;
+	}
+
+	trace_iwlwifi_dev_irq(trans->dev);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
+	if (!read) {
+		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	/*
+	 * Collect all entries up to the first 0, starting from ict_index;
+	 * note we already read at ict_index.
+	 */
+	do {
+		val |= read;
+		IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
+				trans_pcie->ict_index, read);
+		trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
+		trans_pcie->ict_index =
+			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+
+		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
+					   read);
+	} while (read);
+
+	/* We should not get this value, just ignore it. */
+	if (val == 0xffffffff)
+		val = 0;
+
+	/*
+	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+	 * (bit 15 before shifting it to 31) to clear when using interrupt
+	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
+	 * so we use them to decide on the real state of the Rx bit.
+	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
+	 */
+	if (val & 0xC0000)
+		val |= 0x8000;
+
+	inta = (0xff & val) | ((0xff00 & val) << 16);
+	IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
+		      inta, trans_pcie->inta_mask, val);
+	if (iwl_have_debug_level(IWL_DL_ISR))
+		IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
+			      iwl_read32(trans, CSR_INT_MASK));
+
+	inta &= trans_pcie->inta_mask;
+	trans_pcie->inta |= inta;
+
+	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
+	if (likely(inta)) {
+		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		return IRQ_WAKE_THREAD;
+	}
+
+	ret = IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service.
+	 * only Re-enable if disabled by irq.
+	 */
+	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
+	    !trans_pcie->inta)
+		iwl_enable_interrupts(trans);
+
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	return ret;
+}
+
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 {
 	struct iwl_trans *trans = dev_id;
@@ -1019,11 +1181,6 @@ out:
  *
  ******************************************************************************/
 
-/* a device (PCI-E) page is 4096 bytes long */
-#define ICT_SHIFT	12
-#define ICT_SIZE	(1 << ICT_SHIFT)
-#define ICT_COUNT	(ICT_SIZE / sizeof(u32))
-
 /* Free dram table */
 void iwl_pcie_free_ict(struct iwl_trans *trans)
 {
@@ -1110,163 +1267,6 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans)
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
-/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 inta;
-
-	lockdep_assert_held(&trans_pcie->irq_lock);
-
-	trace_iwlwifi_dev_irq(trans->dev);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(trans, CSR_INT);
-
-	if (inta & (~trans_pcie->inta_mask)) {
-		IWL_DEBUG_ISR(trans,
-			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-			      inta & (~trans_pcie->inta_mask));
-		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
-		inta &= trans_pcie->inta_mask;
-	}
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		/*
-		 * Re-enable interrupts here since we don't have anything to
-		 * service, but only in case the handler won't run. Note that
-		 * the handler can be scheduled because of a previous
-		 * interrupt.
-		 */
-		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-		    !trans_pcie->inta)
-			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
-	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
-	}
-
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans,
-			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, trans_pcie->inta_mask,
-			      iwl_read32(trans, CSR_FH_INT_STATUS));
-
-	trans_pcie->inta |= inta;
-	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
-	irqreturn_t ret;
-	u32 inta;
-	u32 val = 0;
-	u32 read;
-
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
-	/* dram interrupt table not set yet,
-	 * use legacy interrupt.
-	 */
-	if (unlikely(!trans_pcie->use_ict)) {
-		ret = iwl_pcie_isr_non_ict(trans);
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
-	}
-
-	trace_iwlwifi_dev_irq(trans->dev);
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
-	if (!read) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		goto none;
-	}
-
-	/*
-	 * Collect all entries up to the first 0, starting from ict_index;
-	 * note we already read at ict_index.
-	 */
-	do {
-		val |= read;
-		IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
-				trans_pcie->ict_index, read);
-		trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
-		trans_pcie->ict_index =
-			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
-
-		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
-					   read);
-	} while (read);
-
-	/* We should not get this value, just ignore it. */
-	if (val == 0xffffffff)
-		val = 0;
-
-	/*
-	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
-	 * (bit 15 before shifting it to 31) to clear when using interrupt
-	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
-	 * so we use them to decide on the real state of the Rx bit.
-	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
-	 */
-	if (val & 0xC0000)
-		val |= 0x8000;
-
-	inta = (0xff & val) | ((0xff00 & val) << 16);
-	IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
-		      inta, trans_pcie->inta_mask, val);
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
-			      iwl_read32(trans, CSR_INT_MASK));
-
-	inta &= trans_pcie->inta_mask;
-	trans_pcie->inta |= inta;
-
-	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
-	if (likely(inta)) {
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return IRQ_WAKE_THREAD;
-	}
-
-	ret = IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service.
-	 * only Re-enable if disabled by irq.
-	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-	    !trans_pcie->inta)
-		iwl_enable_interrupts(trans);
-
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-	return ret;
-}

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 05/10] iwlwifi: pcie: read the interrupt cause from the handler
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
                   ` (3 preceding siblings ...)
  2013-12-11  8:33   ` Emmanuel Grumbach
@ 2013-12-11  8:33 ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

We know disable the interrupts in the hardware from the
upper half and all the rest (including reading the interrupt
cause) is done in the handler.

Change-Id: Ib319a81a6ba124c1e1d22c115ed6f865b678d672
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 7085cda..5044fbd 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -879,20 +879,16 @@ static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
 static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
 	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
 	/* dram interrupt table not set yet,
 	 * use legacy interrupt.
 	 */
 	if (unlikely(!trans_pcie->use_ict)) {
 		ret = iwl_pcie_isr_non_ict(trans);
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 		return ret;
 	}
 
@@ -950,10 +946,8 @@ static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 	trans_pcie->inta |= inta;
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
-	if (likely(inta)) {
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	if (likely(inta))
 		return IRQ_WAKE_THREAD;
-	}
 
 	ret = IRQ_HANDLED;
 
@@ -965,7 +959,6 @@ static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return ret;
 }
 
@@ -977,12 +970,19 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 handled = 0;
 	unsigned long flags;
+	irqreturn_t ret;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
+	ret = iwl_pcie_isr_ict(trans);
+	if (ret != IRQ_WAKE_THREAD) {
+		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		return ret;
+	}
+
 	/* Ack/clear/reset pending uCode interrupts.
 	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
 	 */
@@ -1281,5 +1281,5 @@ irqreturn_t iwl_pcie_isr(int irq, void *data)
 	 */
 	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
 
-	return iwl_pcie_isr_ict(trans);
+	return IRQ_WAKE_THREAD;
 }
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 06/10] iwlwifi: pcie: determine the interrupt type in the handler
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

Instead of having:
iwl_pcie_irq_handler
	iwl_pcie_isr_ict
		iwl_pcie_isr_non_ict

we now have:

iwl_pcie_irq_handler:
	if (use_ict))
		iwl_pcie_int_cause_ict;
	else
		iwl_pcie_int_cause_non_ict;

This is much clearer.

Change-Id: Ieb99e8120c62749c06e3b2636aaf7ccbea8c72c5
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 5044fbd..58d3f64 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,8 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
+static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -876,7 +875,7 @@ static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
+static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	irqreturn_t ret;
@@ -884,14 +883,6 @@ static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 	u32 val = 0;
 	u32 read;
 
-	/* dram interrupt table not set yet,
-	 * use legacy interrupt.
-	 */
-	if (unlikely(!trans_pcie->use_ict)) {
-		ret = iwl_pcie_isr_non_ict(trans);
-		return ret;
-	}
-
 	trace_iwlwifi_dev_irq(trans->dev);
 
 	/* Ignore interrupt if there's nothing in NIC to service.
@@ -977,7 +968,14 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
-	ret = iwl_pcie_isr_ict(trans);
+	/* dram interrupt table not set yet,
+	 * use legacy interrupt.
+	 */
+	if (likely(trans_pcie->use_ict))
+		ret = iwl_pcie_int_cause_ict(trans);
+	else
+		ret = iwl_pcie_int_cause_non_ict(trans);
+
 	if (ret != IRQ_WAKE_THREAD) {
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 		return ret;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 06/10] iwlwifi: pcie: determine the interrupt type in the handler
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Emmanuel Grumbach

Instead of having:
iwl_pcie_irq_handler
	iwl_pcie_isr_ict
		iwl_pcie_isr_non_ict

we now have:

iwl_pcie_irq_handler:
	if (use_ict))
		iwl_pcie_int_cause_ict;
	else
		iwl_pcie_int_cause_non_ict;

This is much clearer.

Change-Id: Ieb99e8120c62749c06e3b2636aaf7ccbea8c72c5
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 5044fbd..58d3f64 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,8 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
+static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -876,7 +875,7 @@ static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
+static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	irqreturn_t ret;
@@ -884,14 +883,6 @@ static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
 	u32 val = 0;
 	u32 read;
 
-	/* dram interrupt table not set yet,
-	 * use legacy interrupt.
-	 */
-	if (unlikely(!trans_pcie->use_ict)) {
-		ret = iwl_pcie_isr_non_ict(trans);
-		return ret;
-	}

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 07/10] iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

These functions are meant to return an interrupt cause and
not an irqreturn_t.

The only drawback is that we will return IRQ_NONE instead
of IRQ_HANDLED when error occurs - but that shouldn't be
an issue.

Change-Id: I2de5c0d39fafb2a00429c314a2a5f0336347233d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 58d3f64..3ddf012 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,7 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -841,14 +841,14 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
 		    !trans_pcie->inta)
 			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
+		return trans_pcie->inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
+		return trans_pcie->inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -859,7 +859,7 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 
 	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
+	return trans_pcie->inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -875,10 +875,9 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
@@ -938,9 +937,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return IRQ_WAKE_THREAD;
-
-	ret = IRQ_HANDLED;
+		return trans_pcie->inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
@@ -950,7 +947,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	return ret;
+	return trans_pcie->inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -961,7 +958,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 handled = 0;
 	unsigned long flags;
-	irqreturn_t ret;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
@@ -972,13 +968,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * use legacy interrupt.
 	 */
 	if (likely(trans_pcie->use_ict))
-		ret = iwl_pcie_int_cause_ict(trans);
+		inta = iwl_pcie_int_cause_ict(trans);
 	else
-		ret = iwl_pcie_int_cause_non_ict(trans);
+		inta = iwl_pcie_int_cause_non_ict(trans);
 
-	if (ret != IRQ_WAKE_THREAD) {
+	if (!inta) {
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
+		return IRQ_NONE;
 	}
 
 	/* Ack/clear/reset pending uCode interrupts.
@@ -992,10 +988,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * hardware bugs here by ACKing all the possible interrupts so that
 	 * interrupt coalescing can still be achieved.
 	 */
-	iwl_write32(trans, CSR_INT,
-		    trans_pcie->inta | ~trans_pcie->inta_mask);
-
-	inta = trans_pcie->inta;
+	iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask);
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 07/10] iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

These functions are meant to return an interrupt cause and
not an irqreturn_t.

The only drawback is that we will return IRQ_NONE instead
of IRQ_HANDLED when error occurs - but that shouldn't be
an issue.

Change-Id: I2de5c0d39fafb2a00429c314a2a5f0336347233d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 58d3f64..3ddf012 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,7 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -841,14 +841,14 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
 		    !trans_pcie->inta)
 			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
+		return trans_pcie->inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
+		return trans_pcie->inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -859,7 +859,7 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 
 	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
+	return trans_pcie->inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -875,10 +875,9 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
@@ -938,9 +937,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return IRQ_WAKE_THREAD;
-
-	ret = IRQ_HANDLED;
+		return trans_pcie->inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
@@ -950,7 +947,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	return ret;
+	return trans_pcie->inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -961,7 +958,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 handled = 0;
 	unsigned long flags;
-	irqreturn_t ret;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
@@ -972,13 +968,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * use legacy interrupt.
 	 */
 	if (likely(trans_pcie->use_ict))
-		ret = iwl_pcie_int_cause_ict(trans);
+		inta = iwl_pcie_int_cause_ict(trans);
 	else
-		ret = iwl_pcie_int_cause_non_ict(trans);
+		inta = iwl_pcie_int_cause_non_ict(trans);
 
-	if (ret != IRQ_WAKE_THREAD) {
+	if (!inta) {
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
+		return IRQ_NONE;
 	}
 
 	/* Ack/clear/reset pending uCode interrupts.
@@ -992,10 +988,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * hardware bugs here by ACKing all the possible interrupts so that
 	 * interrupt coalescing can still be achieved.
 	 */
-	iwl_write32(trans, CSR_INT,
-		    trans_pcie->inta | ~trans_pcie->inta_mask);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 07/10] iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

These functions are meant to return an interrupt cause and
not an irqreturn_t.

The only drawback is that we will return IRQ_NONE instead
of IRQ_HANDLED when error occurs - but that shouldn't be
an issue.

Change-Id: I2de5c0d39fafb2a00429c314a2a5f0336347233d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 58d3f64..3ddf012 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,7 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -841,14 +841,14 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
 		    !trans_pcie->inta)
 			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
+		return trans_pcie->inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
+		return trans_pcie->inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -859,7 +859,7 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 
 	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
+	return trans_pcie->inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -875,10 +875,9 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
@@ -938,9 +937,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return IRQ_WAKE_THREAD;
-
-	ret = IRQ_HANDLED;
+		return trans_pcie->inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
@@ -950,7 +947,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	return ret;
+	return trans_pcie->inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -961,7 +958,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 handled = 0;
 	unsigned long flags;
-	irqreturn_t ret;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
@@ -972,13 +968,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * use legacy interrupt.
 	 */
 	if (likely(trans_pcie->use_ict))
-		ret = iwl_pcie_int_cause_ict(trans);
+		inta = iwl_pcie_int_cause_ict(trans);
 	else
-		ret = iwl_pcie_int_cause_non_ict(trans);
+		inta = iwl_pcie_int_cause_non_ict(trans);
 
-	if (ret != IRQ_WAKE_THREAD) {
+	if (!inta) {
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
+		return IRQ_NONE;
 	}
 
 	/* Ack/clear/reset pending uCode interrupts.
@@ -992,10 +988,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * hardware bugs here by ACKing all the possible interrupts so that
 	 * interrupt coalescing can still be achieved.
 	 */
-	iwl_write32(trans, CSR_INT,
-		    trans_pcie->inta | ~trans_pcie->inta_mask);
-
-	inta = trans_pcie->inta;
+	iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask);
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 07/10] iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

These functions are meant to return an interrupt cause and
not an irqreturn_t.

The only drawback is that we will return IRQ_NONE instead
of IRQ_HANDLED when error occurs - but that shouldn't be
an issue.

Change-Id: I2de5c0d39fafb2a00429c314a2a5f0336347233d
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 58d3f64..3ddf012 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -807,7 +807,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 	wake_up(&trans_pcie->wait_command_queue);
 }
 
-static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 inta;
@@ -841,14 +841,14 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
 		    !trans_pcie->inta)
 			iwl_enable_interrupts(trans);
-		return IRQ_NONE;
+		return trans_pcie->inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return IRQ_HANDLED;
+		return trans_pcie->inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -859,7 +859,7 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 
 	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return IRQ_WAKE_THREAD;
+	return trans_pcie->inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -875,10 +875,9 @@ static irqreturn_t iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
+static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	irqreturn_t ret;
 	u32 inta;
 	u32 val = 0;
 	u32 read;
@@ -938,9 +937,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return IRQ_WAKE_THREAD;
-
-	ret = IRQ_HANDLED;
+		return trans_pcie->inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
@@ -950,7 +947,7 @@ static irqreturn_t iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	return ret;
+	return trans_pcie->inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -961,7 +958,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	u32 inta = 0;
 	u32 handled = 0;
 	unsigned long flags;
-	irqreturn_t ret;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
@@ -972,13 +968,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * use legacy interrupt.
 	 */
 	if (likely(trans_pcie->use_ict))
-		ret = iwl_pcie_int_cause_ict(trans);
+		inta = iwl_pcie_int_cause_ict(trans);
 	else
-		ret = iwl_pcie_int_cause_non_ict(trans);
+		inta = iwl_pcie_int_cause_non_ict(trans);
 
-	if (ret != IRQ_WAKE_THREAD) {
+	if (!inta) {
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-		return ret;
+		return IRQ_NONE;
 	}
 
 	/* Ack/clear/reset pending uCode interrupts.
@@ -992,10 +988,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	 * hardware bugs here by ACKing all the possible interrupts so that
 	 * interrupt coalescing can still be achieved.
 	 */
-	iwl_write32(trans, CSR_INT,
-		    trans_pcie->inta | ~trans_pcie->inta_mask);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 08/10] iwlwifi: pcie: no need to save inta in trans_pcie
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  2013-12-11  8:33   ` Emmanuel Grumbach
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

This was useful when the handling was not in the same
context as the interrupt cause retrieval: we could have
several hard interrupts until the handler gets called.
Since we retrieve the interrupt cause in the handler itself,
there is no need to OR the interrupt causes.

Change-Id: I043ea25c4ba1add17d20d26da23148437114981c
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  1 -
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 21 +++++++--------------
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index c790df6..f959308 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -273,7 +273,6 @@ struct iwl_trans_pcie {
 	__le32 *ict_tbl;
 	dma_addr_t ict_tbl_dma;
 	int ict_index;
-	u32 inta;
 	bool use_ict;
 	struct isr_statistics isr_stats;
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 3ddf012..3f247da 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -838,17 +838,16 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		 * the handler can be scheduled because of a previous
 		 * interrupt.
 		 */
-		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-		    !trans_pcie->inta)
+		if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
 			iwl_enable_interrupts(trans);
-		return trans_pcie->inta;
+		return inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return trans_pcie->inta;
+		return inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -857,9 +856,8 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 			      inta, trans_pcie->inta_mask,
 			      iwl_read32(trans, CSR_FH_INT_STATUS));
 
-	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return trans_pcie->inta;
+	return inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -933,21 +931,19 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 			      iwl_read32(trans, CSR_INT_MASK));
 
 	inta &= trans_pcie->inta_mask;
-	trans_pcie->inta |= inta;
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return trans_pcie->inta;
+		return inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
 	 * only Re-enable if disabled by irq.
 	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-	    !trans_pcie->inta)
+	if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
 		iwl_enable_interrupts(trans);
 
-	return trans_pcie->inta;
+	return inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -994,9 +990,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
 			      inta, iwl_read32(trans, CSR_INT_MASK));
 
-	/* saved interrupt in inta variable now we can reset trans_pcie->inta */
-	trans_pcie->inta = 0;
-
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* Now service all interrupt bits discovered above. */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 08/10] iwlwifi: pcie: no need to save inta in trans_pcie
@ 2013-12-11  8:33   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

This was useful when the handling was not in the same
context as the interrupt cause retrieval: we could have
several hard interrupts until the handler gets called.
Since we retrieve the interrupt cause in the handler itself,
there is no need to OR the interrupt causes.

Change-Id: I043ea25c4ba1add17d20d26da23148437114981c
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  1 -
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 21 +++++++--------------
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index c790df6..f959308 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -273,7 +273,6 @@ struct iwl_trans_pcie {
 	__le32 *ict_tbl;
 	dma_addr_t ict_tbl_dma;
 	int ict_index;
-	u32 inta;
 	bool use_ict;
 	struct isr_statistics isr_stats;
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 3ddf012..3f247da 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -838,17 +838,16 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 		 * the handler can be scheduled because of a previous
 		 * interrupt.
 		 */
-		if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-		    !trans_pcie->inta)
+		if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
 			iwl_enable_interrupts(trans);
-		return trans_pcie->inta;
+		return inta;
 	}
 
 	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
 		/* Hardware disappeared. It might have already raised
 		 * an interrupt */
 		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return trans_pcie->inta;
+		return inta;
 	}
 
 	if (iwl_have_debug_level(IWL_DL_ISR))
@@ -857,9 +856,8 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 			      inta, trans_pcie->inta_mask,
 			      iwl_read32(trans, CSR_FH_INT_STATUS));
 
-	trans_pcie->inta |= inta;
 	/* the thread will service interrupts and re-enable them */
-	return trans_pcie->inta;
+	return inta;
 }
 
 /* a device (PCI-E) page is 4096 bytes long */
@@ -933,21 +931,19 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 			      iwl_read32(trans, CSR_INT_MASK));
 
 	inta &= trans_pcie->inta_mask;
-	trans_pcie->inta |= inta;
 
 	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
-		return trans_pcie->inta;
+		return inta;
 
  none:
 	/* re-enable interrupts here since we don't have anything to service.
 	 * only Re-enable if disabled by irq.
 	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->status) &&
-	    !trans_pcie->inta)
+	if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
 		iwl_enable_interrupts(trans);
 
-	return trans_pcie->inta;
+	return inta;
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
@@ -994,9 +990,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
 			      inta, iwl_read32(trans, CSR_INT_MASK));
 
-	/* saved interrupt in inta variable now we can reset trans_pcie->inta */
-	trans_pcie->inta = 0;

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 09/10] iwlwifi: pcie: move interrupt prints to the common handler
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
                   ` (8 preceding siblings ...)
  2013-12-11  8:33   ` Emmanuel Grumbach
@ 2013-12-11  8:33 ` Emmanuel Grumbach
  2013-12-11  8:33 ` [RFC 10/10] iwlwifi: pcie: stop using _irqsave Emmanuel Grumbach
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

Handling interrupt with no cause and printing logs doesn't
need to be ICT / non-ICT specific move this to the common
code.

Change-Id: I741894a8079faf0bf192a63ea5f40de5d08c433c
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 90 ++++++++++++----------------------
 1 file changed, 30 insertions(+), 60 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 3f247da..f25e6bb 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -819,43 +819,6 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
 	/* Discover which interrupts are active/pending */
 	inta = iwl_read32(trans, CSR_INT);
 
-	if (inta & (~trans_pcie->inta_mask)) {
-		IWL_DEBUG_ISR(trans,
-			      "We got a masked interrupt (0x%08x)...Ack and ignore\n",
-			      inta & (~trans_pcie->inta_mask));
-		iwl_write32(trans, CSR_INT, inta & (~trans_pcie->inta_mask));
-		inta &= trans_pcie->inta_mask;
-	}
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		/*
-		 * Re-enable interrupts here since we don't have anything to
-		 * service, but only in case the handler won't run. Note that
-		 * the handler can be scheduled because of a previous
-		 * interrupt.
-		 */
-		if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
-			iwl_enable_interrupts(trans);
-		return inta;
-	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		return inta;
-	}
-
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans,
-			      "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, trans_pcie->inta_mask,
-			      iwl_read32(trans, CSR_FH_INT_STATUS));
-
 	/* the thread will service interrupts and re-enable them */
 	return inta;
 }
@@ -887,10 +850,8 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 	 * or due to sporadic interrupts thrown from our NIC. */
 	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
 	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
-	if (!read) {
-		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-		goto none;
-	}
+	if (!read)
+		return 0;
 
 	/*
 	 * Collect all entries up to the first 0, starting from ict_index;
@@ -924,25 +885,6 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 		val |= 0x8000;
 
 	inta = (0xff & val) | ((0xff00 & val) << 16);
-	IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n",
-		      inta, trans_pcie->inta_mask, val);
-	if (iwl_have_debug_level(IWL_DL_ISR))
-		IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n",
-			      iwl_read32(trans, CSR_INT_MASK));
-
-	inta &= trans_pcie->inta_mask;
-
-	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
-	if (likely(inta))
-		return inta;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service.
-	 * only Re-enable if disabled by irq.
-	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->status) && !inta)
-		iwl_enable_interrupts(trans);
-
 	return inta;
 }
 
@@ -968,11 +910,39 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	else
 		inta = iwl_pcie_int_cause_non_ict(trans);
 
+	if (iwl_have_debug_level(IWL_DL_ISR)) {
+		IWL_DEBUG_ISR(trans,
+			      "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n",
+			      inta, trans_pcie->inta_mask,
+			      iwl_read32(trans, CSR_INT_MASK),
+			      iwl_read32(trans, CSR_FH_INT_STATUS));
+		if (inta & (~trans_pcie->inta_mask))
+			IWL_DEBUG_ISR(trans,
+				      "We got a masked interrupt (0x%08x)\n",
+				      inta & (~trans_pcie->inta_mask));
+	}
+
+	inta &= trans_pcie->inta_mask;
+
+	/*
+	 * Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC.\
+	 */
 	if (!inta) {
+		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+		/* Re-enable interrupts here since we don't have anything to service */
+		if (test_bit(STATUS_INT_ENABLED, &trans->status))
+			iwl_enable_interrupts(trans);
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 		return IRQ_NONE;
 	}
 
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised an interrupt */
+		IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+	}
+
 	/* Ack/clear/reset pending uCode interrupts.
 	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
 	 */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [RFC 10/10] iwlwifi: pcie: stop using _irqsave
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
                   ` (9 preceding siblings ...)
  2013-12-11  8:33 ` [RFC 09/10] iwlwifi: pcie: move interrupt prints to the common handler Emmanuel Grumbach
@ 2013-12-11  8:33 ` Emmanuel Grumbach
  2013-12-11 11:17 ` [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
  2013-12-15 15:48 ` Sebastian Andrzej Siewior
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  8:33 UTC (permalink / raw)
  To: linux-rt-users; +Cc: linux-wireless, Emmanuel Grumbach

Since we don't take any locks in the upper half any more,
we don't need _irqsave in any place.

Change-Id: I33b33edb063b3b55fb2a50bdb607e0b2ca8cde37
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/pcie/rx.c    | 76 ++++++++++++++-----------------
 drivers/net/wireless/iwlwifi/pcie/trans.c | 23 ++++------
 drivers/net/wireless/iwlwifi/pcie/tx.c    | 10 ++--
 3 files changed, 47 insertions(+), 62 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index f25e6bb..02b8747 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -148,10 +148,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
 static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
 				    struct iwl_rxq *rxq)
 {
-	unsigned long flags;
 	u32 reg;
 
-	spin_lock_irqsave(&rxq->lock, flags);
+	spin_lock(&rxq->lock);
 
 	if (rxq->need_update == 0)
 		goto exit_unlock;
@@ -190,7 +189,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
 	rxq->need_update = 0;
 
  exit_unlock:
-	spin_unlock_irqrestore(&rxq->lock, flags);
+	spin_unlock(&rxq->lock);
 }
 
 /*
@@ -209,7 +208,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	struct iwl_rx_mem_buffer *rxb;
-	unsigned long flags;
 
 	/*
 	 * If the device isn't enabled - not need to try to add buffers...
@@ -222,7 +220,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
 	if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
 		return;
 
-	spin_lock_irqsave(&rxq->lock, flags);
+	spin_lock(&rxq->lock);
 	while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) {
 		/* The overwritten rxb must be a used one */
 		rxb = rxq->queue[rxq->write];
@@ -239,7 +237,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
 		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
 		rxq->free_count--;
 	}
-	spin_unlock_irqrestore(&rxq->lock, flags);
+	spin_unlock(&rxq->lock);
 	/* If the pre-allocated buffer pool is dropping low, schedule to
 	 * refill it */
 	if (rxq->free_count <= RX_LOW_WATERMARK)
@@ -248,9 +246,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
 	/* If we've added more space for the firmware to place data, tell it.
 	 * Increment device's write pointer in multiples of 8. */
 	if (rxq->write_actual != (rxq->write & ~0x7)) {
-		spin_lock_irqsave(&rxq->lock, flags);
+		spin_lock(&rxq->lock);
 		rxq->need_update = 1;
-		spin_unlock_irqrestore(&rxq->lock, flags);
+		spin_unlock(&rxq->lock);
 		iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
 	}
 }
@@ -270,16 +268,15 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
 	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	struct iwl_rx_mem_buffer *rxb;
 	struct page *page;
-	unsigned long flags;
 	gfp_t gfp_mask = priority;
 
 	while (1) {
-		spin_lock_irqsave(&rxq->lock, flags);
+		spin_lock(&rxq->lock);
 		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
+			spin_unlock(&rxq->lock);
 			return;
 		}
-		spin_unlock_irqrestore(&rxq->lock, flags);
+		spin_unlock(&rxq->lock);
 
 		if (rxq->free_count > RX_LOW_WATERMARK)
 			gfp_mask |= __GFP_NOWARN;
@@ -308,17 +305,17 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
 			return;
 		}
 
-		spin_lock_irqsave(&rxq->lock, flags);
+		spin_lock(&rxq->lock);
 
 		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
+			spin_unlock(&rxq->lock);
 			__free_pages(page, trans_pcie->rx_page_order);
 			return;
 		}
 		rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer,
 				       list);
 		list_del(&rxb->list);
-		spin_unlock_irqrestore(&rxq->lock, flags);
+		spin_unlock(&rxq->lock);
 
 		BUG_ON(rxb->page);
 		rxb->page = page;
@@ -329,9 +326,9 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
 				     DMA_FROM_DEVICE);
 		if (dma_mapping_error(trans->dev, rxb->page_dma)) {
 			rxb->page = NULL;
-			spin_lock_irqsave(&rxq->lock, flags);
+			spin_lock(&rxq->lock);
 			list_add(&rxb->list, &rxq->rx_used);
-			spin_unlock_irqrestore(&rxq->lock, flags);
+			spin_unlock(&rxq->lock);
 			__free_pages(page, trans_pcie->rx_page_order);
 			return;
 		}
@@ -340,12 +337,12 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
 		/* and also 256 byte aligned! */
 		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
 
-		spin_lock_irqsave(&rxq->lock, flags);
+		spin_lock(&rxq->lock);
 
 		list_add_tail(&rxb->list, &rxq->rx_free);
 		rxq->free_count++;
 
-		spin_unlock_irqrestore(&rxq->lock, flags);
+		spin_unlock(&rxq->lock);
 	}
 }
 
@@ -379,13 +376,12 @@ 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);
-	unsigned long flags;
 
 	iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_pcie_rxq_restock(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 }
 
 static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
@@ -511,7 +507,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	int i, err;
-	unsigned long flags;
 
 	if (!rxq->bd) {
 		err = iwl_pcie_rx_alloc(trans);
@@ -519,7 +514,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
 			return err;
 	}
 
-	spin_lock_irqsave(&rxq->lock, flags);
+	spin_lock(&rxq->lock);
 
 	INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work);
 
@@ -535,16 +530,16 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
 	rxq->read = rxq->write = 0;
 	rxq->write_actual = 0;
 	memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
-	spin_unlock_irqrestore(&rxq->lock, flags);
+	spin_unlock(&rxq->lock);
 
 	iwl_pcie_rx_replenish(trans);
 
 	iwl_pcie_rx_hw_init(trans, rxq);
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	rxq->need_update = 1;
 	iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	return 0;
 }
@@ -553,7 +548,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_rxq *rxq = &trans_pcie->rxq;
-	unsigned long flags;
 
 	/*if rxq->bd is NULL, it means that nothing has been allocated,
 	 * exit now */
@@ -564,9 +558,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
 
 	cancel_work_sync(&trans_pcie->rx_replenish);
 
-	spin_lock_irqsave(&rxq->lock, flags);
+	spin_lock(&rxq->lock);
 	iwl_pcie_rxq_free_rbs(trans);
-	spin_unlock_irqrestore(&rxq->lock, flags);
+	spin_unlock(&rxq->lock);
 
 	dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
 			  rxq->bd, rxq->bd_dma);
@@ -589,7 +583,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
-	unsigned long flags;
 	bool page_stolen = false;
 	int max_len = PAGE_SIZE << trans_pcie->rx_page_order;
 	u32 offset = 0;
@@ -691,7 +684,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 	/* Reuse the page if possible. For notification packets and
 	 * SKBs that fail to Rx correctly, add them back into the
 	 * rx_free list for reuse later. */
-	spin_lock_irqsave(&rxq->lock, flags);
+	spin_lock(&rxq->lock);
 	if (rxb->page != NULL) {
 		rxb->page_dma =
 			dma_map_page(trans->dev, rxb->page, 0,
@@ -712,7 +705,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 		}
 	} else
 		list_add_tail(&rxb->list, &rxq->rx_used);
-	spin_unlock_irqrestore(&rxq->lock, flags);
+	spin_unlock(&rxq->lock);
 }
 
 /*
@@ -895,12 +888,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
 	u32 inta = 0;
 	u32 handled = 0;
-	unsigned long flags;
 	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 
 	/* dram interrupt table not set yet,
 	 * use legacy interrupt.
@@ -934,7 +926,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 		/* Re-enable interrupts here since we don't have anything to service */
 		if (test_bit(STATUS_INT_ENABLED, &trans->status))
 			iwl_enable_interrupts(trans);
-		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+		spin_unlock(&trans_pcie->irq_lock);
 		return IRQ_NONE;
 	}
 
@@ -960,7 +952,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n",
 			      inta, iwl_read32(trans, CSR_INT_MASK));
 
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	/* Now service all interrupt bits discovered above. */
 	if (inta & CSR_INT_BIT_HW_ERR) {
@@ -1185,12 +1177,11 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 val;
-	unsigned long flags;
 
 	if (!trans_pcie->ict_tbl)
 		return;
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_disable_interrupts(trans);
 
 	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
@@ -1207,18 +1198,17 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans)
 	trans_pcie->ict_index = 0;
 	iwl_write32(trans, CSR_INT, trans_pcie->inta_mask);
 	iwl_enable_interrupts(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 }
 
 /* Device is going down disable ict interrupt usage */
 void iwl_pcie_disable_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	trans_pcie->use_ict = false;
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 }
 
 irqreturn_t iwl_pcie_isr(int irq, void *data)
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index af3ec74..67ea0b1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -271,13 +271,12 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans)
 static int iwl_pcie_nic_init(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
 
 	/* nic_init */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_pcie_apm_init(trans);
 
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	iwl_pcie_set_pwr(trans, false);
 
@@ -635,13 +634,12 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
 	bool hw_rfkill;
 
 	/* tell the device to stop sending interrupts */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	/* device going down, Stop using ICT table */
 	iwl_pcie_disable_ict(trans);
@@ -673,9 +671,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	/* Upon stop, the APM issues an interrupt if HW RF kill is set.
 	 * Clean again the interrupt here
 	 */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	/* stop and reset the on-board processor */
 	iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
@@ -821,18 +819,17 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	unsigned long flags;
 
 	/* disable interrupts - don't enable HW RF kill interrupt */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	iwl_pcie_apm_stop(trans);
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	iwl_pcie_disable_ict(trans);
 }
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 049e474..127088e 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -742,10 +742,9 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ch, txq_id, ret;
-	unsigned long flags;
 
 	/* Turn off all Tx DMA fifos */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 
 	iwl_pcie_txq_set_sched(trans, 0);
 
@@ -762,7 +761,7 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
 				iwl_read_direct32(trans,
 						  FH_TSSR_TX_STATUS_REG));
 	}
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	if (!trans_pcie->txq) {
 		IWL_WARN(trans,
@@ -870,7 +869,6 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret;
 	int txq_id, slots_num;
-	unsigned long flags;
 	bool alloc = false;
 
 	if (!trans_pcie->txq) {
@@ -880,7 +878,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
 		alloc = true;
 	}
 
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	spin_lock(&trans_pcie->irq_lock);
 
 	/* Turn off all Tx DMA fifos */
 	iwl_write_prph(trans, SCD_TXFACT, 0);
@@ -889,7 +887,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
 	iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
 			   trans_pcie->kw.dma >> 4);
 
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+	spin_unlock(&trans_pcie->irq_lock);
 
 	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
 	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [RFC 03/10] iwlwifi: pcie: re-organize the PCIe ISR code
  2013-12-11  8:33 ` [RFC 03/10] iwlwifi: pcie: re-organize the PCIe ISR code Emmanuel Grumbach
@ 2013-12-11  9:49   ` Emmanuel Grumbach
  0 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11  9:49 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-rt-users, linux-wireless

On Wed, Dec 11, 2013 at 10:33 AM, Emmanuel Grumbach
<emmanuel.grumbach@intel.com> wrote:
>
> Separate the code that simply disables interrupt in the
> hardware and the code that checks what interrupt fired.
> This will be useful to move the second part in the threaded
> handler which will be done in a future patch.
>
> Change-Id: Iec42aa577c9de5c5a13a6030a1d8a69b4da37f43
> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> ---
>  drivers/net/wireless/iwlwifi/pcie/internal.h |  2 +-
>  drivers/net/wireless/iwlwifi/pcie/rx.c       | 49 +++++++++++++---------------
>  drivers/net/wireless/iwlwifi/pcie/trans.c    |  4 +--
>  3 files changed, 26 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
> index c9821ca..c790df6 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/internal.h
> +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
> @@ -346,7 +346,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans);
>  /*****************************************************
>  * ICT - interrupt handling
>  ******************************************************/
> -irqreturn_t iwl_pcie_isr_ict(int irq, void *data);
> +irqreturn_t iwl_pcie_isr(int irq, void *data);
>  int iwl_pcie_alloc_ict(struct iwl_trans *trans);
>  void iwl_pcie_free_ict(struct iwl_trans *trans);
>  void iwl_pcie_reset_ict(struct iwl_trans *trans);
> diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
> index 7e4836f..54a2f4a 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/rx.c
> +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
> @@ -1111,9 +1111,8 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans)
>  }
>
>  /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
> -static irqreturn_t iwl_pcie_isr(int irq, void *data)
> +static irqreturn_t iwl_pcie_isr_non_ict(struct iwl_trans *trans)
>  {
> -       struct iwl_trans *trans = data;
>         struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
>         u32 inta;
>
> @@ -1121,12 +1120,6 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
>
>         trace_iwlwifi_dev_irq(trans->dev);
>
> -       /* Disable (but don't clear!) interrupts here to avoid
> -        *    back-to-back ISRs and sporadic interrupts from our NIC.
> -        * If we have something to service, the irq thread will re-enable ints.
> -        * If we *don't* have something, we'll re-enable before leaving here. */
> -       iwl_write32(trans, CSR_INT_MASK, 0x00000000);
> -
>         /* Discover which interrupts are active/pending */
>         inta = iwl_read32(trans, CSR_INT);
>
> @@ -1181,20 +1174,14 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
>   * the interrupt we need to service, driver will set the entries back to 0 and
>   * set index.
>   */
> -irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
> +static irqreturn_t iwl_pcie_isr_ict(struct iwl_trans *trans)
>  {
> -       struct iwl_trans *trans = data;
> -       struct iwl_trans_pcie *trans_pcie;
> +       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
> +       unsigned long flags;
> +       irqreturn_t ret;
>         u32 inta;
>         u32 val = 0;
>         u32 read;
> -       unsigned long flags;
> -       irqreturn_t ret = IRQ_NONE;
> -
> -       if (!trans)
> -               return IRQ_NONE;
> -
> -       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
>
>         spin_lock_irqsave(&trans_pcie->irq_lock, flags);
>
> @@ -1202,20 +1189,13 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
>          * use legacy interrupt.
>          */
>         if (unlikely(!trans_pcie->use_ict)) {
> -               ret = iwl_pcie_isr(irq, data);
> +               ret = iwl_pcie_isr_non_ict(trans);
>                 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
>                 return ret;
>         }
>
>         trace_iwlwifi_dev_irq(trans->dev);
>
> -       /* Disable (but don't clear!) interrupts here to avoid
> -        * back-to-back ISRs and sporadic interrupts from our NIC.
> -        * If we have something to service, the tasklet will re-enable ints.
> -        * If we *don't* have something, we'll re-enable before leaving here.
> -        */
> -       iwl_write32(trans, CSR_INT_MASK, 0x00000000);
> -
>         /* Ignore interrupt if there's nothing in NIC to service.
>          * This may be due to IRQ shared with another device,
>          * or due to sporadic interrupts thrown from our NIC. */
> @@ -1286,3 +1266,20 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
>         spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
>         return ret;
>  }
> +
> +irqreturn_t iwl_pcie_isr(int irq, void *data)
> +{
> +       struct iwl_trans *trans = data;
> +
> +       if (!trans)
> +               return IRQ_NONE;
> +
> +       /* Disable (but don't clear!) interrupts here to avoid
> +        * back-to-back ISRs and sporadic interrupts from our NIC.
> +        * If we have something to service, the tasklet will re-enable ints.
> +        * If we *don't* have something, we'll re-enable before leaving here.
> +        */
> +       iwl_write32(trans, CSR_INT_MASK, 0x00000000);
> +
> +       return iwl_pcie_isr_ict(trans);
> +}
> diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
> index d8ae0ad..af3ec74 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/trans.c
> +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
> @@ -1608,11 +1608,11 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
>
>  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
>         err = compat_request_threaded_irq(&trans_pcie->irq_compat,
> -                                         pdev->irq, iwl_pcie_isr_ict,
> +                                         pdev->irq, iwl_pcie_isr,
>                                           iwl_pcie_irq_handler,
>                                           IRQF_SHARED, DRV_NAME, trans);
>  #else
> -       err = request_threaded_irq(pdev->irq, iwl_pcie_isr_ict,
> +       err = request_threaded_irq(pdev->irq, iwl_pcie_isr,
>                                    iwl_pcie_irq_handler,
>                                    IRQF_SHARED, DRV_NAME, trans);
>  #endif
> --

Oops - now you all know I work on a backport based tree ;)

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
                   ` (10 preceding siblings ...)
  2013-12-11  8:33 ` [RFC 10/10] iwlwifi: pcie: stop using _irqsave Emmanuel Grumbach
@ 2013-12-11 11:17 ` Emmanuel Grumbach
  2013-12-15 15:48 ` Sebastian Andrzej Siewior
  12 siblings, 0 replies; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-11 11:17 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-rt-users, linux-wireless

On Wed, Dec 11, 2013 at 10:33 AM, Emmanuel Grumbach
<emmanuel.grumbach@intel.com> wrote:
> RT folks have raised issues with iwlwifi wrt. RT kernel some time
> ago. Johannes had a few patches to address this, but I had a few
> concerns with them. This series tries to address the RT concerns:
> * we don't do anything in hard-irq context besides stopping the
>   interrupts in the device.
> * the interrupt cause is read from the irq handler and is handled
>   there.
>

Well - this was a bit unfair :)
The code I get is probably very similar (and inspired) from Johannes's
work. But I guess I was missing:
iwlwifi: pcie: track interrupt mask in SW.


> This allows us to avoid the usage of _irqsave all over the driver
> and also avoids any kind of locks in the hard-irq context.
> We still have some work to do with the locks in the handler.
> I believe the locking model can be improved there.
>
> This patch series is split is very small patches. While this can
> annoy the reader - it helped me much to make sure I don't do anything
> wrong (well - I am still not sure) - and IMHO, it makes the review easier.
> For example, in patch
>     iwlwifi: pcie: move the ICT / non-ICT handling functions
> I just copy code from place to place without changing a bit. This makes
> the significant diff smaller.
>
> Emmanuel Grumbach (10):
>   iwlwifi: pcie: clean up ICT allocation code
>   iwlwifi: pcie: track interrupt mask in SW
>   iwlwifi: pcie: re-organize the PCIe ISR code
>   iwlwifi: pcie: move the ICT / non-ICT handling functions
>   iwlwifi: pcie: read the interrupt cause from the handler
>   iwlwifi: pcie: determine the interrupt type in the handler
>   iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict
>   iwlwifi: pcie: no need to save inta in trans_pcie
>   iwlwifi: pcie: move interrupt prints to the common handler
>   iwlwifi: pcie: stop using _irqsave
>
>  drivers/net/wireless/iwlwifi/iwl-csr.h       |   3 +-
>  drivers/net/wireless/iwlwifi/pcie/internal.h |   9 +-
>  drivers/net/wireless/iwlwifi/pcie/rx.c       | 389 +++++++++++----------------
>  drivers/net/wireless/iwlwifi/pcie/trans.c    |  27 +-
>  drivers/net/wireless/iwlwifi/pcie/tx.c       |  10 +-
>  5 files changed, 185 insertions(+), 253 deletions(-)
>
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
                   ` (11 preceding siblings ...)
  2013-12-11 11:17 ` [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
@ 2013-12-15 15:48 ` Sebastian Andrzej Siewior
  2013-12-15 17:45   ` Emmanuel Grumbach
  12 siblings, 1 reply; 28+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-12-15 15:48 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-rt-users, linux-wireless

* Emmanuel Grumbach | 2013-12-11 10:33:35 [+0200]:

>RT folks have raised issues with iwlwifi wrt. RT kernel some time
>ago. Johannes had a few patches to address this, but I had a few
>concerns with them. This series tries to address the RT concerns:
>* we don't do anything in hard-irq context besides stopping the
>  interrupts in the device.
>* the interrupt cause is read from the irq handler and is handled
>  there.

Thanks for the patches. I haven't yet looked at them I doubt I manage it
anytime soon. Could you please answer one question: Do you grab any
locks in the primary interrupt handler?

Sebastian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-15 15:48 ` Sebastian Andrzej Siewior
@ 2013-12-15 17:45   ` Emmanuel Grumbach
  2013-12-15 17:46     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-15 17:45 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Emmanuel Grumbach
  Cc: linux-rt-users, linux-wireless



On 12/15/2013 05:48 PM, Sebastian Andrzej Siewior wrote:
> * Emmanuel Grumbach | 2013-12-11 10:33:35 [+0200]:
> 
>> RT folks have raised issues with iwlwifi wrt. RT kernel some time
>> ago. Johannes had a few patches to address this, but I had a few
>> concerns with them. This series tries to address the RT concerns:
>> * we don't do anything in hard-irq context besides stopping the
>>  interrupts in the device.
>> * the interrupt cause is read from the irq handler and is handled
>>  there.
> 
> Thanks for the patches. I haven't yet looked at them I doubt I manage it
> anytime soon. Could you please answer one question: Do you grab any
> locks in the primary interrupt handler?
> 
No we don't. The primary interrupt just tells the hardware to stop
firing interrupts and wakes up the thread as written above.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-15 17:45   ` Emmanuel Grumbach
@ 2013-12-15 17:46     ` Sebastian Andrzej Siewior
  2013-12-15 17:50       ` Emmanuel Grumbach
  0 siblings, 1 reply; 28+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-12-15 17:46 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: Emmanuel Grumbach, linux-rt-users, linux-wireless

On 12/15/2013 06:45 PM, Emmanuel Grumbach wrote:
> No we don't. The primary interrupt just tells the hardware to stop
> firing interrupts and wakes up the thread as written above.

Sounds great then.

Sebastian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-15 17:46     ` Sebastian Andrzej Siewior
@ 2013-12-15 17:50       ` Emmanuel Grumbach
  2013-12-17  9:21         ` Henrik Austad
  0 siblings, 1 reply; 28+ messages in thread
From: Emmanuel Grumbach @ 2013-12-15 17:50 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Emmanuel Grumbach, linux-rt-users, linux-wireless



On 12/15/2013 07:46 PM, Sebastian Andrzej Siewior wrote:
> On 12/15/2013 06:45 PM, Emmanuel Grumbach wrote:
>> No we don't. The primary interrupt just tells the hardware to stop
>> firing interrupts and wakes up the thread as written above.
> 
> Sounds great then.
> 

Ok - I guess I'll submit then internally then before we send them upstream.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-15 17:50       ` Emmanuel Grumbach
@ 2013-12-17  9:21         ` Henrik Austad
  2013-12-17  9:32           ` Grumbach, Emmanuel
  0 siblings, 1 reply; 28+ messages in thread
From: Henrik Austad @ 2013-12-17  9:21 UTC (permalink / raw)
  To: Emmanuel Grumbach
  Cc: Sebastian Andrzej Siewior, Emmanuel Grumbach, linux-rt-users,
	linux-wireless

[-- Attachment #1: Type: text/plain, Size: 909 bytes --]

On Sun, Dec 15, 2013 at 07:50:23PM +0200, Emmanuel Grumbach wrote:
> 
> 
> On 12/15/2013 07:46 PM, Sebastian Andrzej Siewior wrote:
> > On 12/15/2013 06:45 PM, Emmanuel Grumbach wrote:
> >> No we don't. The primary interrupt just tells the hardware to stop
> >> firing interrupts and wakes up the thread as written above.
> > 
> > Sounds great then.
> > 
> 
> Ok - I guess I'll submit then internally then before we send them upstream.

I'm trying to mash this on top of 3.12.5 for the latest rt-release, and 
especially drivers/net/wireless/iwlwifi/pcie/rx.c is not particularly 
compatible with your patches, especially iwl_pcie_int_cause_non_ict(), 
which as been moved, renamed and given new return values.

Especially 07 is giving me some headaches, and instead of me making a 
massive trainwreck of it all, would you mind moving this closer to 3.12?

Thanks!

-- 
Henrik Austad

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [RFC 00/10] make iwlwifi RT friendly
  2013-12-17  9:21         ` Henrik Austad
@ 2013-12-17  9:32           ` Grumbach, Emmanuel
  2013-12-17  9:43             ` Henrik Austad
  0 siblings, 1 reply; 28+ messages in thread
From: Grumbach, Emmanuel @ 2013-12-17  9:32 UTC (permalink / raw)
  To: Henrik Austad, Emmanuel Grumbach
  Cc: Sebastian Andrzej Siewior, linux-rt-users, linux-wireless

> 
> On Sun, Dec 15, 2013 at 07:50:23PM +0200, Emmanuel Grumbach wrote:
> >
> >
> > On 12/15/2013 07:46 PM, Sebastian Andrzej Siewior wrote:
> > > On 12/15/2013 06:45 PM, Emmanuel Grumbach wrote:
> > >> No we don't. The primary interrupt just tells the hardware to stop
> > >> firing interrupts and wakes up the thread as written above.
> > >
> > > Sounds great then.
> > >
> >
> > Ok - I guess I'll submit then internally then before we send them upstream.
> 
> I'm trying to mash this on top of 3.12.5 for the latest rt-release, and especially
> drivers/net/wireless/iwlwifi/pcie/rx.c is not particularly compatible with your
> patches, especially iwl_pcie_int_cause_non_ict(), which as been moved,
> renamed and given new return values.

iwl_pcie_int_cause_non_ict didn't exist before my patch. I am not sure I follow here...
I am not sure I'll have the time to fulfill your request, but I'll try.

> 
> Especially 07 is giving me some headaches, and instead of me making a
> massive trainwreck of it all, would you mind moving this closer to 3.12?
> 
> Thanks!
> 
> --
> Henrik Austad

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [RFC 00/10] make iwlwifi RT friendly
  2013-12-17  9:32           ` Grumbach, Emmanuel
@ 2013-12-17  9:43             ` Henrik Austad
  0 siblings, 0 replies; 28+ messages in thread
From: Henrik Austad @ 2013-12-17  9:43 UTC (permalink / raw)
  To: Grumbach, Emmanuel
  Cc: Emmanuel Grumbach, Sebastian Andrzej Siewior, linux-rt-users,
	linux-wireless

[-- Attachment #1: Type: text/plain, Size: 1410 bytes --]

On Tue, Dec 17, 2013 at 09:32:14AM +0000, Grumbach, Emmanuel wrote:
> > 
> > On Sun, Dec 15, 2013 at 07:50:23PM +0200, Emmanuel Grumbach wrote:
> > >
> > >
> > > On 12/15/2013 07:46 PM, Sebastian Andrzej Siewior wrote:
> > > > On 12/15/2013 06:45 PM, Emmanuel Grumbach wrote:
> > > >> No we don't. The primary interrupt just tells the hardware to stop
> > > >> firing interrupts and wakes up the thread as written above.
> > > >
> > > > Sounds great then.
> > > >
> > >
> > > Ok - I guess I'll submit then internally then before we send them upstream.
> > 
> > I'm trying to mash this on top of 3.12.5 for the latest rt-release, and especially
> > drivers/net/wireless/iwlwifi/pcie/rx.c is not particularly compatible with your
> > patches, especially iwl_pcie_int_cause_non_ict(), which as been moved,
> > renamed and given new return values.
> 
> iwl_pcie_int_cause_non_ict didn't exist before my patch. I am not sure I follow here...

bah, git is messing with my head, iwl_pcie_is_non_ict() used a lot of the 
same code as iwl_pcie_isr(), so I mistakenly saw it as a rename (which got 
me a bit confused). Looking closer and applying enough braincells to form a 
synapse, I see that it has just moved further down.

> I am not sure I'll have the time to fulfill your request, but I'll try.

Fair enough, I'll give the rt-port of the patches another go :)

-- 
Henrik Austad

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2013-12-17  9:44 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-11  8:33 [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 01/10] iwlwifi: pcie: clean up ICT allocation code Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 02/10] iwlwifi: pcie: track interrupt mask in SW Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 03/10] iwlwifi: pcie: re-organize the PCIe ISR code Emmanuel Grumbach
2013-12-11  9:49   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 04/10] iwlwifi: pcie: move the ICT / non-ICT handling functions Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 05/10] iwlwifi: pcie: read the interrupt cause from the handler Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 06/10] iwlwifi: pcie: determine the interrupt type in " Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 07/10] iwlwifi: pcie: return inta from iwl_pcie_int_cause_{non_}ict Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 08/10] iwlwifi: pcie: no need to save inta in trans_pcie Emmanuel Grumbach
2013-12-11  8:33   ` Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 09/10] iwlwifi: pcie: move interrupt prints to the common handler Emmanuel Grumbach
2013-12-11  8:33 ` [RFC 10/10] iwlwifi: pcie: stop using _irqsave Emmanuel Grumbach
2013-12-11 11:17 ` [RFC 00/10] make iwlwifi RT friendly Emmanuel Grumbach
2013-12-15 15:48 ` Sebastian Andrzej Siewior
2013-12-15 17:45   ` Emmanuel Grumbach
2013-12-15 17:46     ` Sebastian Andrzej Siewior
2013-12-15 17:50       ` Emmanuel Grumbach
2013-12-17  9:21         ` Henrik Austad
2013-12-17  9:32           ` Grumbach, Emmanuel
2013-12-17  9:43             ` Henrik Austad

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.