[PATCH] Clean up DXE's IRQ handling

Pontus Fuchs pontus.fuchs at gmail.com
Thu Apr 18 05:08:15 EDT 2013


From: Pontus Fuchs <pontus2.fuchs at sonymobile.com>

Free irq's on shutdown
Check for errors
Refactor and move irq allocation to dxe_init
---
 dxe.c  |  256 +++++++++++++++++++++++++++++++++++-----------------------------
 dxe.h  |    2 +-
 main.c |    2 +-
 3 files changed, 142 insertions(+), 118 deletions(-)

diff --git a/dxe.c b/dxe.c
index 4033eb8..daf25b2 100644
--- a/dxe.c
+++ b/dxe.c
@@ -209,115 +209,6 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *
 	}
 	return 0;
 }
-int wcn36xx_dxe_init(struct wcn36xx *wcn)
-{
-	int reg_data = 0;
-
-	reg_data = WCN36XX_DXE_REG_RESET;
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
-
-	// Setting interrupt path
-	reg_data = WCN36XX_DXE_CCU_INT;
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
-
-	/***************************************/
-	/* Init descriptors for TX LOW channel */
-	/***************************************/
-	wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
-
-	// Write chanel head to a NEXT register
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
-		wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);
-
-	// Program DMA destination addr for TX LOW
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_DEST_ADDR_TX_L,
-		WCN36XX_DXE_WQ_TX_L);
-
-	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
-	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
-
-	/***************************************/
-	/* Init descriptors for TX HIGH channel */
-	/***************************************/
-	wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
-
-	// Write chanel head to a NEXT register
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
-		wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);
-
-	// Program DMA destination addr for TX HIGH
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_DEST_ADDR_TX_H,
-		WCN36XX_DXE_WQ_TX_H);
-
-	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
-	// Enable channel interrupts
-	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
-
-	/***************************************/
-	/* Init descriptors for RX LOW channel */
-	/***************************************/
-	wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);
-
-	// For RX we need to prealocat buffers
-	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
-
-	// Write chanel head to a NEXT register
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
-		wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);
-
-	// Write DMA source address
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_SRC_ADDR_RX_L,
-		WCN36XX_DXE_WQ_RX_L);
-
-	// Program preallocated destionatio Address
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_DEST_ADDR_RX_L,
-		wcn->dxe_rx_l_ch.head_blk_ctl->desc->desc.phy_next_l);
-
-
-	// Enable default control registers
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_REG_CTL_RX_L,
-		WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
-
-	// Enable channel interrupts
-	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
-
-	/***************************************/
-	/* Init descriptors for RX HIGH channel */
-	/***************************************/
-	wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);
-
-	// For RX we need to prealocat buffers
-	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
-
-	// Write chanel head to a NEXT register
-	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
-		wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);
-
-	// Write DMA source address
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_SRC_ADDR_RX_H,
-		WCN36XX_DXE_WQ_RX_H);
-
-	// Program preallocated destionatio Address
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_CH_DEST_ADDR_RX_H,
-		 wcn->dxe_rx_h_ch.head_blk_ctl->desc->desc.phy_next_l);
-
-	// Enable default control registers
-	wcn36xx_dxe_write_register(wcn,
-		WCN36XX_DXE_REG_CTL_RX_H,
-		WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
-
-	// Enable channel interrupts
-	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
-
-	return 0;
-}
 
 static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
 {
@@ -333,19 +224,25 @@ static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev)
 	queue_work(wcn->ctl_wq, &wcn->rx_ready_work);
 	return IRQ_HANDLED;
 }
-int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) {
+static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn)
+{
+	int ret;
 
 	ENTER();
 	// Register TX complete irq
-	if (request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, IRQF_TRIGGER_HIGH,
-                           "wcnss_wlan", wcn)) {
-		return -EIO;
+	ret =request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, IRQF_TRIGGER_HIGH,
+                           "wcn36xx_tx", wcn);
+	if (ret) {
+		wcn36xx_error("failed to alloc tx irq");
+		goto out_err;
 	}
 
 	// Register RX irq
-	if (request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH,
-                           "wcnss_wlan", wcn)){
-		return -EIO;
+	ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH,
+                           "wcn36xx_rx", wcn);
+	if (ret) {
+		wcn36xx_error("failed to alloc rx irq");
+		goto out_txirq;
 	}
 	// disable tx irq, not supported
 	disable_irq_nosync(wcn->tx_irq);
