[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, ®_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, ®_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, ®_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, ®_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