Re: wcn36xx: bug #538: stuck tx management frames
On Thu, May 24, 2018 at 3:39 PM, Kalle Valowrote: > Daniel Mack writes: > >> On Thursday, May 24, 2018 01:48 PM, Kalle Valo wrote: >>> Daniel Mack writes: On Thursday, May 24, 2018 10:44 AM, Kalle Valo wrote: > Daniel Mack writes: >> It seems that once a network is successfully joined, the network stability is fine. I haven't seen any starvation of streams lately, at least not with the the patches in this series which I'm running since a while. That is, until a disconnect/reconnect attempt is made, and at this point, only management frames are involved. >>> >>> Ah, maybe originally you were seeing different issues with similar >>> symptoms? But now you have fixed the other bugsand now the stuck >>> transmitted management frame issue is left? Just guessing... >> >> Yeah, I wish I had a clearer picture on all this myself :( >> >> My patches definitely address some of the issues I have seen before, >> also the fixes for potential race conditions are likely to have a >> positive effect. But as you guessed yourself, I'm afraid that there's >> a multitude of possible sources for bugs, so it's hard to tell. > > Sure, but things seem to going be forward in steady state. Thanks for > your hard work! > >>> It would be great to have wcn36xx logging via tracing, just like ath10k >>> and iwlwifi does. This way logging shouldn't slow down the system too >>> much and with wpasupplicant's -T switch you can even get wpasupplicant's >>> debug messages to the same log with proper timestamps! And almost >>> forgot, you can also include mac80211 tracing logs as well: >>> >>> https://wireless.wiki.kernel.org/en/developers/documentation/mac80211/tracing >>> >>> https://wireless.wiki.kernel.org/en/users/drivers/ath10k/debug#tracing >>> >>> See ath10k_dbg() and trace_ath10k_log_dbg() for ideas how to implement >>> this, and you can also take a look at iwlwifi. Should be pretty easy. >>> Patches more than welcome :) >> >> Okay, I'll see if I can find some time to look into this. >> >> The reason why I didn't focus the logging possibilities is that I >> looked at the SMD messages that are flying around which result from >> ieee80211 API calls into the driver, and I can't seem to find anything >> that's wrong, especially not before the timeouts occur. Hence, I don't >> actually expect any oddness on the ieee80211 layer. >> >> But I agree that in general, better logging is certainly helpful. > > Yeah, I'm not expecting tracing logs to solve this case either but maybe > we could find some hints. And it just makes it so much easier to see > what's really happening from tracing logs instead trying to guess from > the bug description. "a tracing log is worth a thousand words" ;) > > But if you don't have time to implement tracing support to wcn36xx > hopefully someone else has, all one needs is a DragonBoard 410c. A > simple project for a student or someone who wants to contribute > something to the kernel. I have time to do it. If nobody else started yet... Thanks. > It seems it does, yes. Tests at night seem to take a bit more time to make the effect happen. But then again, it could also be unrelated. I can't be certain at this point. >>> >>> Can you describe what kind of radio environment you have, is it a busy >>> office complex? How many APs around etc? >> >> I've tried different environments. In the office with 15-20 >> laptops/mobiles in the room I see about 10-15 APs. At home, where I >> did long-term nightly test, there's maybe a higher number of APs, but >> fewer devices on the channel of the AP that I used for tests. >> >> I haven't used any more sophisticated environments like a sealed >> reverberation chamber yet though. > > Ok, but please let me know if you see any differences caused by the > environment. > > -- > Kalle Valo > > ___ > wcn36xx mailing list > wcn3...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/wcn36xx
[PATCH v3] wcn36xx: Add support for Factory Test Mode (FTM)
From: Eyal Ilsar <eil...@codeaurora.org> Introduce infrastructure for supporting Factory Test Mode (FTM) of the wireless LAN subsystem. In order for the user space to access the firmware in test mode the relevant netlink channel needs to be exposed from the kernel driver. The above is achieved as follows: 1) Register wcn36xx driver to testmode callback from netlink 2) Add testmode callback implementation to handle incoming FTM commands 3) Add FTM command packet structure 4) Add handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) 5) Add generic handling for all PTT_MSG packets Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <ramon.fr...@linaro.org> --- v3: * fixed kbuild warning v2: * check for NULL after kmalloc * don't assign value to ret. drivers/net/wireless/ath/wcn36xx/Makefile | 2 + drivers/net/wireless/ath/wcn36xx/hal.h| 16 ++ drivers/net/wireless/ath/wcn36xx/main.c | 3 + drivers/net/wireless/ath/wcn36xx/smd.c| 81 ++ drivers/net/wireless/ath/wcn36xx/smd.h| 4 + drivers/net/wireless/ath/wcn36xx/testmode.c | 149 ++ drivers/net/wireless/ath/wcn36xx/testmode.h | 46 ++ drivers/net/wireless/ath/wcn36xx/testmode_i.h | 29 drivers/net/wireless/ath/wcn36xx/wcn36xx.h| 2 + 9 files changed, 332 insertions(+) create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.c create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.h create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode_i.h diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 182963522941..8491b3cb3206 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2230,6 +2230,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 69d6be59d97f..ea14f87d11ff 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include #include #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -1116,6 +1117,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add= wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 8932af5e4d8d..fb0192b7ee99 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -292,12 +292,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do {\ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, _body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do {\ + memset(send_buf, 0, p_msg_body->header.len); \ + memcpy(send_buf, p_msg_body, p_msg_body
[PATCH v2] wcn36xx: Add support for Factory Test Mode (FTM)
From: Eyal Ilsar <eil...@codeaurora.org> Introduce infrastructure for supporting Factory Test Mode (FTM) of the wireless LAN subsystem. In order for the user space to access the firmware in test mode the relevant netlink channel needs to be exposed from the kernel driver. The above is achieved as follows: 1) Register wcn36xx driver to testmode callback from netlink 2) Add testmode callback implementation to handle incoming FTM commands 3) Add FTM command packet structure 4) Add handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) 5) Add generic handling for all PTT_MSG packets Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <ramon.fr...@linaro.org> --- v2: * check for NULL after kmalloc * don't assign value to ret. drivers/net/wireless/ath/wcn36xx/Makefile | 2 + drivers/net/wireless/ath/wcn36xx/hal.h| 16 ++ drivers/net/wireless/ath/wcn36xx/main.c | 3 + drivers/net/wireless/ath/wcn36xx/smd.c| 81 ++ drivers/net/wireless/ath/wcn36xx/smd.h| 4 + drivers/net/wireless/ath/wcn36xx/testmode.c | 151 ++ drivers/net/wireless/ath/wcn36xx/testmode.h | 46 ++ drivers/net/wireless/ath/wcn36xx/testmode_i.h | 29 drivers/net/wireless/ath/wcn36xx/wcn36xx.h| 2 + 9 files changed, 334 insertions(+) create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.c create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.h create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode_i.h diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 182963522941..8491b3cb3206 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2230,6 +2230,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 69d6be59d97f..ea14f87d11ff 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include #include #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -1116,6 +1117,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add= wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 8932af5e4d8d..fb0192b7ee99 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -292,12 +292,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do {\ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, _body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do {\ + memset(send_buf, 0, p_msg_body->header.len); \ + memcpy(send_buf, p_msg_body, p_msg_body->header.len); \ + } while (0) + static i
Re: [PATCH] wcn36xx: Add support for Factory Test Mode (FTM)
On 17 May 2018 at 21:37, Jeff Johnson <jjohn...@codeaurora.org> wrote: > On 2018-05-17 04:32, Ramon Fried wrote: >> >> From: Eyal Ilsar <eil...@codeaurora.org> > > ... >> >> +int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn, >> + struct ieee80211_vif *vif, void *ptt_msg, >> size_t len, >> + void **ptt_rsp_msg) >> +{ >> + struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body; >> + int ret = 0; >> + >> + mutex_lock(>hal_mutex); >> + p_msg_body = kmalloc( >> + sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len, >> + GFP_ATOMIC); > > > NULL check required? > >> + INIT_HAL_PTT_MSG(p_msg_body, len); >> + Thanks Jeff. will fix it and send again :)
[PATCH] wcn36xx: Add support for Factory Test Mode (FTM)
From: Eyal Ilsar <eil...@codeaurora.org> Introduce infrastructure for supporting Factory Test Mode (FTM) of the wireless LAN subsystem. In order for the user space to access the firmware in test mode the relevant netlink channel needs to be exposed from the kernel driver. The above is achieved as follows: 1) Register wcn36xx driver to testmode callback from netlink 2) Add testmode callback implementation to handle incoming FTM commands 3) Add FTM command packet structure 4) Add handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) 5) Add generic handling for all PTT_MSG packets Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <ramon.fr...@linaro.org> --- drivers/net/wireless/ath/wcn36xx/Makefile | 2 + drivers/net/wireless/ath/wcn36xx/hal.h| 16 ++ drivers/net/wireless/ath/wcn36xx/main.c | 3 + drivers/net/wireless/ath/wcn36xx/smd.c| 74 + drivers/net/wireless/ath/wcn36xx/smd.h| 4 + drivers/net/wireless/ath/wcn36xx/testmode.c | 151 ++ drivers/net/wireless/ath/wcn36xx/testmode.h | 46 ++ drivers/net/wireless/ath/wcn36xx/testmode_i.h | 29 drivers/net/wireless/ath/wcn36xx/wcn36xx.h| 2 + 9 files changed, 327 insertions(+) create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.c create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.h create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode_i.h diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 182963522941..8491b3cb3206 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2230,6 +2230,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 69d6be59d97f..ea14f87d11ff 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include #include #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -1116,6 +1117,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add= wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 8932af5e4d8d..8eaf192f8bdb 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -292,12 +292,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do {\ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, _body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do {\ + memset(send_buf, 0, p_msg_body->header.len); \ + memcpy(send_buf, p_msg_body, p_msg_body->header.len); \ + } while (0) + static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) { struct wcn
Re: [PATCH 02/10] wcn36xx: set DMA mask explicitly
On Wed, May 16, 2018 at 5:08 PM, Daniel Mack <dan...@zonque.org> wrote: > The device takes 32-bit addresses only, so inform the DMA API about it. > This is the default on msm8016, so that doesn't change anything, but > it's best practice to be explicit. > > Signed-off-by: Daniel Mack <dan...@zonque.org> > --- > drivers/net/wireless/ath/wcn36xx/main.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/net/wireless/ath/wcn36xx/main.c > b/drivers/net/wireless/ath/wcn36xx/main.c > index e3b91b3b38ef..e6330ad372b3 100644 > --- a/drivers/net/wireless/ath/wcn36xx/main.c > +++ b/drivers/net/wireless/ath/wcn36xx/main.c > @@ -1309,6 +1309,12 @@ static int wcn36xx_probe(struct platform_device *pdev) > mutex_init(>hal_mutex); > mutex_init(>scan_lock); > > + ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32)); > + if (ret < 0) { > + wcn36xx_err("failed to set DMA mask: %d\n", ret); > + goto out_wq; > + } > + > INIT_WORK(>scan_work, wcn36xx_hw_scan_worker); > > wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", > wcn36xx_smd_rsp_process, hw); > -- > 2.14.3 > > > ___ > wcn36xx mailing list > wcn3...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/wcn36xx Acked-by: Ramon Fried <ramon.fr...@linaro.org>
Re: [PATCH 01/10] wcn36xx: fix buffer commit logic on TX path
le(wcn->dev, > - skb->data, > - skb->len, > - DMA_TO_DEVICE); > - if (dma_mapping_error(wcn->dev, desc->src_addr_l)) { > + desc_skb->src_addr_l = dma_map_single(wcn->dev, > + skb->data, > + skb->len, > + DMA_TO_DEVICE); > + if (dma_mapping_error(wcn->dev, desc_skb->src_addr_l)) { > dev_err(wcn->dev, "unable to DMA map src_addr_l\n"); > ret = -ENOMEM; > goto unlock; > } > > - ctl->skb = skb; > - desc->dst_addr_l = ch->dxe_wq; > - desc->fr_len = ctl->skb->len; > - > - /* set dxe descriptor to VALID */ > - desc->ctrl = ch->ctrl_skb; > + ctl_skb->skb = skb; > + desc_skb->dst_addr_l = ch->dxe_wq; > + desc_skb->fr_len = ctl_skb->skb->len; > > wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", > -(char *)desc, sizeof(*desc)); > +(char *)desc_skb, sizeof(*desc_skb)); > wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", > - (char *)ctl->skb->data, ctl->skb->len); > +(char *)ctl_skb->skb->data, ctl_skb->skb->len); > > /* Move the head of the ring to the next empty descriptor */ > -ch->head_blk_ctl = ctl->next; > +ch->head_blk_ctl = ctl_skb->next; > + > + /* Commit all previous writes and set descriptors to VALID */ > + wmb(); > + desc_skb->ctrl = ch->ctrl_skb; > + wmb(); > + desc_bd->ctrl = ch->ctrl_bd; > > /* > * When connected and trying to send data frame chip can be in sleep > -- > 2.14.3 > > > ___ > wcn36xx mailing list > wcn3...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/wcn36xx Acked-by: Ramon Fried <ramon.fr...@linaro.org>
Re: [PATCH 0/5] wcn36xx: scan related patches
On 16 April 2018 at 16:16, Daniel Mackwrote: > Here's another series of 5 patches for wcn36xx that address some issues > with scanning. The first one is the most important one. > Nicely done. Thanks ! > > Daniel > > Daniel Mack (5): > wcn36xx: abort scan request when 'dequeued' indicator is sent > wcn36xx: cancel pending scan request when interface goes down > wcn36xx: handle scan cancellation when firmware support is missing > wcn36xx: send bss_type in scan requests > wcn36xx: pass information elements in scan requests > > drivers/net/wireless/ath/wcn36xx/hal.h | 8 +++- > drivers/net/wireless/ath/wcn36xx/main.c| 29 + > drivers/net/wireless/ath/wcn36xx/smd.c | 20 +--- > drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 7 +-- > 4 files changed, 50 insertions(+), 14 deletions(-) > > -- > 2.14.3 >
Re: [PATCH] wcn36xx: use READ_ONCE() to access desc->ctrl
On 11 April 2018 at 09:58, Daniel Mack <dan...@zonque.org> wrote: > On Tuesday, April 10, 2018 08:17 PM, Ramon Fried wrote: >> On 10 April 2018 at 20:35, Daniel Mack <dan...@zonque.org> wrote: >>> When accessing shared memory to check for the stat of submitted >>> descriptors, make sure to use READ_ONCE(). This will guarantee the >>> compiler treats these memory locations as volatile and doesn't apply >>> any caching. >> >> The structure that is tested is not shared memory. It's accessed only >> by the apps processor. > > Hmm? ctl->desc is of type struct wcn36xx_dxe_desc, which is packed and > shared with the firmware. The WCN36xx_DXE_CTRL_VLD bit in ctrl bitfield > is set by the firmware when a frame is valid, and before asserting the > RX interrupt. So the host CPU must treat it as volatile and expect it to > change. > > Am I reading this wrong? > No, you're right. I missed that. > > Thanks, > Daniel
Re: [PATCH] wcn36xx: use READ_ONCE() to access desc->ctrl
On 10 April 2018 at 20:35, Daniel Mackwrote: > When accessing shared memory to check for the stat of submitted > descriptors, make sure to use READ_ONCE(). This will guarantee the > compiler treats these memory locations as volatile and doesn't apply > any caching. The structure that is tested is not shared memory. It's accessed only by the apps processor. In this case, caching does make sense. I'm not sure regarding READ_ONCE in that context I'll have to do some reading regarding that. But I don't think this is right here. Thanks, Ramon > > While this doesn't fix any particular problem I ran into, it's best > practice to do it this way. > > Note that this patch also removes the superflous extra condition check > in the do-while loop in reap_tx_dxes(), as the loop will break > instantly anyway in that case. > > Signed-off-by: Daniel Mack > --- > drivers/net/wireless/ath/wcn36xx/dxe.c | 7 +++ > 1 file changed, 3 insertions(+), 4 deletions(-) > > diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c > b/drivers/net/wireless/ath/wcn36xx/dxe.c > index 26e6c42f886a..c52f1c21ece9 100644 > --- a/drivers/net/wireless/ath/wcn36xx/dxe.c > +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c > @@ -363,7 +363,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct > wcn36xx_dxe_ch *ch) > spin_lock_irqsave(>lock, flags); > ctl = ch->tail_blk_ctl; > do { > - if (ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD) > + if (READ_ONCE(ctl->desc->ctrl) & WCN36xx_DXE_CTRL_VLD) > break; > if (ctl->skb) { > dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, > @@ -382,8 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct > wcn36xx_dxe_ch *ch) > ctl->skb = NULL; > } > ctl = ctl->next; > - } while (ctl != ch->head_blk_ctl && > - !(ctl->desc->ctrl & WCN36xx_DXE_CTRL_VLD)); > + } while (ctl != ch->head_blk_ctl); > > ch->tail_blk_ctl = ctl; > spin_unlock_irqrestore(>lock, flags); > @@ -525,7 +524,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, > int_mask = WCN36XX_DXE_INT_CH3_MASK; > } > > - while (!(dxe->ctrl & WCN36xx_DXE_CTRL_VLD)) { > + while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) { > skb = ctl->skb; > dma_addr = dxe->dst_addr_l; > ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC); > -- > 2.14.3 >
Re: [PATCH 0/1] RFC: memory coherency and data races on TX path
On 10 April 2018 at 20:42, Daniel Mackwrote: > I found something that I believe might be an issue, and I have an > idea on how to correct this, but unfortunately, this doesn't solve > the issues I occasionally see with this driver. I'd still like to > share it, because I might be totally mistaken in my understanding. > Thanks for sharing you idea. Are you aware of the recent patch I sent that Loic Poulain wrote that fixes a race issue in access to wcn36xx_dxe_tx_frame() ? Kalle just recently applied it to ath-next, I don't think it's available yet upstream. The patch was fixing something similar, perhaps it will solve the issue you're experiencing. > With no firmware code or documentation at hand, it's not exactly clear > which assumption the firmware makes, but obviously, the driver and the > firmware share memory to exchange descriptors that either contain > control information or payload. The driver puts control descriptors > and payload descriptors in a ring buffer in an interleaved fashion. > > When the driver wants to send an skb, it looks for a currently unused > control descriptor, and then fills it, together with its directly > chained payload descriptor. The descriptors are both marked valid and > then the firmware is instructed to start processing the ringbuffer. > In case the firmware is idle when wcn36xx_dxe_tx_frame() is entered, > this is all fine. However, when sending many packets in a short time > frame, there are cases when the firmware is still processing the ring > buffer (iow, ch->reg_ctrl & WCN36xx_DXE_CH_CTRL_EN != 0), and in this > case, writes to the shared memory area depict a data race. The local > spinlock of course doesn't help to prevent that. OTOH, it should be > completely fine to modify the descriptors while firmware is still > reading them, as the firmware should only pay attention to such that > are marked valid. > > There's a problem with the latter presumption however which looks like > this in the driver code: > > desc->fr_len = ctl->skb->len; > /* set dxe descriptor to VALID */ > desc->ctrl = ch->ctrl_skb; > The firmware won't start reading the descriptors until it receives an interrupt from driver. which in turn happen later in the function using: wcn36xx_dxe_write_register() so I don't think reordering in this case make any problem. > The CPU may very well reorder the two writes, even though the memory is > allocated as coherent DMA. When that happens, the firmware may see a > wrong length for a valid descriptor. A simple memory write barrier would > suffice to solve this, but then again, there are two descriptors > involved. > > My attempt to fix that restructures the code a bit and makes the > payload descriptor valid first and then the control descriptor, both > strongly ordered through memory fences. This however assumes that the > firmware will ignore valid payload descriptors unless they have a > valid control descriptor preceding them, but that's really just > guessing. > > Does that make sense? As I said, I can't really say this improves > anything, sadly, so I might be mistaken entirely. But I'll leave this > here for further discussion. Ideally, somebody with access to the > firmware sources could give an assessment whether this is an issue at > all or not. When I'm not sure regarding some implementation I consult with the downstream pronto driver. https://github.com/sultanqasim/qcom_wlan_prima Did you look there if they actually placed wmb() ? > > > Thanks, > Daniel > > > Daniel Mack (1): > wcn36xx: fix buffer commit logic on TX path > > drivers/net/wireless/ath/wcn36xx/dxe.c | 75 > +- > 1 file changed, 38 insertions(+), 37 deletions(-) > > -- > 2.14.3 >
Re: [PATCH 3/3] wcn36xx: don't delete invalid bss indices
On 4/3/2018 7:51 PM, Daniel Mack wrote: > The firmware code cannot cope with requests to remove BSS indices that have > not previously been added. This primarily happens when the device is > suspended and then resumed. ieee80211_reconfig() then calls into > wcn36xx_bss_info_changed() with an empty bssid and BSS_CHANGED_BSSID set, > which subsequently leads to a firmware crash: > > [ 43.647928] qcom-wcnss-pil a204000.wcnss: fatal error received: > halMsg.c:4964:halMsg_DelBss: Invalid BSSIndex 0 > [ 43.647959] remoteproc remoteproc0: crash detected in a204000.wcnss: type > fatal error > > To fix this, set bss_index to WCN36XX_HAL_BSS_INVALID_IDX for all bss > that have not been configured in the firmware, and don't call into the > firmware with invalid indices. > > Signed-off-by: Daniel Mack> --- > drivers/net/wireless/ath/wcn36xx/main.c | 1 + > drivers/net/wireless/ath/wcn36xx/smd.c | 6 ++ > 2 files changed, 7 insertions(+) > > diff --git a/drivers/net/wireless/ath/wcn36xx/main.c > b/drivers/net/wireless/ath/wcn36xx/main.c > index 69d6be59d97f..32bbd6e2fd09 100644 > --- a/drivers/net/wireless/ath/wcn36xx/main.c > +++ b/drivers/net/wireless/ath/wcn36xx/main.c > @@ -953,6 +953,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw, > > mutex_lock(>conf_mutex); > > + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; > list_add(_priv->list, >vif_list); > wcn36xx_smd_add_sta_self(wcn, vif); > > diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c > b/drivers/net/wireless/ath/wcn36xx/smd.c > index 8932af5e4d8d..5be07e40a86d 100644 > --- a/drivers/net/wireless/ath/wcn36xx/smd.c > +++ b/drivers/net/wireless/ath/wcn36xx/smd.c > @@ -1446,6 +1446,10 @@ int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct > ieee80211_vif *vif) > int ret = 0; > > mutex_lock(>hal_mutex); > + > + if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX) > + goto out; > + > INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); > > msg_body.bss_index = vif_priv->bss_index; > @@ -1464,6 +1468,8 @@ int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct > ieee80211_vif *vif) > wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); > goto out; > } > + > + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; > out: > mutex_unlock(>hal_mutex); > return ret; Interesting. I have never seen this bug before. Do you have a way of recreating it so I can test it on my side ? -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH 1/3] wcn36xx: check for DMA mapping errors in wcn36xx_dxe_tx_frame()
On 4/3/2018 7:51 PM, Daniel Mack wrote: > Bail out if the mapping fails. Even though this hasn't occured during > tests, this unlikely case should still be handled. > > Signed-off-by: Daniel Mack <dan...@zonque.org> > --- > drivers/net/wireless/ath/wcn36xx/dxe.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c > b/drivers/net/wireless/ath/wcn36xx/dxe.c > index 6e9a3583c447..e8ad8f989ccd 100644 > --- a/drivers/net/wireless/ath/wcn36xx/dxe.c > +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c > @@ -707,6 +707,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, > ctl->skb->data, > ctl->skb->len, > DMA_TO_DEVICE); > + if (dma_mapping_error(wcn->dev, desc->src_addr_l)) { > + dev_err(wcn->dev, "unable to DMA map src_addr_l\n"); > + ret = -ENOMEM; > + goto unlock; > + } > > desc->dst_addr_l = ch->dxe_wq; > desc->fr_len = ctl->skb->len; I have the exact patch ready for submission, you got a head of me :) Acked-by: Ramon Fried <rfr...@codeaurora.org> -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v2] wcn36xx: Disable 5GHz for wcn3610
(adding Bjorn Andersson) On 3/29/2018 10:15 AM, Kalle Valo wrote: > (adding devicetree list) > > Ramon Fried <rfr...@codeaurora.org> writes: > >> wcn3610 can only operate on 2.4GHz band due to RF limitation. >> If wcn36xx digital block is associated with an external IRIS >> RF module, retrieve the id and disable 5GHz band in case of >> wcn3610 id. >> >> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> >> --- >> v2: fixed wrong assignment, which is logically introduces the >> same behaviour, but for correctness. >> >> drivers/net/wireless/ath/wcn36xx/main.c| 4 +++- >> drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + >> 2 files changed, 4 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c >> b/drivers/net/wireless/ath/wcn36xx/main.c >> index ab5be6d2c691..833531a68c95 100644 >> --- a/drivers/net/wireless/ath/wcn36xx/main.c >> +++ b/drivers/net/wireless/ath/wcn36xx/main.c >> @@ -1146,7 +1146,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) >> BIT(NL80211_IFTYPE_MESH_POINT); >> >> wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz; >> -if (wcn->rf_id != RF_IRIS_WCN3620) >> +if (wcn->rf_id != RF_IRIS_WCN3610 && wcn->rf_id != RF_IRIS_WCN3620) >> wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz; >> >> wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; >> @@ -1248,6 +1248,8 @@ static int wcn36xx_platform_get_resources(struct >> wcn36xx *wcn, >> if (iris_node) { >> if (of_device_is_compatible(iris_node, "qcom,wcn3620")) >> wcn->rf_id = RF_IRIS_WCN3620; >> +else if (of_device_is_compatible(iris_node, "qcom,wcn3610")) >> +wcn->rf_id = RF_IRIS_WCN3610; >> of_node_put(iris_node); >> } > Should we document qcom,wcn3610 just like wcn3620 is: > > Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt: > "qcom,wcn3620", IMHO the mentioned bindings is related to the PIL (peripheral image loaded) which is just the firmware part and has nothing to do with wifi frontend(IRIS).
Re: [PATCH] wcn36xx: Disable 5GHz for wcn3610
On 3/29/2018 9:58 AM, Rafał Miłecki wrote: > On 03/29/2018 08:20 AM, Ramon Fried wrote: >> wcn3610 can only operate on 2.4GHz band due to RF limitation. >> If wcn36xx digital block is associated with an external IRIS >> RF module, retrieve the id and disable 5GHz band in case of >> wcn3610 id. >> >> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> >> --- >> drivers/net/wireless/ath/wcn36xx/main.c | 4 +++- >> drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + >> 2 files changed, 4 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c >> b/drivers/net/wireless/ath/wcn36xx/main.c >> index ab5be6d2c691..833531a68c95 100644 >> --- a/drivers/net/wireless/ath/wcn36xx/main.c >> +++ b/drivers/net/wireless/ath/wcn36xx/main.c >> @@ -1146,7 +1146,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) >> BIT(NL80211_IFTYPE_MESH_POINT); >> >> wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz; >> - if (wcn->rf_id != RF_IRIS_WCN3620) >> + if (wcn->rf_id != RF_IRIS_WCN3610 && wcn->rf_id != RF_IRIS_WCN3620) >> wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz; >> >> wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; >> @@ -1248,6 +1248,8 @@ static int wcn36xx_platform_get_resources(struct >> wcn36xx *wcn, >> if (iris_node) { >> if (of_device_is_compatible(iris_node, "qcom,wcn3620")) >> wcn->rf_id = RF_IRIS_WCN3620; >> + else if (of_device_is_compatible(iris_node, "qcom,wcn3610")) >> + wcn->rf_id = RF_IRIS_WCN3620; > > RF_IRIS_WCN3610 ? You're correct. I also noticed just now. Sent v2. Thanks. > > ___ > wcn36xx mailing list > wcn3...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/wcn36xx
[PATCH v2] wcn36xx: Disable 5GHz for wcn3610
wcn3610 can only operate on 2.4GHz band due to RF limitation. If wcn36xx digital block is associated with an external IRIS RF module, retrieve the id and disable 5GHz band in case of wcn3610 id. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- v2: fixed wrong assignment, which is logically introduces the same behaviour, but for correctness. drivers/net/wireless/ath/wcn36xx/main.c| 4 +++- drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..833531a68c95 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1146,7 +1146,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) BIT(NL80211_IFTYPE_MESH_POINT); wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz; - if (wcn->rf_id != RF_IRIS_WCN3620) + if (wcn->rf_id != RF_IRIS_WCN3610 && wcn->rf_id != RF_IRIS_WCN3620) wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz; wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; @@ -1248,6 +1248,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, if (iris_node) { if (of_device_is_compatible(iris_node, "qcom,wcn3620")) wcn->rf_id = RF_IRIS_WCN3620; + else if (of_device_is_compatible(iris_node, "qcom,wcn3610")) + wcn->rf_id = RF_IRIS_WCN3610; of_node_put(iris_node); } diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 81017e6703b4..bc4d1a10d90e 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -95,6 +95,7 @@ enum wcn36xx_ampdu_state { #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) #define RF_UNKNOWN 0x +#define RF_IRIS_WCN36100x3610 #define RF_IRIS_WCN36200x3620 static inline void buff_to_be(u32 *buf, size_t len) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: Disable 5GHz for wcn3610
wcn3610 can only operate on 2.4GHz band due to RF limitation. If wcn36xx digital block is associated with an external IRIS RF module, retrieve the id and disable 5GHz band in case of wcn3610 id. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/main.c| 4 +++- drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..833531a68c95 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1146,7 +1146,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) BIT(NL80211_IFTYPE_MESH_POINT); wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz; - if (wcn->rf_id != RF_IRIS_WCN3620) + if (wcn->rf_id != RF_IRIS_WCN3610 && wcn->rf_id != RF_IRIS_WCN3620) wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz; wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; @@ -1248,6 +1248,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, if (iris_node) { if (of_device_is_compatible(iris_node, "qcom,wcn3620")) wcn->rf_id = RF_IRIS_WCN3620; + else if (of_device_is_compatible(iris_node, "qcom,wcn3610")) + wcn->rf_id = RF_IRIS_WCN3620; of_node_put(iris_node); } diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 81017e6703b4..bc4d1a10d90e 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -95,6 +95,7 @@ enum wcn36xx_ampdu_state { #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) #define RF_UNKNOWN 0x +#define RF_IRIS_WCN36100x3610 #define RF_IRIS_WCN36200x3620 static inline void buff_to_be(u32 *buf, size_t len) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v3] wcn36xx: reduce verbosity of drivers messages
Hi Kalle. Kind reminder. Is the patch ok ? Thanks, Ramon On 2/27/2018 4:05 PM, Ramon Fried wrote: > Whenever the WLAN interface is started the FW > version and caps are printed. > The caps now will be displayed only in debug mode. > Firmware version will be displayed only once on first > startup of the interface. > > Change-Id: I4db6ea7f384fe15eebe4c3ddb1d1ccab00094332 > Signed-off-by: Ramon Fried <rfr...@codeaurora.org> > --- > v2: print the firwmare version as info but only > onetime. > v3: change the static variable to a struct variable. > > drivers/net/wireless/ath/wcn36xx/main.c| 3 ++- > drivers/net/wireless/ath/wcn36xx/smd.c | 18 ++ > drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 ++ > 3 files changed, 14 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/wireless/ath/wcn36xx/main.c > b/drivers/net/wireless/ath/wcn36xx/main.c > index ab5be6d2c691..bfe9062bfa52 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)); > } > } > > @@ -1283,6 +1283,7 @@ static int wcn36xx_probe(struct platform_device *pdev) > wcn = hw->priv; > wcn->hw = hw; > wcn->dev = >dev; > + wcn->first_boot = true; > mutex_init(>conf_mutex); > mutex_init(>hal_mutex); > mutex_init(>scan_lock); > diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c > b/drivers/net/wireless/ath/wcn36xx/smd.c > index 2a4871ca9c72..1a5b4d57c0ac 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; > } > > 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]; > > + boolfirst_boot; > + > /* IRQs */ > int tx_irq; > int rx_irq;
Re: [PATCH] wcn36xx: dequeue all pending indicator messages
On 3/16/2018 12:37 AM, Daniel Mack wrote: In case wcn36xx_smd_rsp_process() is called more than once before hal_ind_work was dispatched, the messages will end up in hal_ind_queue, but wcn36xx_ind_smd_work() will only look at the first message in that list. Fix this by dequeing the messages from the list in a loop, and only stop when it's empty. Interesting. does it solve a specific bug ? can you elaborate ? Signed-off-by: Daniel Mack--- drivers/net/wireless/ath/wcn36xx/smd.c | 95 +++--- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 7cc29285e052..a6b5352f59e9 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -2409,54 +2409,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(>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(>hal_ind_queue, - struct wcn36xx_hal_ind_msg, - list); - list_del(wcn->hal_ind_queue.next); - spin_unlock_irqrestore(>hal_ind_lock, flags); + spin_lock_irqsave(>hal_ind_lock, flags); - msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; + if (list_empty(>hal_ind_queue)) { + spin_unlock_irqrestore(>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(>hal_ind_queue, + struct wcn36xx_hal_ind_msg, + list); + list_del(_ind_msg->list); + spin_unlock_irqrestore(>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: +
[PATCH] wcn36xx: Fix firmware crash due to corrupted buffer address
From: Loic Poulain <loic.poul...@linaro.org> wcn36xx_start_tx function retrieves the buffer descriptor from the channel control queue to start filling tx buffer information. However, nothing prevents this same buffer to be concurrently accessed in a concurent tx call, leading to potential buffer coruption and firmware crash (observed during iperf test). The channel control queue should only be accessed and updated with the channel lock. Fix this issue by using a local buffer descriptor which will be copied in the thread-safe wcn36xx_dxe_tx_frame. Note that buffer descriptor size is few bytes so the introduced copy overhead is insignificant. Moreover, this allows to keep the locked section minimal. Signed-off-by: Loic Poulain <loic.poul...@linaro.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 13 - drivers/net/wireless/ath/wcn36xx/dxe.h | 3 ++- drivers/net/wireless/ath/wcn36xx/txrx.c | 32 ++-- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 7d5ecaf02288..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 ? - >dxe_tx_l_ch : - >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, @@ -648,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) { @@ -681,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 2bc376c5391b..ce580960d109 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -452,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); @@ -463,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/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(, 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 &
[PATCH] wcn36xx: turn off probe response offloading
It appears that the WCN36xx firmware doesn't actually respond to probe requests. Until it's resolved, switch the probe response responsibility to the 802.11 layer to allow creation of hidden SSID AP's. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..9d8c177ac7e1 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1155,8 +1155,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 = _support; #endif -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v2] wcn36xx: Add support for FTM WLAN
From: Eyal Ilsar <eil...@codeaurora.org> Introduce infrastructure for supporting Factory Test Mode (FTM) of the wireless LAN subsystem. In order for the user space to access the firmware in test mode the relevant netlink channel needs to be exposed from the kernel driver. The above is achieved as follows: 1) Register wcn36xx driver to testmode callback from netlink 2) Add testmode callback implementation to handle incoming FTM commands 3) Add FTM command packet structure 4) Add handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) 5) Add generic handling for all PTT_MSG packets Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- v2: * changed commit msg * remove unnecessary whitespace * kept the stop/start as the messages do arrive, but changed the documentation to explain the purpose. drivers/net/wireless/ath/wcn36xx/Makefile | 2 + drivers/net/wireless/ath/wcn36xx/hal.h| 16 +++ drivers/net/wireless/ath/wcn36xx/main.c | 3 + drivers/net/wireless/ath/wcn36xx/smd.c| 74 +++ drivers/net/wireless/ath/wcn36xx/smd.h| 4 + drivers/net/wireless/ath/wcn36xx/testmode.c | 173 ++ drivers/net/wireless/ath/wcn36xx/testmode.h | 46 +++ drivers/net/wireless/ath/wcn36xx/testmode_i.h | 45 +++ drivers/net/wireless/ath/wcn36xx/wcn36xx.h| 2 + 9 files changed, 365 insertions(+) create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.c create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.h create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode_i.h diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 182963522941..8491b3cb3206 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2230,6 +2230,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 8c2654075eb8..6b73da6f7fde 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include #include #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -1119,6 +1120,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add= wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 3048722f0484..c4c2fc6309bf 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -292,12 +292,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do {\ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, _body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do {\ + memset(send_buf, 0, p_
Re: [PATCH] wcn36xx: Add support for FTM WLAN
On 3/10/2018 11:45 AM, Kalle Valo wrote: > Ramon Fried <rfr...@codeaurora.org> writes: > >> From: Eyal Ilsar <eil...@codeaurora.org> >> >> Introduced infrastructure for supporting FTM WLAN in user space exposing >> the netlink channel from the kernel WLAN driver. > What's FTM WLAN? Don't assume that people know all the acronyms. FTM is factory test mode if I recall correctly, but you're right. I elaborate more in the commit message. > > This included: >> 1) Registered wcn36xx driver to testmode callback from netlink >> 2) Added testmode callback implementation to handle incoming FTM commands >> 3) Added FTM command packet structure >> 4) Added handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) >> 5) Added generic handling for all PTT_MSG packets > I don't remember the english grammar terminology, but in the commit log > use the form "register", "add" instead of "registered", "added". OK. Will fix. >> +struct wcn36xx_hal_process_ptt_msg_rsp_msg { >> +struct wcn36xx_hal_msg_header header; >> + >> +/* FTM Command response status */ >> +u32 ptt_msg_resp_status; > Unnecessary whitespace after u32. Thanks. >> +static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len, >> +void **p_ptt_rsp_msg) >> +{ >> +struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp; >> +int ret = 0; >> + >> +ret = wcn36xx_smd_rsp_status_check(buf, len); >> +if (ret) >> +return ret; >> +rsp = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)buf; >> +wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length >> %d\n", >> +rsp->header.len); >> +wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg, >> +rsp->header.len - sizeof(rsp->ptt_msg_resp_status)); >> +if (rsp->header.len > 0) { >> +*p_ptt_rsp_msg = kmalloc(rsp->header.len, GFP_ATOMIC); >> +memcpy(*p_ptt_rsp_msg, rsp->ptt_msg, rsp->header.len); >> +} >> +return ret; >> +} > Adding few empty lines to the function would make it more readable. Ok, I will add. >> @@ -2330,6 +2399,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, >> struct ieee80211_hw *hw = priv; >> struct wcn36xx *wcn = hw->priv; >> struct wcn36xx_hal_ind_msg *msg_ind; >> + >> wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); > Unrelated change. Nice catch. thanks. >> +int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, >> + void *data, int len) >> +{ >> +struct wcn36xx *wcn = hw->priv; >> +struct nlattr *tb[WCN36XX_TM_ATTR_MAX + 1]; >> +int ret = 0; >> +unsigned short attr; >> + >> +wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "Data:", data, len); >> +ret = nla_parse(tb, WCN36XX_TM_ATTR_MAX, data, len, >> +wcn36xx_tm_policy, NULL); >> +if (ret) >> +return ret; >> + >> +if (!tb[WCN36XX_TM_ATTR_CMD]) >> +return -EINVAL; >> + >> +attr = nla_get_u16(tb[WCN36XX_TM_ATTR_CMD]); >> + >> +switch (attr) { >> +case WCN36XX_TM_CMD_START: >> +case WCN36XX_TM_CMD_STOP: >> +// N/A to this driver as it does not need to switch state >> +break; > [...] > >> +enum wcn36xx_tm_cmd { >> +/* For backwards compatibility >> + */ >> +WCN36XX_TM_CMD_START = 1, >> + >> +/* For backwards compatibility >> + */ >> +WCN36XX_TM_CMD_STOP = 2, > This looks odd. If wcn36xx does not need START and STOP commands why add > those in the first place? AFAIK the user-space app sends these commands, but I will check again. in WCN36xx unlike ATH10k it's not needed to do any transition or replace the firmware to go in test mode, but I assume that if this command arrives we should return success. >
[PATCH] wcn36xx: calculate DXE default channel values
DXE channel defaults used hardcoded magic values. Added bit definitions of the control register and calculate this values in compilation for clarity. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.h | 104 +++-- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index 73a14953920d..feb3cb7ee81f 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -140,12 +140,106 @@ H2H_TEST_RX_TX = DMA2 #define WCN36XX_DXE_WQ_RX_L0xB #define WCN36XX_DXE_WQ_RX_H0x4 -/* TODO This must calculated properly but not hardcoded */ +/* Channel enable or restart */ +#define WCN36xx_DXE_CH_CTRL_EN BIT(0) +/* End of packet bit */ +#define WCN36xx_DXE_CH_CTRL_EOPBIT(3) +/* BD Handling bit */ +#define WCN36xx_DXE_CH_CTRL_BDHBIT(4) +/* Source is queue */ +#define WCN36xx_DXE_CH_CTRL_SIQBIT(5) +/* Destination is queue */ +#define WCN36xx_DXE_CH_CTRL_DIQBIT(6) +/* Pointer descriptor is queue */ +#define WCN36xx_DXE_CH_CTRL_PIQBIT(7) +/* Relase PDU when done */ +#define WCN36xx_DXE_CH_CTRL_PDU_RELBIT(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_ERRBIT(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) + /* DXE default control register values */ -#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L0x847EAD2F -#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H0x84FED12F -#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H0x853ECF4D -#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L0x843e8b4d +#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 | \ +
[PATCH] wcn36xx: Check DXE IRQ reason
IRQ reason was not cheked for errors. Although error handing is not currently supported, it will be nice to output an error value to the log if the DMA operation failed. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 50 +- drivers/net/wireless/ath/wcn36xx/dxe.h | 4 +++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 8e4d6d9ea277..7d5ecaf02288 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -415,14 +415,31 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, _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, >dxe_tx_h_ch); } @@ -431,14 +448,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, _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, >dxe_tx_l_ch); } diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index feb3cb7ee81f..2bc376c5391b 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -262,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 0x8000 +#define WCN36XX_CH_STAT_INT_ERR_MASK0x4000 +#define WCN36XX_CH_STAT_INT_ED_MASK 0x2000 + #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) #define WCN36XX_DXE_0_CH1_STATUS
Re: [PATCH] wcn36xx: calculate DXE control registers values
On 3/10/2018 11:47 AM, Kalle Valo wrote: > Ramon Fried <rfr...@codeaurora.org> writes: > >> DXE descriptor control registers used hardcoded magic values. Added >> bit definitions of the control register and calculate this values in >> compilation for clarity. >> >> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> > I assume that the values are still the same and there are no functional > changes? If yes, I'll add that to the commit log when I commit this. Yes. I double verified this. the values are the same.
[PATCH] wcn36xx: calculate DXE control registers values
DXE descriptor control registers used hardcoded magic values. Added bit definitions of the control register and calculate this values in compilation for clarity. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 6 +- drivers/net/wireless/ath/wcn36xx/dxe.h | 112 + 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index a3f1f7d042a4..8e4d6d9ea277 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -376,7 +376,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) spin_lock_irqsave(>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 +397,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(>lock, flags); @@ -503,7 +503,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); diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index c012e807753b..73a14953920d 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_RIVA0x310 #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_ENDIANNESSBIT(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_P
[PATCH] wcn36xx: Add support for FTM WLAN
From: Eyal Ilsar <eil...@codeaurora.org> Introduced infrastructure for supporting FTM WLAN in user space exposing the netlink channel from the kernel WLAN driver. This included: 1) Registered wcn36xx driver to testmode callback from netlink 2) Added testmode callback implementation to handle incoming FTM commands 3) Added FTM command packet structure 4) Added handling for GET_BUILD_RELEASE_NUMBER (msgid=0x32A2) 5) Added generic handling for all PTT_MSG packets Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/Makefile | 2 + drivers/net/wireless/ath/wcn36xx/hal.h| 16 +++ drivers/net/wireless/ath/wcn36xx/main.c | 3 + drivers/net/wireless/ath/wcn36xx/smd.c| 72 drivers/net/wireless/ath/wcn36xx/smd.h| 4 + drivers/net/wireless/ath/wcn36xx/testmode.c | 161 ++ drivers/net/wireless/ath/wcn36xx/testmode.h | 42 +++ drivers/net/wireless/ath/wcn36xx/testmode_i.h | 41 +++ drivers/net/wireless/ath/wcn36xx/wcn36xx.h| 2 + 9 files changed, 343 insertions(+) create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.c create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode.h create mode 100644 drivers/net/wireless/ath/wcn36xx/testmode_i.h diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 182963522941..d2df6750e5f6 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2230,6 +2230,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 8c2654075eb8..6b73da6f7fde 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include #include #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -1119,6 +1120,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add= wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 3048722f0484..b6f1e98395d0 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -292,12 +292,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do {\ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, _body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do {\ + memset(send_buf, 0, p_msg_body->header.len); \ + memcpy(send_buf, p_msg_body, p_msg_body->header.len); \ + } while (0) + static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) { struct wcn36xx_fw_msg_status_rsp *rsp; @@ -742,6 +756,61 @@ int wcn36xx_smd_switch_channel(stru
[PATCH v3] wcn36xx: reduce verbosity of drivers messages
Whenever the WLAN interface is started the FW version and caps are printed. The caps now will be displayed only in debug mode. Firmware version will be displayed only once on first startup of the interface. Change-Id: I4db6ea7f384fe15eebe4c3ddb1d1ccab00094332 Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- v2: print the firwmare version as info but only onetime. v3: change the static variable to a struct variable. drivers/net/wireless/ath/wcn36xx/main.c| 3 ++- drivers/net/wireless/ath/wcn36xx/smd.c | 18 ++ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 ++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..bfe9062bfa52 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)); } } @@ -1283,6 +1283,7 @@ static int wcn36xx_probe(struct platform_device *pdev) wcn = hw->priv; wcn->hw = hw; wcn->dev = >dev; + wcn->first_boot = true; mutex_init(>conf_mutex); mutex_init(>hal_mutex); mutex_init(>scan_lock); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 2a4871ca9c72..1a5b4d57c0ac 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; } 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]; + boolfirst_boot; + /* IRQs */ int tx_irq; int rx_irq; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v2] wcn36xx: reduce verbosity of drivers messages
Whenever the WLAN interface is started the FW version and caps are printed. The caps now will be displayed only in debug mode. Firmware version will be displayed only once on first startup of the interface. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- v2: print the firwmare version as info but only onetime. drivers/net/wireless/ath/wcn36xx/main.c | 2 +- drivers/net/wireless/ath/wcn36xx/smd.c | 19 +++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..8c2654075eb8 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)); } } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 2a4871ca9c72..3048722f0484 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -385,6 +385,7 @@ out:return ret; static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) { + static bool first = true; struct wcn36xx_hal_mac_start_rsp_msg *rsp; if (len < sizeof(*rsp)) @@ -409,15 +410,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 (first) { + first = 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; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: reduce verbosity of drivers messages
Whenever the WLAN interface is started the FW version and caps are printed, this info should appear as debug info. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index ab5be6d2c691..8c2654075eb8 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)); } } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 2a4871ca9c72..7c4d19b041bc 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -409,10 +409,10 @@ 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", + wcn36xx_dbg(WCN36XX_DBG_HAL, "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", + wcn36xx_dbg(WCN36XX_DBG_HAL, "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, -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v2] wcn36xx: release resources in case of error
wcn36xx_dxe_init() doesn't check for the return value of wcn36xx_dxe_init_descs(). This patch releases the resources in case an error ocurred. Change-Id: I924bd7489b60243c0a0cbaa716caf924f11d7587 Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 48 +- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d5c810a8cc52..60bf9b25d07f 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -236,6 +236,16 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn return 0; } +static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) +{ + size_t size; + + size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); + dma_free_coherent(dev, size, + wcn_ch->cpu_addr, + wcn_ch->dma_addr); +} + static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, struct wcn36xx_dxe_mem_pool *pool) { @@ -722,7 +732,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + if (ret) { + dev_err(wcn->dev, "Error allocating descriptor\n"); + return ret; + } wcn36xx_dxe_init_tx_bd(>dxe_tx_l_ch, >data_mem_pool); /* Write channel head to a NEXT register */ @@ -740,7 +754,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + if (ret) { + dev_err(wcn->dev, "Error allocating descriptor\n"); + goto out_err_txh_ch; + } + wcn36xx_dxe_init_tx_bd(>dxe_tx_h_ch, >mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -760,7 +779,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + if (ret) { + dev_err(wcn->dev, "Error allocating descriptor\n"); + goto out_err_rxl_ch; + } + /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_l_ch); @@ -790,7 +814,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch); + if (ret) { + dev_err(wcn->dev, "Error allocating descriptor\n"); + goto out_err_rxh_ch; + } /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_h_ch); @@ -819,11 +847,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ret = wcn36xx_dxe_request_irqs(wcn); if (ret < 0) - goto out_err; + goto out_err_irq; return 0; -out_err: +out_err_irq: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_h_ch); +out_err_rxh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_l_ch); +out_err_rxl_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_h_ch); +out_err_txh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_l_ch); + return ret; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: wcn36xx: release resources in case of error
On 1/22/2018 8:14 AM, Kalle Valo wrote: > Ramon Fried <rfr...@codeaurora.org> wrote: > >> wcn36xx_dxe_init() doesn't check for the return value >> of wcn36xx_dxe_init_descs(). >> This patch releases the resources in case an error ocurred. >> >> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> > Doesn't compile: Sorry Kalle, I mistakenly sent the wrong version of the patch :( I will sent the correct one shortly. > > drivers/net/wireless/ath/wcn36xx/dxe.c: In function > ‘wcn36xx_dxe_deinit_descs’: > drivers/net/wireless/ath/wcn36xx/dxe.c:243:15: error: ‘struct wcn36xx_dxe_ch’ > has no member named ‘desc_bum’ > size = wcn_ch->desc_bum * sizeof(struct wcn36xx_dxe_desc); >^ > drivers/net/wireless/ath/wcn36xx/dxe.c:244:20: error: ‘wcn’ undeclared (first > use in this function) > dma_free_coherent(wcn->dev, size, > ^ > drivers/net/wireless/ath/wcn36xx/dxe.c:244:20: note: each undeclared > identifier is reported only once for each function it appears in > drivers/net/wireless/ath/wcn36xx/dxe.c: In function ‘wcn36xx_dxe_init’: > drivers/net/wireless/ath/wcn36xx/dxe.c:737:3: error: implicit declaration of > function ‘dev_error’ [-Werror=implicit-function-declaration] >dev_error("Error allocating descriptor\n"); >^ > drivers/net/wireless/ath/wcn36xx/dxe.c:818:2: error: expected ‘;’ before ‘if’ > if (ret) { > ^ > drivers/net/wireless/ath/wcn36xx/dxe.c:860:1: warning: label ‘out_err_txh_ch’ > defined but not used [-Wunused-label] > out_err_txh_ch: > ^ > drivers/net/wireless/ath/wcn36xx/dxe.c:856:1: warning: label ‘out_err_rxh_ch’ > defined but not used [-Wunused-label] > out_err_rxh_ch: > ^ > drivers/net/wireless/ath/wcn36xx/dxe.c:760:3: error: label ‘our_err_txh_ch’ > used but not defined >goto our_err_txh_ch; >^ > cc1: some warnings being treated as errors > make[5]: *** [drivers/net/wireless/ath/wcn36xx/dxe.o] Error 1 > make[4]: *** [drivers/net/wireless/ath/wcn36xx] Error 2 > make[3]: *** [drivers/net/wireless/ath] Error 2 > make[2]: *** [drivers/net/wireless] Error 2 > make[1]: *** [drivers/net] Error 2 > make[1]: *** Waiting for unfinished jobs > make: *** [drivers] Error 2 > > Patch set to Changes Requested. >
[PATCH] wcn36xx: release resources in case of error
wcn36xx_dxe_init() doesn't check for the return value of wcn36xx_dxe_init_descs(). This patch releases the resources in case an error ocurred. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 48 +- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d5c810a8cc52..dc7129edac96 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -236,6 +236,16 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn return 0; } +static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) +{ + size_t size; + + size = wcn_ch->desc_bum * sizeof(struct wcn36xx_dxe_desc); + dma_free_coherent(wcn->dev, size, + wcn_ch->cpu_addr, + wcn_ch->dma_addr); +} + static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, struct wcn36xx_dxe_mem_pool *pool) { @@ -722,7 +732,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + return ret; + } wcn36xx_dxe_init_tx_bd(>dxe_tx_l_ch, >data_mem_pool); /* Write channel head to a NEXT register */ @@ -740,7 +754,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto our_err_txh_ch; + } + wcn36xx_dxe_init_tx_bd(>dxe_tx_h_ch, >mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -760,7 +779,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxl_ch; + } + /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_l_ch); @@ -790,7 +814,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch) + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxh_ch; + } /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_h_ch); @@ -819,11 +847,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ret = wcn36xx_dxe_request_irqs(wcn); if (ret < 0) - goto out_err; + goto out_err_irq; return 0; -out_err: +out_err_irq: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_h_ch); +out_err_rxh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_l_ch); +out_err_rxl_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_h_ch); +out_err_txh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_l_ch); + return ret; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: release resources in case of error
wcn36xx_dxe_init() doesn't check for the return value of wcn36xx_dxe_init_descs(). This patch releases the resources in case an error ocurred. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 48 +- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d5c810a8cc52..dc7129edac96 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -236,6 +236,16 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn return 0; } +static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) +{ + size_t size; + + size = wcn_ch->desc_bum * sizeof(struct wcn36xx_dxe_desc); + dma_free_coherent(wcn->dev, size, + wcn_ch->cpu_addr, + wcn_ch->dma_addr); +} + static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, struct wcn36xx_dxe_mem_pool *pool) { @@ -722,7 +732,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + return ret; + } wcn36xx_dxe_init_tx_bd(>dxe_tx_l_ch, >data_mem_pool); /* Write channel head to a NEXT register */ @@ -740,7 +754,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto our_err_txh_ch; + } + wcn36xx_dxe_init_tx_bd(>dxe_tx_h_ch, >mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -760,7 +779,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxl_ch; + } + /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_l_ch); @@ -790,7 +814,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch) + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxh_ch; + } /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_h_ch); @@ -819,11 +847,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ret = wcn36xx_dxe_request_irqs(wcn); if (ret < 0) - goto out_err; + goto out_err_irq; return 0; -out_err: +out_err_irq: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_h_ch); +out_err_rxh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_l_ch); +out_err_rxl_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_h_ch); +out_err_txh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_l_ch); + return ret; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: release resources in case of error
wcn36xx_dxe_init() doesn't check for the return value of wcn36xx_dxe_init_descs(). This patch releases the resources in case an error ocurred. Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 48 +- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d5c810a8cc52..dc7129edac96 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -236,6 +236,16 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn return 0; } +static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) +{ + size_t size; + + size = wcn_ch->desc_bum * sizeof(struct wcn36xx_dxe_desc); + dma_free_coherent(wcn->dev, size, + wcn_ch->cpu_addr, + wcn_ch->dma_addr); +} + static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, struct wcn36xx_dxe_mem_pool *pool) { @@ -722,7 +732,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + return ret; + } wcn36xx_dxe_init_tx_bd(>dxe_tx_l_ch, >data_mem_pool); /* Write channel head to a NEXT register */ @@ -740,7 +754,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for TX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_tx_h_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto our_err_txh_ch; + } + wcn36xx_dxe_init_tx_bd(>dxe_tx_h_ch, >mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -760,7 +779,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX LOW channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_l_ch); + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxl_ch; + } + /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_l_ch); @@ -790,7 +814,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***/ /* Init descriptors for RX HIGH channel */ /***/ - wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn->dev, >dxe_rx_h_ch) + if (ret) { + dev_error("Error allocating descriptor\n"); + goto out_err_rxh_ch; + } /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, >dxe_rx_h_ch); @@ -819,11 +847,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ret = wcn36xx_dxe_request_irqs(wcn); if (ret < 0) - goto out_err; + goto out_err_irq; return 0; -out_err: +out_err_irq: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_h_ch); +out_err_rxh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_rx_l_ch); +out_err_rxl_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_h_ch); +out_err_txh_ch: + wcn36xx_dxe_deinit_descs(wcn->dev, >dxe_tx_l_ch); + return ret; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v2] wcn36xx: Fix dynamic power saving
On Mon, Dec 11, 2017 at 10:52:22AM +0200, Loic Poulain wrote: > Since driver does not report hardware dynamic power saving cap, > this is up to the mac80211 to manage power saving timeout and > state machine, using the ieee80211 config callback to report > PS changes. This patch enables/disables PS mode according to > the new configuration. > > Remove old behaviour enabling PS mode in a static way, this make > the device unusable when power save is enabled since device is > forced to PS regardless RX/TX traffic. > Hi. I tried to see if this patch solves the ping delay once power save is turned on and it appears it doesn't (log below). I do see some change in the delay though in comparison to testing without the patch. Bjorn, How did you test it ? Thanks, Ramon. root@dragonboard-410c:~# ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: seq=0 ttl=64 time=2.688 ms 64 bytes from 192.168.0.1: seq=1 ttl=64 time=1.593 ms 64 bytes from 192.168.0.1: seq=2 ttl=64 time=1.581 ms 64 bytes from 192.168.0.1: seq=3 ttl=64 time=1.466 ms 64 bytes from 192.168.0.1: seq=4 ttl=64 time=1.625 ms 64 bytes from 192.168.0.1: seq=5 ttl=64 time=1.620 ms 64 bytes from 192.168.0.1: seq=6 ttl=64 time=2.907 ms 64 bytes from 192.168.0.1: seq=7 ttl=64 time=1.426 ms 64 bytes from 192.168.0.1: seq=8 ttl=64 time=1.521 ms 64 bytes from 192.168.0.1: seq=9 ttl=64 time=1.543 ms 64 bytes from 192.168.0.1: seq=10 ttl=64 time=6.804 ms 64 bytes from 192.168.0.1: seq=11 ttl=64 time=1.562 ms 64 bytes from 192.168.0.1: seq=12 ttl=64 time=3.148 ms 64 bytes from 192.168.0.1: seq=13 ttl=64 time=1.568 ms 64 bytes from 192.168.0.1: seq=14 ttl=64 time=1.491 ms 64 bytes from 192.168.0.1: seq=15 ttl=64 time=2.884 ms 64 bytes from 192.168.0.1: seq=16 ttl=64 time=1.669 ms 64 bytes from 192.168.0.1: seq=17 ttl=64 time=1.556 ms 64 bytes from 192.168.0.1: seq=18 ttl=64 time=1.487 ms 64 bytes from 192.168.0.1: seq=19 ttl=64 time=1.377 ms 64 bytes from 192.168.0.1: seq=20 ttl=64 time=1.534 ms ^C --- 192.168.0.1 ping statistics --- 21 packets transmitted, 21 packets received, 0% packet loss round-trip min/avg/max = 1.377/2.050/6.804 ms root@dragonboard-410c:~# iw dev wlan0 set power_save on root@dragonboard-410c:~# ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: seq=0 ttl=64 time=4.849 ms 64 bytes from 192.168.0.1: seq=1 ttl=64 time=11.250 ms 64 bytes from 192.168.0.1: seq=2 ttl=64 time=11.402 ms 64 bytes from 192.168.0.1: seq=3 ttl=64 time=11.732 ms 64 bytes from 192.168.0.1: seq=4 ttl=64 time=10.076 ms 64 bytes from 192.168.0.1: seq=5 ttl=64 time=11.532 ms 64 bytes from 192.168.0.1: seq=6 ttl=64 time=15.479 ms 64 bytes from 192.168.0.1: seq=7 ttl=64 time=11.318 ms 64 bytes from 192.168.0.1: seq=8 ttl=64 time=13.299 ms 64 bytes from 192.168.0.1: seq=9 ttl=64 time=11.068 ms 64 bytes from 192.168.0.1: seq=10 ttl=64 time=11.087 ms 64 bytes from 192.168.0.1: seq=11 ttl=64 time=11.362 ms 64 bytes from 192.168.0.1: seq=12 ttl=64 time=11.341 ms 64 bytes from 192.168.0.1: seq=13 ttl=64 time=15.945 ms 64 bytes from 192.168.0.1: seq=14 ttl=64 time=11.318 ms 64 bytes from 192.168.0.1: seq=15 ttl=64 time=11.343 ms 64 bytes from 192.168.0.1: seq=16 ttl=64 time=11.378 ms 64 bytes from 192.168.0.1: seq=17 ttl=64 time=7.693 ms 64 bytes from 192.168.0.1: seq=18 ttl=64 time=11.703 ms 64 bytes from 192.168.0.1: seq=19 ttl=64 time=11.528 ms 64 bytes from 192.168.0.1: seq=20 ttl=64 time=12.008 ms 64 bytes from 192.168.0.1: seq=21 ttl=64 time=11.522 ms 64 bytes from 192.168.0.1: seq=22 ttl=64 time=12.949 ms 64 bytes from 192.168.0.1: seq=23 ttl=64 time=12.056 ms 64 bytes from 192.168.0.1: seq=24 ttl=64 time=13.097 ms 64 bytes from 192.168.0.1: seq=25 ttl=64 time=11.638 ms ^C --- 192.168.0.1 ping statistics --- > Acked-by: Bjorn Andersson> Signed-off-by: Loic Poulain > --- > v2: remove error msg on unbalanced bmps exit > return -EALREADY if not in bmps mode > > drivers/net/wireless/ath/wcn36xx/main.c | 23 --- > drivers/net/wireless/ath/wcn36xx/pmc.c | 6 -- > 2 files changed, 16 insertions(+), 13 deletions(-) > > diff --git a/drivers/net/wireless/ath/wcn36xx/main.c > b/drivers/net/wireless/ath/wcn36xx/main.c > index f0b4d43..436b8ea 100644 > --- a/drivers/net/wireless/ath/wcn36xx/main.c > +++ b/drivers/net/wireless/ath/wcn36xx/main.c > @@ -384,6 +384,18 @@ static int wcn36xx_config(struct ieee80211_hw *hw, > u32 changed) > } > } > > + if (changed & IEEE80211_CONF_CHANGE_PS) { > + list_for_each_entry(tmp, >vif_list, list) { > + vif = wcn36xx_priv_to_vif(tmp); > + if (hw->conf.flags & IEEE80211_CONF_PS) { > + if (vif->bss_conf.ps) /* ps allowed ? */ > + wcn36xx_pmc_enter_bmps_state(wcn, > vif); > + } else { > +
[PATCH v4] wcn36xx: Set default BTLE coexistence config
From: Eyal Ilsar <eil...@codeaurora.org> If the value for the firmware configuration parameters BTC_STATIC_LEN_LE_BT and BTC_STATIC_LEN_LE_WLAN are not set the duty cycle between BT and WLAN is such that if BT (including BLE) is active WLAN gets 0 bandwidth. When tuning these parameters having a too high value for WLAN means that BLE performance degrades. The "sweet" point of roughly half of the maximal values was empirically found to achieve a balance between BLE and Wi-Fi coexistence performance. Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 9c6590d5348a..6f1e741acf3e 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -73,6 +73,8 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = { WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v3] wcn36xx: Set default BTLE coexistence config
From: Eyal Ilsar <eil...@codeaurora.org> If the value for the firmware configuration parameters BTC_STATIC_LEN_LE_BT and BTC_STATIC_LEN_LE_WLAN are not set the duty cycle between BT and WLAN is such that if BT (including BLE) is active WLAN gets 0 bandwidth. When tuning these parameters having a too high value for WLAN means that BLE performance degrades. The "sweet" point of roughly half of the maximal values was empirically found to achieve a balance between BLE and Wi-Fi coexistence performance. Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/smd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 9c6590d5348a..1c7598752255 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -72,8 +72,10 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = { WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0), WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), - WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: Set BTLE coexistence related configuration values to defaults
From: Eyal Ilsar <eil...@codeaurora.org> If the value for the firmware configuration parameters BTC_STATIC_LEN_LE_BT and BTC_STATIC_LEN_LE_WLAN are not set the duty cycle between BT and WLAN is such that if BT (including BLE) is active WLAN gets 0 bandwidth. When tuning these parameters having a too high value for WLAN means that BLE performance degrades. The "sweet" point of roughly half of the maximal values was empirically found to achieve a balance between BLE and Wi-Fi coexistence performance. Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/smd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 9c6590d..1c75987 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -72,8 +72,10 @@ struct wcn36xx_cfg_val { WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0), WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), - WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] wcn36xx: Set BTLE coexistence related configuration values to defaults
From: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Eyal Ilsar <eil...@codeaurora.org> Signed-off-by: Ramon Fried <rfr...@codeaurora.org> --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- drivers/net/wireless/ath/wcn36xx/smd.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index b83f01d..0d4ed41 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -27,7 +27,7 @@ #include #include "wcn36xx.h" -unsigned int wcn36xx_dbg_mask; +unsigned int wcn36xx_dbg_mask = WCN36XX_DBG_NONE; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 9c6590d..1c75987 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -72,8 +72,10 @@ struct wcn36xx_cfg_val { WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0), WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), - WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project