diff options
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/debug.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.c | 69 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.h | 221 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 115 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/txrx.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 |
7 files changed, 337 insertions, 121 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c index 2a6bb62e785c..389b5e7129a6 100644 --- a/drivers/net/wireless/ath/wcn36xx/debug.c +++ b/drivers/net/wireless/ath/wcn36xx/debug.c @@ -161,9 +161,8 @@ void wcn36xx_debugfs_init(struct wcn36xx *wcn) dfs->rootdir = NULL; } - ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR, - &fops_wcn36xx_bmps, wcn); - ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn); + ADD_FILE(bmps_switcher, 0600, &fops_wcn36xx_bmps, wcn); + ADD_FILE(dump, 0200, &fops_wcn36xx_dump, wcn); } void wcn36xx_debugfs_exit(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index a3f1f7d042a4..2c3b899a88fa 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -27,15 +27,6 @@ #include "wcn36xx.h" #include "txrx.h" -void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low) -{ - struct wcn36xx_dxe_ch *ch = is_low ? - &wcn->dxe_tx_l_ch : - &wcn->dxe_tx_h_ch; - - return ch->head_blk_ctl->bd_cpu_addr; -} - static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data) { wcn36xx_dbg(WCN36XX_DBG_DXE, @@ -376,7 +367,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) spin_lock_irqsave(&ch->lock, flags); ctl = ch->tail_blk_ctl; do { - if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) + if (ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD) break; if (ctl->skb) { dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, @@ -397,7 +388,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) } ctl = ctl->next; } while (ctl != ch->head_blk_ctl && - !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); + !(ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD)); ch->tail_blk_ctl = ctl; spin_unlock_irqrestore(&ch->lock, flags); @@ -415,14 +406,31 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, &int_reason); - /* TODO: Check int_reason */ - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, WCN36XX_INT_MASK_CHAN_TX_H); - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, - WCN36XX_INT_MASK_CHAN_TX_H); + if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ERR_CLR, + WCN36XX_INT_MASK_CHAN_TX_H); + + wcn36xx_err("DXE IRQ reported error: 0x%x in high TX channel\n", + int_src); + } + + if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_DONE_CLR, + WCN36XX_INT_MASK_CHAN_TX_H); + } + + if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ED_CLR, + WCN36XX_INT_MASK_CHAN_TX_H); + } + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); } @@ -431,14 +439,33 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, &int_reason); - /* TODO: Check int_reason */ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, WCN36XX_INT_MASK_CHAN_TX_L); - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, - WCN36XX_INT_MASK_CHAN_TX_L); + + if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ERR_CLR, + WCN36XX_INT_MASK_CHAN_TX_L); + + wcn36xx_err("DXE IRQ reported error: 0x%x in low TX channel\n", + int_src); + } + + if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_DONE_CLR, + WCN36XX_INT_MASK_CHAN_TX_L); + } + + if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ED_CLR, + WCN36XX_INT_MASK_CHAN_TX_L); + } + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); } @@ -503,7 +530,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, int_mask = WCN36XX_DXE_INT_CH3_MASK; } - while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { + while (!(dxe->ctrl & WCN36xx_DXE_CTRL_VLD)) { skb = ctl->skb; dma_addr = dxe->dst_addr_l; ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl); @@ -612,6 +639,7 @@ void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct wcn36xx_vif *vif_priv, + struct wcn36xx_tx_bd *bd, struct sk_buff *skb, bool is_low) { @@ -645,6 +673,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, ctl->skb = NULL; desc = ctl->desc; + /* write buffer descriptor */ + memcpy(ctl->bd_cpu_addr, bd, sizeof(*bd)); + /* Set source address of the BD we send */ desc->src_addr_l = ctl->bd_phy_addr; diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index c012e807753b..ce580960d109 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -33,15 +33,106 @@ H2H_TEST_RX_TX = DMA2 #define WCN36XX_CCU_DXE_INT_SELECT_RIVA 0x310 #define WCN36XX_CCU_DXE_INT_SELECT_PRONTO 0x10dc -/* TODO This must calculated properly but not hardcoded */ -#define WCN36XX_DXE_CTRL_TX_L 0x328a44 -#define WCN36XX_DXE_CTRL_TX_H 0x32ce44 -#define WCN36XX_DXE_CTRL_RX_L 0x12ad2f -#define WCN36XX_DXE_CTRL_RX_H 0x12d12f -#define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 -#define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d -#define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 -#define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d +/* Descriptor valid */ +#define WCN36xx_DXE_CTRL_VLD BIT(0) +/* End of packet */ +#define WCN36xx_DXE_CTRL_EOP BIT(3) +/* BD handling bit */ +#define WCN36xx_DXE_CTRL_BDH BIT(4) +/* Source is a queue */ +#define WCN36xx_DXE_CTRL_SIQ BIT(5) +/* Destination is a queue */ +#define WCN36xx_DXE_CTRL_DIQ BIT(6) +/* Pointer address is a queue */ +#define WCN36xx_DXE_CTRL_PIQ BIT(7) +/* Release PDU when done */ +#define WCN36xx_DXE_CTRL_PDU_REL BIT(8) +/* STOP channel processing */ +#define WCN36xx_DXE_CTRL_STOP BIT(16) +/* INT on descriptor done */ +#define WCN36xx_DXE_CTRL_INT BIT(17) +/* Endian byte swap enable */ +#define WCN36xx_DXE_CTRL_SWAP BIT(20) +/* Master endianness */ +#define WCN36xx_DXE_CTRL_ENDIANNESS BIT(21) + +/* Transfer type */ +#define WCN36xx_DXE_CTRL_XTYPE_SHIFT 1 +#define WCN36xx_DXE_CTRL_XTYPE_MASK GENMASK(2, WCN36xx_DXE_CTRL_XTYPE_SHIFT) +#define WCN36xx_DXE_CTRL_XTYPE_SET(x) ((x) << WCN36xx_DXE_CTRL_XTYPE_SHIFT) + +/* BMU Threshold select */ +#define WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT 9 +#define WCN36xx_DXE_CTRL_BTHLD_SEL_MASK GENMASK(12, WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT) +#define WCN36xx_DXE_CTRL_BTHLD_SEL_SET(x) ((x) << WCN36xx_DXE_CTRL_BTHLD_SEL_SHIFT) + +/* Priority */ +#define WCN36xx_DXE_CTRL_PRIO_SHIFT 13 +#define WCN36xx_DXE_CTRL_PRIO_MASK GENMASK(15, WCN36xx_DXE_CTRL_PRIO_SHIFT) +#define WCN36xx_DXE_CTRL_PRIO_SET(x) ((x) << WCN36xx_DXE_CTRL_PRIO_SHIFT) + +/* BD Template index */ +#define WCN36xx_DXE_CTRL_BDT_IDX_SHIFT 18 +#define WCN36xx_DXE_CTRL_BDT_IDX_MASK GENMASK(19, WCN36xx_DXE_CTRL_BDT_IDX_SHIFT) +#define WCN36xx_DXE_CTRL_BDT_IDX_SET(x) ((x) << WCN36xx_DXE_CTRL_BDT_IDX_SHIFT) + +/* Transfer types: */ +/* Host to host */ +#define WCN36xx_DXE_XTYPE_H2H (0) +/* Host to BMU */ +#define WCN36xx_DXE_XTYPE_H2B (2) +/* BMU to host */ +#define WCN36xx_DXE_XTYPE_B2H (3) + +#define WCN36XX_DXE_CTRL_TX_L (WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | \ + WCN36xx_DXE_CTRL_PRIO_SET(4) | WCN36xx_DXE_CTRL_INT | \ + WCN36xx_DXE_CTRL_SWAP | WCN36xx_DXE_CTRL_ENDIANNESS) + +#define WCN36XX_DXE_CTRL_TX_H (WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | \ + WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_INT | \ + WCN36xx_DXE_CTRL_SWAP | WCN36xx_DXE_CTRL_ENDIANNESS) + +#define WCN36XX_DXE_CTRL_RX_L (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ + WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_SIQ | \ + WCN36xx_DXE_CTRL_PDU_REL | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(6) | \ + WCN36xx_DXE_CTRL_PRIO_SET(5) | WCN36xx_DXE_CTRL_INT | \ + WCN36xx_DXE_CTRL_SWAP) + +#define WCN36XX_DXE_CTRL_RX_H (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ + WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_SIQ | \ + WCN36xx_DXE_CTRL_PDU_REL | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(8) | \ + WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_INT | \ + WCN36xx_DXE_CTRL_SWAP) + +#define WCN36XX_DXE_CTRL_TX_H_BD (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | \ + WCN36xx_DXE_CTRL_PRIO_SET(6) | WCN36xx_DXE_CTRL_SWAP | \ + WCN36xx_DXE_CTRL_ENDIANNESS) + +#define WCN36XX_DXE_CTRL_TX_H_SKB (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_DIQ | \ + WCN36xx_DXE_CTRL_BTHLD_SEL_SET(7) | WCN36xx_DXE_CTRL_PRIO_SET(6) | \ + WCN36xx_DXE_CTRL_INT | WCN36xx_DXE_CTRL_SWAP | \ + WCN36xx_DXE_CTRL_ENDIANNESS) + +#define WCN36XX_DXE_CTRL_TX_L_BD (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_DIQ | WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | \ + WCN36xx_DXE_CTRL_PRIO_SET(4) | WCN36xx_DXE_CTRL_SWAP | \ + WCN36xx_DXE_CTRL_ENDIANNESS) + +#define WCN36XX_DXE_CTRL_TX_L_SKB (WCN36xx_DXE_CTRL_VLD | \ + WCN36xx_DXE_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CTRL_EOP | WCN36xx_DXE_CTRL_DIQ | \ + WCN36xx_DXE_CTRL_BTHLD_SEL_SET(5) | WCN36xx_DXE_CTRL_PRIO_SET(4) | \ + WCN36xx_DXE_CTRL_INT | WCN36xx_DXE_CTRL_SWAP | \ + WCN36xx_DXE_CTRL_ENDIANNESS) /* TODO This must calculated properly but not hardcoded */ #define WCN36XX_DXE_WQ_TX_L 0x17 @@ -49,15 +140,106 @@ H2H_TEST_RX_TX = DMA2 #define WCN36XX_DXE_WQ_RX_L 0xB #define WCN36XX_DXE_WQ_RX_H 0x4 -/* DXE descriptor control filed */ -#define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) +/* Channel enable or restart */ +#define WCN36xx_DXE_CH_CTRL_EN BIT(0) +/* End of packet bit */ +#define WCN36xx_DXE_CH_CTRL_EOP BIT(3) +/* BD Handling bit */ +#define WCN36xx_DXE_CH_CTRL_BDH BIT(4) +/* Source is queue */ +#define WCN36xx_DXE_CH_CTRL_SIQ BIT(5) +/* Destination is queue */ +#define WCN36xx_DXE_CH_CTRL_DIQ BIT(6) +/* Pointer descriptor is queue */ +#define WCN36xx_DXE_CH_CTRL_PIQ BIT(7) +/* Relase PDU when done */ +#define WCN36xx_DXE_CH_CTRL_PDU_REL BIT(8) +/* Stop channel processing */ +#define WCN36xx_DXE_CH_CTRL_STOP BIT(16) +/* Enable external descriptor interrupt */ +#define WCN36xx_DXE_CH_CTRL_INE_ED BIT(17) +/* Enable channel interrupt on errors */ +#define WCN36xx_DXE_CH_CTRL_INE_ERR BIT(18) +/* Enable Channel interrupt when done */ +#define WCN36xx_DXE_CH_CTRL_INE_DONE BIT(19) +/* External descriptor enable */ +#define WCN36xx_DXE_CH_CTRL_EDEN BIT(20) +/* Wait for valid bit */ +#define WCN36xx_DXE_CH_CTRL_EDVEN BIT(21) +/* Endianness is little endian*/ +#define WCN36xx_DXE_CH_CTRL_ENDIANNESS BIT(26) +/* Abort transfer */ +#define WCN36xx_DXE_CH_CTRL_ABORT BIT(27) +/* Long descriptor format */ +#define WCN36xx_DXE_CH_CTRL_DFMT BIT(28) +/* Endian byte swap enable */ +#define WCN36xx_DXE_CH_CTRL_SWAP BIT(31) + +/* Transfer type */ +#define WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT 1 +#define WCN36xx_DXE_CH_CTRL_XTYPE_MASK GENMASK(2, WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT) +#define WCN36xx_DXE_CH_CTRL_XTYPE_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_XTYPE_SHIFT) + +/* Channel BMU Threshold select */ +#define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT 9 +#define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_MASK GENMASK(12, WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT) +#define WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SHIFT) + +/* Channel Priority */ +#define WCN36xx_DXE_CH_CTRL_PRIO_SHIFT 13 +#define WCN36xx_DXE_CH_CTRL_PRIO_MASK GENMASK(15, WCN36xx_DXE_CH_CTRL_PRIO_SHIFT) +#define WCN36xx_DXE_CH_CTRL_PRIO_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_PRIO_SHIFT) + +/* Counter select */ +#define WCN36xx_DXE_CH_CTRL_SEL_SHIFT 22 +#define WCN36xx_DXE_CH_CTRL_SEL_MASK GENMASK(25, WCN36xx_DXE_CH_CTRL_SEL_SHIFT) +#define WCN36xx_DXE_CH_CTRL_SEL_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_SEL_SHIFT) + +/* Channel BD template index */ +#define WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT 29 +#define WCN36xx_DXE_CH_CTRL_BDT_IDX_MASK GENMASK(30, WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT) +#define WCN36xx_DXE_CH_CTRL_BDT_IDX_SET(x) ((x) << WCN36xx_DXE_CH_CTRL_BDT_IDX_SHIFT) -/* TODO This must calculated properly but not hardcoded */ /* DXE default control register values */ -#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F -#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F -#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D -#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d +#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L (WCN36xx_DXE_CH_CTRL_EN | \ + WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ + WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_SIQ | \ + WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(6) | \ + WCN36xx_DXE_CH_CTRL_PRIO_SET(5) | WCN36xx_DXE_CH_CTRL_INE_ED | \ + WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ + WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ + WCN36xx_DXE_CH_CTRL_SEL_SET(1) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ + WCN36xx_DXE_CH_CTRL_SWAP) + +#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H (WCN36xx_DXE_CH_CTRL_EN | \ + WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_B2H) | \ + WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_SIQ | \ + WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(8) | \ + WCN36xx_DXE_CH_CTRL_PRIO_SET(6) | WCN36xx_DXE_CH_CTRL_INE_ED | \ + WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ + WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ + WCN36xx_DXE_CH_CTRL_SEL_SET(3) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ + WCN36xx_DXE_CH_CTRL_SWAP) + +#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H (WCN36xx_DXE_CH_CTRL_EN | \ + WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_DIQ | \ + WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(7) | \ + WCN36xx_DXE_CH_CTRL_PRIO_SET(6) | WCN36xx_DXE_CH_CTRL_INE_ED | \ + WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ + WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ + WCN36xx_DXE_CH_CTRL_SEL_SET(4) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ + WCN36xx_DXE_CH_CTRL_SWAP) + +#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L (WCN36xx_DXE_CH_CTRL_EN | \ + WCN36xx_DXE_CH_CTRL_XTYPE_SET(WCN36xx_DXE_XTYPE_H2B) | \ + WCN36xx_DXE_CH_CTRL_EOP | WCN36xx_DXE_CH_CTRL_DIQ | \ + WCN36xx_DXE_CH_CTRL_PDU_REL | WCN36xx_DXE_CH_CTRL_BTHLD_SEL_SET(5) | \ + WCN36xx_DXE_CH_CTRL_PRIO_SET(4) | WCN36xx_DXE_CH_CTRL_INE_ED | \ + WCN36xx_DXE_CH_CTRL_INE_ERR | WCN36xx_DXE_CH_CTRL_INE_DONE | \ + WCN36xx_DXE_CH_CTRL_EDEN | WCN36xx_DXE_CH_CTRL_EDVEN | \ + WCN36xx_DXE_CH_CTRL_SEL_SET(0) | WCN36xx_DXE_CH_CTRL_ENDIANNESS | \ + WCN36xx_DXE_CH_CTRL_SWAP) /* Common DXE registers */ #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) @@ -80,6 +262,10 @@ H2H_TEST_RX_TX = DMA2 #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) +#define WCN36XX_CH_STAT_INT_DONE_MASK 0x00008000 +#define WCN36XX_CH_STAT_INT_ERR_MASK 0x00004000 +#define WCN36XX_CH_STAT_INT_ED_MASK 0x00002000 + #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) @@ -266,6 +452,7 @@ struct wcn36xx_dxe_mem_pool { dma_addr_t phy_addr; }; +struct wcn36xx_tx_bd; struct wcn36xx_vif; int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn); void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn); @@ -277,8 +464,8 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn); int wcn36xx_dxe_init_channels(struct wcn36xx *wcn); int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct wcn36xx_vif *vif_priv, + struct wcn36xx_tx_bd *bd, struct sk_buff *skb, bool is_low); void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status); -void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low); #endif /* _DXE_H_ */ diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..69d6be59d97f 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -261,7 +261,7 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn) for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) { if (get_feat_caps(wcn->fw_feat_caps, i)) - wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i)); + wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i)); } } @@ -666,16 +666,13 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw, { struct wcn36xx *wcn = hw->priv; - if (!wcn36xx_smd_stop_hw_scan(wcn)) { - struct cfg80211_scan_info scan_info = { .aborted = true }; - - ieee80211_scan_completed(wcn->hw, &scan_info); - } - mutex_lock(&wcn->scan_lock); wcn->scan_aborted = true; mutex_unlock(&wcn->scan_lock); + /* ieee80211_scan_completed will be called on FW scan indication */ + wcn36xx_smd_stop_hw_scan(wcn); + cancel_work_sync(&wcn->scan_work); } @@ -1155,8 +1152,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) wcn->hw->wiphy->cipher_suites = cipher_suites; wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); - wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - #ifdef CONFIG_PM wcn->hw->wiphy->wowlan = &wowlan_support; #endif @@ -1283,6 +1278,7 @@ static int wcn36xx_probe(struct platform_device *pdev) wcn = hw->priv; wcn->hw = hw; wcn->dev = &pdev->dev; + wcn->first_boot = true; mutex_init(&wcn->conf_mutex); mutex_init(&wcn->hal_mutex); mutex_init(&wcn->scan_lock); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 2a4871ca9c72..8932af5e4d8d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -409,15 +409,17 @@ static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) wcn->fw_minor = rsp->start_rsp_params.version.minor; wcn->fw_major = rsp->start_rsp_params.version.major; - wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", - wcn->wlan_version, wcn->crm_version); - - wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", - wcn->fw_major, wcn->fw_minor, - wcn->fw_version, wcn->fw_revision, - rsp->start_rsp_params.stations, - rsp->start_rsp_params.bssids); + if (wcn->first_boot) { + wcn->first_boot = false; + wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", + wcn->wlan_version, wcn->crm_version); + wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", + wcn->fw_major, wcn->fw_minor, + wcn->fw_version, wcn->fw_revision, + rsp->start_rsp_params.stations, + rsp->start_rsp_params.bssids); + } return 0; } @@ -2138,6 +2140,8 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_SCAN_IND_COMPLETED: mutex_lock(&wcn->scan_lock); wcn->scan_req = NULL; + if (wcn->scan_aborted) + scan_info.aborted = true; mutex_unlock(&wcn->scan_lock); ieee80211_scan_completed(wcn->hw, &scan_info); break; @@ -2407,54 +2411,63 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) { struct wcn36xx *wcn = container_of(work, struct wcn36xx, hal_ind_work); - struct wcn36xx_hal_msg_header *msg_header; - struct wcn36xx_hal_ind_msg *hal_ind_msg; - unsigned long flags; - spin_lock_irqsave(&wcn->hal_ind_lock, flags); + for (;;) { + struct wcn36xx_hal_msg_header *msg_header; + struct wcn36xx_hal_ind_msg *hal_ind_msg; + unsigned long flags; - hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, - struct wcn36xx_hal_ind_msg, - list); - list_del(wcn->hal_ind_queue.next); - spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); + spin_lock_irqsave(&wcn->hal_ind_lock, flags); - msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; + if (list_empty(&wcn->hal_ind_queue)) { + spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); + return; + } - switch (msg_header->msg_type) { - case WCN36XX_HAL_COEX_IND: - case WCN36XX_HAL_DEL_BA_IND: - case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: - break; - case WCN36XX_HAL_OTA_TX_COMPL_IND: - wcn36xx_smd_tx_compl_ind(wcn, - hal_ind_msg->msg, - hal_ind_msg->msg_len); - break; - case WCN36XX_HAL_MISSED_BEACON_IND: - wcn36xx_smd_missed_beacon_ind(wcn, - hal_ind_msg->msg, - hal_ind_msg->msg_len); - break; - case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: - wcn36xx_smd_delete_sta_context_ind(wcn, - hal_ind_msg->msg, - hal_ind_msg->msg_len); - break; - case WCN36XX_HAL_PRINT_REG_INFO_IND: - wcn36xx_smd_print_reg_info_ind(wcn, - hal_ind_msg->msg, - hal_ind_msg->msg_len); - break; - case WCN36XX_HAL_SCAN_OFFLOAD_IND: - wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg, - hal_ind_msg->msg_len); - break; - default: - wcn36xx_err("SMD_EVENT (%d) not supported\n", - msg_header->msg_type); + hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, + struct wcn36xx_hal_ind_msg, + list); + list_del(&hal_ind_msg->list); + spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); + + msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; + + switch (msg_header->msg_type) { + case WCN36XX_HAL_COEX_IND: + case WCN36XX_HAL_DEL_BA_IND: + case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: + break; + case WCN36XX_HAL_OTA_TX_COMPL_IND: + wcn36xx_smd_tx_compl_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; + case WCN36XX_HAL_MISSED_BEACON_IND: + wcn36xx_smd_missed_beacon_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; + case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: + wcn36xx_smd_delete_sta_context_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; + case WCN36XX_HAL_PRINT_REG_INFO_IND: + wcn36xx_smd_print_reg_info_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; + case WCN36XX_HAL_SCAN_OFFLOAD_IND: + wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; + default: + wcn36xx_err("SMD_EVENT (%d) not supported\n", + msg_header->msg_type); + } + + kfree(hal_ind_msg); } - kfree(hal_ind_msg); } int wcn36xx_smd_open(struct wcn36xx *wcn) { diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 22304edc5948..b1768ed6b0be 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -272,21 +272,9 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, bool is_low = ieee80211_is_data(hdr->frame_control); bool bcast = is_broadcast_ether_addr(hdr->addr1) || is_multicast_ether_addr(hdr->addr1); - struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low); - - if (!bd) { - /* - * TX DXE are used in pairs. One for the BD and one for the - * actual frame. The BD DXE's has a preallocated buffer while - * the skb ones does not. If this isn't true something is really - * wierd. TODO: Recover from this situation - */ - - wcn36xx_err("bd address may not be NULL for BD DXE\n"); - return -EINVAL; - } + struct wcn36xx_tx_bd bd; - memset(bd, 0, sizeof(*bd)); + memset(&bd, 0, sizeof(bd)); wcn36xx_dbg(WCN36XX_DBG_TX, "tx skb %p len %d fc %04x sn %d %s %s\n", @@ -296,10 +284,10 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len); - bd->dpu_rf = WCN36XX_BMU_WQ_TX; + bd.dpu_rf = WCN36XX_BMU_WQ_TX; - bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); - if (bd->tx_comp) { + bd.tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); + if (bd.tx_comp) { wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); spin_lock_irqsave(&wcn->dxe_lock, flags); if (wcn->tx_ack_skb) { @@ -321,13 +309,13 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, /* Data frames served first*/ if (is_low) - wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast); + wcn36xx_set_tx_data(&bd, wcn, &vif_priv, sta_priv, skb, bcast); else /* MGMT and CTRL frames are handeld here*/ - wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast); + wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast); - buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); - bd->tx_bd_sign = 0xbdbdbdbd; + buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32)); + bd.tx_bd_sign = 0xbdbdbdbd; - return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low); + return wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low); } diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 81017e6703b4..5854adf43f3a 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -192,6 +192,8 @@ struct wcn36xx { u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; + bool first_boot; + /* IRQs */ int tx_irq; int rx_irq; |