@@ -353,6 +250,12 @@ int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) {
 	// enable rx irq
 	enable_irq_wake(wcn->rx_irq);
 	return 0;
+
+out_txirq:
+	free_irq(wcn->tx_irq, wcn);
+out_err:
+	return -ret;
+
 }
 void wcn36xx_rx_ready_work(struct work_struct *work)
 {
@@ -464,3 +367,124 @@ int wcn36xx_dxe_tx(struct wcn36xx *wcn, struct sk_buff *skb, u8 broadcast)
 		WCN36XX_DXE_CH_DEFAULT_CTL_TX_H);
 	return 0;
 }
+int wcn36xx_dxe_init(struct wcn36xx *wcn)
+{
+	int reg_data = 0, ret;
+
+	reg_data = WCN36XX_DXE_REG_RESET;
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
+
+	// Setting interrupt path
+	reg_data = WCN36XX_DXE_CCU_INT;
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
+
+	/***************************************/
+	/* Init descriptors for TX LOW channel */
+	/***************************************/
+	wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
+
+	// Write chanel head to a NEXT register
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
+		wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);
+
+	// Program DMA destination addr for TX LOW
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_DEST_ADDR_TX_L,
+		WCN36XX_DXE_WQ_TX_L);
+
+	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
+	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
+
+	/***************************************/
+	/* Init descriptors for TX HIGH channel */
+	/***************************************/
+	wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
+
+	// Write chanel head to a NEXT register
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
+		wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);
+
+	// Program DMA destination addr for TX HIGH
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_DEST_ADDR_TX_H,
+		WCN36XX_DXE_WQ_TX_H);
+
+	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
+	// Enable channel interrupts
+	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
+
+	/***************************************/
+	/* Init descriptors for RX LOW channel */
+	/***************************************/
+	wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);
+
+	// For RX we need to prealocat buffers
+	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
+
+	// Write chanel head to a NEXT register
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
+		wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);
+
+	// Write DMA source address
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_SRC_ADDR_RX_L,
+		WCN36XX_DXE_WQ_RX_L);
+
+	// Program preallocated destionatio Address
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_DEST_ADDR_RX_L,
+		wcn->dxe_rx_l_ch.head_blk_ctl->desc->desc.phy_next_l);
+
+
+	// Enable default control registers
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_REG_CTL_RX_L,
+		WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
+
+	// Enable channel interrupts
+	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
+
+	/***************************************/
+	/* Init descriptors for RX HIGH channel */
+	/***************************************/
+	wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);
+
+	// For RX we need to prealocat buffers
+	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
+
+	// Write chanel head to a NEXT register
+	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
+		wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);
+
+	// Write DMA source address
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_SRC_ADDR_RX_H,
+		WCN36XX_DXE_WQ_RX_H);
+
+	// Program preallocated destionatio Address
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_CH_DEST_ADDR_RX_H,
+		 wcn->dxe_rx_h_ch.head_blk_ctl->desc->desc.phy_next_l);
+
+	// Enable default control registers
+	wcn36xx_dxe_write_register(wcn,
+		WCN36XX_DXE_REG_CTL_RX_H,
+		WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
+
+	// Enable channel interrupts
+	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
+
+	ret = wcn36xx_dxe_request_irqs(wcn);
+	if (ret < 0)
+		goto out_err;
+	return 0;
+
+out_err:
+	return ret;
+}
+
+void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
+{
+	free_irq(wcn->tx_irq, wcn);
+	free_irq(wcn->rx_irq, wcn);
+}
diff --git a/dxe.h b/dxe.h
index b16d48c..a8c0638 100644
--- a/dxe.h
+++ b/dxe.h
@@ -209,7 +209,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn);
 void wcn36xx_rx_ready_work(struct work_struct *work);
 int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn);
 int wcn36xx_dxe_init(struct wcn36xx *wcn);
+void wcn36xx_dxe_deinit(struct wcn36xx *wcn);
 int wcn36xx_dxe_init_channels(struct wcn36xx *wcn);
-int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn);
 int wcn36xx_dxe_tx(struct wcn36xx *wcn, struct sk_buff *skb, u8 broadcast);
 #endif	/* _DXE_H_ */
diff --git a/main.c b/main.c
index 156e97e..0eb675a 100644
--- a/main.c
+++ b/main.c
@@ -67,7 +67,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
 
 	// DMA chanel initialization
 	wcn36xx_dxe_init(wcn);
-	wcn36xx_dxe_request_irqs(wcn);
 
 	return 0;
 }
@@ -77,6 +76,7 @@ static void wcn36xx_stop(struct ieee80211_hw *hw)
 
 	ENTER();
 
+	wcn36xx_dxe_deinit(wcn);
 	wcn36xx_smd_close(wcn);
 
 	kfree(wcn->smd_buf);
-- 
1.7.10.4




More information about the wcn36xx mailing list