Re: [PATCH V2 8/8] brcmfmac: disable command decode in sdio_aos
On 2018/11/12 下午 06:33, Arend van Spriel wrote: > On 11/12/2018 8:30 AM, Chi-Hsien Lin wrote: >> From: Wright Feng >> >> AOS is a part of the SDIOD core that becomes active when the rest of >> SDIOD is sleeping to keep SDIO bus alive responding to reduced set of >> commands. >> >> Transaction between AOS and SDIOD is not protected, and if cmd 52 is >> received in AOS and in the middle of response state changed from AOS to >> SDIOD, response is corrupted and it causes to SDIO Host controller to >> hang. > > Just one question. The above sound pretty generic so does it apply to > any SDIO chip with AOS logic? > We found this issue when verifying SR feature with some SDIO cards(what we had), not sure whether every SDIO card has same problem. So we only change those chip's wake-up mechanism to noCmdDecode mode and let SDIOD_AOS just generates a wake-up request without responding. -Wright > Regards, > Arend > > >
Re: [PATCH 1/5] brcmfmac: set apsta to 1 when AP start on primary interface.
On 2018/11/9 下午 08:48, Arend van Spriel wrote: > On 11/8/2018 4:48 AM, Chi-Hsien Lin wrote: >> From: Wright Feng >> >> APSTA can work on two band concurrently with using VSDB(Virtual >> Simultaneous Dual-Band) or RSDB(Real Simultaneous Dual-Band) features. >> In this case, we have to keep apsta is 1 in firmware side. However, if >> we start wpa_supplicant on wlan0 and then start hostapd on wlan 1, the >> apsta will be set to 0, and we will see data stall on wlan0(station) >> So that, we only set apsta to 1 when AP start on primary interface. > > The description makes my head spin. From reading the commit message I > think the code should add a !VSDB check instead of dropping the !RSDB > check. Would you agree? > > Regards, > Arend I will revise the commit message as below and add two checks (!MCHAN and !RSDB)in v2. Let me know if you have concern about that. When starting station mode on wlan0 and AP mode on wlan1, the apsta will be disabled and cause data stall on wlan0(station) The apsta feature with MCHAN(Multi-Channel Concurrent) or RSDB(Real Simultaneous Dual-Band) can make STA+AP work on two bands concurrently. Because of that, we keep apsta enabled if firmware supports MCHAN or RSDB features. - Wright > >> Signed-off-by: Wright Feng >> Signed-off-by: Chi-Hsien Lin >> --- >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 +--- >> 1 file changed, 1 insertion(+), 3 deletions(-) >
Re: [PATCH 2/5] brcmfmac: remove "arp_hostip_clear" from "brcmf_netdev_stop"
On 2018/11/9 上午 03:19, Franky Lin wrote: > On Wed, Nov 7, 2018 at 7:48 PM Chi-Hsien Lin > wrote: >> >> From: Wright Feng >> >> The firmware does not respond ARP request and causes ping failure with >> following steps: >> >> 1. Bring up interface >> ifconfig wlan0 up or start wpa_supplicant >> 2. Set the IP address >> ifconfig wlan0 192.168.100.10 >> 3. Bring down interface or >> ifconfig wlan0 down or kill wpa_supplicant >> 4. Bring up interface again and set the same IP address >> 5. Connect to AP(192.168.100.1) and ping to AP will be failed. >> >> FMAC clears arp_hostip when bringing down the interface, but not set it >> back if setting the same IP address. We are able to see the IP address >> in interface info(inconfig wlan0) but the ping still cannot work because >> the firmware ARP offload does not respond the ARP request. >> Because of that, we remove "arp_hostip_clear" from function >> "brcmf_netdev_stop" > > Shouldn't brcmf_inetaddr_changed get called when the interface up again? > > Thanks, > - Franky > The brcmf_inetaddr_changed only be called in inet_del_ifa and inet_insert_ifa. If the IP address is not changed when the interface up again, the brcmf_inetaddr_changed will not be called. -Wright >> >> Signed-off-by: Wright Feng >> Signed-off-by: Chi-Hsien Lin >> --- >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 -- >> 1 file changed, 2 deletions(-) >> >> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c >> index b1f702faff4f..e1666cf3801c 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c >> @@ -533,8 +533,6 @@ static int brcmf_netdev_stop(struct net_device *ndev) >> >> brcmf_cfg80211_down(ndev); >> >> - brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); >> - >> brcmf_net_setcarrier(ifp, false); >> >> return 0; >> -- >> 2.1.0 >> > > > -- > > You're receiving this message because you're a member of the > brcm80211-dev-list group. >
[PATCH v3 1/3] brcmfmac: add credit numbers updating support
The credit numbers are static and tunable per chip in firmware side. However the credit number may be changed that is based on packet pool length and will send BRCMF_E_FIFO_CREDIT_MAP event to notify host driver updates the credit numbers during interface up. The purpose of this patch is making host driver has ability of updating the credit numbers when receiving the BRCMF_E_FIFO_CREDIT_MAP event. Signed-off-by: Wright Feng --- v2: Replace brcmf_err with WARN_ONCE --- .../broadcom/brcm80211/brcmfmac/fwsignal.c| 23 --- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f3cbf78c8899..c75be2703b3e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -511,6 +511,7 @@ struct brcmf_fws_info { struct work_struct fws_dequeue_work; u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; int fifo_credit[BRCMF_FWS_FIFO_COUNT]; + int init_fifo_credit[BRCMF_FWS_FIFO_COUNT]; int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1]; int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; u32 fifo_credit_map; @@ -1237,6 +1238,9 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, } fws->fifo_credit[fifo] += credits; + if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo]) + fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo]; + } static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) @@ -1595,19 +1599,21 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, brcmf_err("event payload too small (%d)\n", e->datalen); return -EINVAL; } - if (fws->creditmap_received) - return 0; fws->creditmap_received = true; brcmf_dbg(TRACE, "enter: credits %pM\n", credits); brcmf_fws_lock(fws); for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { - if (*credits) + fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i]; + fws->init_fifo_credit[i] = credits[i]; + if (fws->fifo_credit[i] > 0) fws->fifo_credit_map |= 1 << i; else fws->fifo_credit_map &= ~(1 << i); - fws->fifo_credit[i] = *credits++; + WARN_ONCE(fws->fifo_credit[i] < 0, + "fifo_credit[%d] is negative(%d)\n", i, + fws->fifo_credit[i]); } brcmf_fws_schedule_deq(fws); brcmf_fws_unlock(fws); @@ -2013,7 +2019,7 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) } for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) { - if (fws->fifo_credit[lender_ac]) { + if (fws->fifo_credit[lender_ac] > 0) { fws->credits_borrowed[lender_ac]++; fws->fifo_credit[lender_ac]--; if (fws->fifo_credit[lender_ac] == 0) @@ -2210,8 +2216,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) } continue; } - while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && - (fifo == BRCMF_FWS_FIFO_BCMC))) { + while ((fws->fifo_credit[fifo] > 0) || + ((!fws->bcmc_credit_check) && + (fifo == BRCMF_FWS_FIFO_BCMC))) { skb = brcmf_fws_deq(fws, fifo); if (!skb) break; @@ -,7 +2229,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) break; } if ((fifo == BRCMF_FWS_FIFO_AC_BE) && - (fws->fifo_credit[fifo] == 0) && + (fws->fifo_credit[fifo] <= 0) && (!fws->bus_flow_blocked)) { while (brcmf_fws_borrow_credit(fws) == 0) { skb = brcmf_fws_deq(fws, fifo); -- 2.19.1
[PATCH v3 0/3] brcmfmac: throughput enhancement for flow control mode
The patches are for throughput enhancement with flow control mode enabled and introduce a new module parameter to enhance TX throughput as well. Changes since v2: - Add "brcmfmac: handle compressed tx status signal" in this series. - Enable frameburst mode in default instead of being a module parameter Changes since v1: - Remove the patch "calling skb_orphan before sending skb to SDIO bus" - Revise the patch "brcmfmac: add credit numbers updating support" Chung-Hsien Hsu (1): brcmfmac: handle compressed tx status signal Wright Feng (2): brcmfmac: add credit numbers updating support brcmfmac: enable frameburst mode in default firmware setting .../broadcom/brcm80211/brcmfmac/cfg80211.c| 4 + .../broadcom/brcm80211/brcmfmac/fwil.h| 1 + .../broadcom/brcm80211/brcmfmac/fwsignal.c| 144 +++--- 3 files changed, 91 insertions(+), 58 deletions(-) -- 2.19.1
[PATCH v3 2/3] brcmfmac: enable frameburst mode in default firmware setting
The frameburst feature can enable per-packet framebursting in firmware side and get higher TX throughput in High Throughput(HT) mode. To enhance TX throughput, we enable frameburst mode in default firmware setting. Signed-off-by: Wright Feng --- v3: Enable frameburst in default instead of being a module parameter --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 6 ++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 230a378c26fc..a7361d142a27 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6638,6 +6638,12 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) brcmf_configure_arp_nd_offload(ifp, true); + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); + if (err) { + brcmf_err("failed to set frameburst mode\n"); + goto default_conf_out; + } + cfg->dongle_up = true; default_conf_out: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 63b1287e2e6d..b6b183b18413 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -80,6 +80,7 @@ #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 #define BRCMF_C_SET_ASSOC_PREFER 205 #define BRCMF_C_GET_VALID_CHANNELS 217 +#define BRCMF_C_SET_FAKEFRAG 219 #define BRCMF_C_GET_KEY_PRIMARY235 #define BRCMF_C_SET_KEY_PRIMARY236 #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 -- 2.19.1
[PATCH v3 3/3] brcmfmac: handle compressed tx status signal
From: Chung-Hsien Hsu Firmware inform the driver about tx status by normal tx status signal or compressed tx status signal. This patch adds support to handle the compressed tx status signal. Signed-off-by: Chung-Hsien Hsu Signed-off-by: Chi-Hsien Lin Signed-off-by: Wright Feng --- v3: Add this patch into this series --- .../broadcom/brcm80211/brcmfmac/fwsignal.c| 121 ++ 1 file changed, 71 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index c75be2703b3e..02759ebd207c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -1455,9 +1455,10 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, static int brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, - u32 genbit, u16 seq) + u32 genbit, u16 seq, u8 compcnt) { u32 fifo; + u8 cnt = 0; int ret; bool remove_from_hanger = true; struct sk_buff *skb; @@ -1468,60 +1469,71 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, brcmf_dbg(DATA, "flags %d\n", flags); if (flags == BRCMF_FWS_TXSTATUS_DISCARD) - fws->stats.txs_discard++; + fws->stats.txs_discard += compcnt; else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) { - fws->stats.txs_supp_core++; + fws->stats.txs_supp_core += compcnt; remove_from_hanger = false; } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { - fws->stats.txs_supp_ps++; + fws->stats.txs_supp_ps += compcnt; remove_from_hanger = false; } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) - fws->stats.txs_tossed++; + fws->stats.txs_tossed += compcnt; else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) - fws->stats.txs_host_tossed++; + fws->stats.txs_host_tossed += compcnt; else brcmf_err("unexpected txstatus\n"); - ret = brcmf_fws_hanger_poppkt(>hanger, hslot, , - remove_from_hanger); - if (ret != 0) { - brcmf_err("no packet in hanger slot: hslot=%d\n", hslot); - return ret; - } + while (cnt < compcnt) { + ret = brcmf_fws_hanger_poppkt(>hanger, hslot, , + remove_from_hanger); + if (ret != 0) { + brcmf_err("no packet in hanger slot: hslot=%d\n", + hslot); + goto cont; + } - skcb = brcmf_skbcb(skb); - entry = skcb->mac; - if (WARN_ON(!entry)) { - brcmu_pkt_buf_free_skb(skb); - return -EINVAL; - } - entry->transit_count--; - if (entry->suppressed && entry->suppr_transit_count) - entry->suppr_transit_count--; + skcb = brcmf_skbcb(skb); + entry = skcb->mac; + if (WARN_ON(!entry)) { + brcmu_pkt_buf_free_skb(skb); + goto cont; + } + entry->transit_count--; + if (entry->suppressed && entry->suppr_transit_count) + entry->suppr_transit_count--; - brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags, - skcb->htod, seq); + brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, + flags, skcb->htod, seq); - /* pick up the implicit credit from this packet */ - fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); - if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) || - (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) || - (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) { - brcmf_fws_return_credits(fws, fifo, 1); - brcmf_fws_schedule_deq(fws); - } - brcmf_fws_macdesc_return_req_credit(skb); + /* pick up the implicit credit from this packet */ + fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); + if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT || + (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) || + flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) { + brcmf_fws_return_credits(fws, fifo, 1); + brcmf_fws_schedule_deq(fws); + } + brcmf_fws_macdesc_return_req_credit(skb); - ret = brcmf_proto_hdrpull(fws-
Re: [PATCH v2 2/2] brcmfmac: make firmware frameburst mode a module parameter
Arend van Spriel 於 11/2/2018 8:31 PM 寫道: > On 11/2/2018 9:24 AM, Wright Feng wrote: >> This patch is for adding a new module parameter "frameburst". >> With setting "frameburst=1" in module parameters, firmware frameburst >> mode >> will be enabled. The feature can enable per-packet framebursting in >> firmware side and get higher TX throughput in High Throughput(HT) mode. > > So why not always enable it in firmware as it seems to be the default in > recent firmware anyway. > > Regards, > Arend We don't have all the chips(some are not belong to Cypress) to do modification and verify them in our internal test, so the frameburst feature will not benefit to all firmwares. How about removing module parameter and setting frameburst to be default in host driver side? It will be good to all Linux supported chips and users. -Wright > >> Signed-off-by: Wright Feng >> --- >> .../net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +++ >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 5 + >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 2 ++ >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h | 1 + >> 4 files changed, 15 insertions(+) >> >> diff --git >> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c >> index 230a378c26fc..4a05d3f50cff 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c >> @@ -6638,6 +6638,13 @@ static s32 brcmf_config_dongle(struct >> brcmf_cfg80211_info *cfg) >> >> brcmf_configure_arp_nd_offload(ifp, true); >> >> + if (ifp->drvr->settings->frameburst) { >> + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); >> + if (err) >> + brcmf_info("setting frameburst mode failed\n"); >> + brcmf_dbg(INFO, "frameburst mode enabled\n"); >> + } >> + >> cfg->dongle_up = true; >> default_conf_out: >> >> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >> index 94044a7a6021..0ad4c3196e5d 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >> @@ -78,6 +78,10 @@ static int brcmf_iapp_enable; >> module_param_named(iapp, brcmf_iapp_enable, int, 0); >> MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted >> Inter-Access Point Protocol"); >> >> +static int brcmf_frameburst; >> +module_param_named(frameburst, brcmf_frameburst, int, 0); >> +MODULE_PARM_DESC(frameburst, "Enable firmware frameburst feature"); >> + >> #ifdef DEBUG >> /* always succeed brcmf_bus_started() */ >> static int brcmf_ignore_probe_fail; >> @@ -419,6 +423,7 @@ struct brcmf_mp_device >> *brcmf_get_module_param(struct device *dev, >> settings->fcmode = brcmf_fcmode; >> settings->roamoff = !!brcmf_roamoff; >> settings->iapp = !!brcmf_iapp_enable; >> + settings->frameburst = !!brcmf_frameburst; >> #ifdef DEBUG >> settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; >> #endif >> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h >> index a34642cb4d2f..b91975258a68 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h >> @@ -47,6 +47,7 @@ extern struct brcmf_mp_global_t brcmf_mp_global; >> * @feature_disable: Feature_disable bitmask. >> * @fcmode: FWS flow control. >> * @roamoff: Firmware roaming off? >> + * @frameburst: Firmware frame burst mode. >> * @ignore_probe_fail: Ignore probe failure. >> * @country_codes: If available, pointer to struct for translating >> country codes >> * @bus: Bus specific platform data. Only SDIO at the mmoment. >> @@ -57,6 +58,7 @@ struct brcmf_mp_device { >> int fcmode; >> bool roamoff; >> bool iapp; >> + bool frameburst; >> bool ignore_probe_fail; >> struct brcmfmac_pd_cc *country_codes; >> union { >> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h >> index 63b1287e2e6d..b6b183b18413 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h >> @@ -80,6 +80,7 @@ >> #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 >> #define BRCMF_C_SET_ASSOC_PREFER 205 >> #define BRCMF_C_GET_VALID_CHANNELS 217 >> +#define BRCMF_C_SET_FAKEFRAG 219 >> #define BRCMF_C_GET_KEY_PRIMARY 235 >> #define BRCMF_C_SET_KEY_PRIMARY 236 >> #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 >> >
Re: [PATCH 1/3] brcmfmac: calling skb_orphan before sending skb to SDIO bus
Franky Lin 於 11/3/2018 3:51 AM 寫道: > On Thu, Nov 1, 2018 at 8:08 PM Wright Feng wrote: >> >> >> >> On 2018/10/30 上午 02:50, Franky Lin wrote: >>> On Mon, Oct 29, 2018 at 3:27 AM Wright Feng wrote: >>>> >>>> Linux 3.6 introduces TSQ which has a per socket threshold for TCP Tx >>>> packets to reduce latency. In fcmode 1 and fcmode 2, host driver enqueues >>>> skb in hanger and TCP doesn't push new skb until host frees the skb when >>>> receiving fwstatus event. So using skb_orphan before sending skb to bus >>>> will make the skb removing the ownership of socket. With this patch, we >>>> are able to get better throughput in fcmode 1 and fcmode 2. >>>> >>>> Tested 43455 TCP throughput in 20 MHz bandwidth with / without this patch. >>>> fcmode 0: 59.5 / 59.6 (mbps) >>>> fcmode 1: 59.3 / 23.4 (mbps) >>>> fcmode 2: 59.6 / 21.5 (mbps) >>>> >>>> Signed-off-by: Wright Feng >>>> --- >>>>drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + >>>>1 file changed, 1 insertion(+) >>>> >>>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >>>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >>>> index b2e1ab5..519b25d 100644 >>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >>>> @@ -2298,6 +2298,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio >>>> *bus, uint maxframes) >>>> _out); >>>> if (pkt == NULL) >>>> break; >>>> + skb_orphan(pkt); >>> >>> TSQ allows device driver to tweak for a deeper queue now. [1]. We >>> should use that instead of orphaning the packet before handing over to >>> firmware which would remove the bufferbloat protection by TSQ. >>> >>> Thanks, >>> -Franky >>> >> Since the aggregation problem has been fixed by setting sk_pacing_shift, >> I will submit v2 without this one. >> Thanks for the information. > > No the problem is not fixed. The patch just provides an interface > sk_pacing_shift_update so the device driver can tweak the scale to > allow more packets being queued. You need to call > sk_pacing_shift_update somewhere in brcmfmac. > > Thanks, > -Franky We are still implementing the function of setting sk_pacing_shift in brcmfmac, so the patch will be submitted in another patch series once we have done the fully tests. -Wright >> >> -Wright >>> [1] >>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3a9b76fd0db9f >>> >>>> __skb_queue_tail(, pkt); >>>> } >>>> spin_unlock_bh(>txq_lock); >>>> -- >>>> 1.9.1 >>>>
[PATCH v2 2/2] brcmfmac: make firmware frameburst mode a module parameter
This patch is for adding a new module parameter "frameburst". With setting "frameburst=1" in module parameters, firmware frameburst mode will be enabled. The feature can enable per-packet framebursting in firmware side and get higher TX throughput in High Throughput(HT) mode. Signed-off-by: Wright Feng --- .../net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c| 7 +++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 5 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 2 ++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h| 1 + 4 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 230a378c26fc..4a05d3f50cff 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6638,6 +6638,13 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) brcmf_configure_arp_nd_offload(ifp, true); + if (ifp->drvr->settings->frameburst) { + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); + if (err) + brcmf_info("setting frameburst mode failed\n"); + brcmf_dbg(INFO, "frameburst mode enabled\n"); + } + cfg->dongle_up = true; default_conf_out: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 94044a7a6021..0ad4c3196e5d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -78,6 +78,10 @@ static int brcmf_iapp_enable; module_param_named(iapp, brcmf_iapp_enable, int, 0); MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); +static int brcmf_frameburst; +module_param_named(frameburst, brcmf_frameburst, int, 0); +MODULE_PARM_DESC(frameburst, "Enable firmware frameburst feature"); + #ifdef DEBUG /* always succeed brcmf_bus_started() */ static int brcmf_ignore_probe_fail; @@ -419,6 +423,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, settings->fcmode = brcmf_fcmode; settings->roamoff = !!brcmf_roamoff; settings->iapp = !!brcmf_iapp_enable; + settings->frameburst = !!brcmf_frameburst; #ifdef DEBUG settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; #endif diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index a34642cb4d2f..b91975258a68 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -47,6 +47,7 @@ extern struct brcmf_mp_global_t brcmf_mp_global; * @feature_disable: Feature_disable bitmask. * @fcmode: FWS flow control. * @roamoff: Firmware roaming off? + * @frameburst: Firmware frame burst mode. * @ignore_probe_fail: Ignore probe failure. * @country_codes: If available, pointer to struct for translating country codes * @bus: Bus specific platform data. Only SDIO at the mmoment. @@ -57,6 +58,7 @@ struct brcmf_mp_device { int fcmode; boolroamoff; booliapp; + boolframeburst; boolignore_probe_fail; struct brcmfmac_pd_cc *country_codes; union { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 63b1287e2e6d..b6b183b18413 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -80,6 +80,7 @@ #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 #define BRCMF_C_SET_ASSOC_PREFER 205 #define BRCMF_C_GET_VALID_CHANNELS 217 +#define BRCMF_C_SET_FAKEFRAG 219 #define BRCMF_C_GET_KEY_PRIMARY235 #define BRCMF_C_SET_KEY_PRIMARY236 #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 -- 2.19.1
[PATCH v2 1/2] brcmfmac: add credit numbers updating support
The credit numbers are static and tunable per chip in firmware side. However the credit number may be changed that is based on packet pool length and will send BRCMF_E_FIFO_CREDIT_MAP event to notify host driver updates the credit numbers during interface up. The purpose of this patch is making host driver has ability of updating the credit numbers when receiving the BRCMF_E_FIFO_CREDIT_MAP event. Signed-off-by: Wright Feng --- v2: replace brcmf_err with WARN_ONCE --- .../broadcom/brcm80211/brcmfmac/fwsignal.c| 23 --- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f3cbf78c8899..c75be2703b3e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -511,6 +511,7 @@ struct brcmf_fws_info { struct work_struct fws_dequeue_work; u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; int fifo_credit[BRCMF_FWS_FIFO_COUNT]; + int init_fifo_credit[BRCMF_FWS_FIFO_COUNT]; int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1]; int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; u32 fifo_credit_map; @@ -1237,6 +1238,9 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, } fws->fifo_credit[fifo] += credits; + if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo]) + fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo]; + } static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) @@ -1595,19 +1599,21 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, brcmf_err("event payload too small (%d)\n", e->datalen); return -EINVAL; } - if (fws->creditmap_received) - return 0; fws->creditmap_received = true; brcmf_dbg(TRACE, "enter: credits %pM\n", credits); brcmf_fws_lock(fws); for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { - if (*credits) + fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i]; + fws->init_fifo_credit[i] = credits[i]; + if (fws->fifo_credit[i] > 0) fws->fifo_credit_map |= 1 << i; else fws->fifo_credit_map &= ~(1 << i); - fws->fifo_credit[i] = *credits++; + WARN_ONCE(fws->fifo_credit[i] < 0, + "fifo_credit[%d] is negative(%d)\n", i, + fws->fifo_credit[i]); } brcmf_fws_schedule_deq(fws); brcmf_fws_unlock(fws); @@ -2013,7 +2019,7 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) } for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) { - if (fws->fifo_credit[lender_ac]) { + if (fws->fifo_credit[lender_ac] > 0) { fws->credits_borrowed[lender_ac]++; fws->fifo_credit[lender_ac]--; if (fws->fifo_credit[lender_ac] == 0) @@ -2210,8 +2216,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) } continue; } - while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && - (fifo == BRCMF_FWS_FIFO_BCMC))) { + while ((fws->fifo_credit[fifo] > 0) || + ((!fws->bcmc_credit_check) && + (fifo == BRCMF_FWS_FIFO_BCMC))) { skb = brcmf_fws_deq(fws, fifo); if (!skb) break; @@ -,7 +2229,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) break; } if ((fifo == BRCMF_FWS_FIFO_AC_BE) && - (fws->fifo_credit[fifo] == 0) && + (fws->fifo_credit[fifo] <= 0) && (!fws->bus_flow_blocked)) { while (brcmf_fws_borrow_credit(fws) == 0) { skb = brcmf_fws_deq(fws, fifo); -- 2.19.1
[PATCH v2 0/2] brcmfmac: throughput enhancement for flow control mode
The patches are for throughput enhancement with flow control mode enabled and introduce a new module parameter to enhance TX throughput as well. Changes since v1: Remove the patch "calling skb_orphan before sending skb to SDIO bus" Revise the patch "brcmfmac: add credit numbers updating support" Wright Feng (2): brcmfmac: add credit numbers updating support brcmfmac: make firmware frameburst mode a module parameter .../broadcom/brcm80211/brcmfmac/cfg80211.c| 7 ++ .../broadcom/brcm80211/brcmfmac/common.c | 5 .../broadcom/brcm80211/brcmfmac/common.h | 2 ++ .../broadcom/brcm80211/brcmfmac/fwil.h| 1 + .../broadcom/brcm80211/brcmfmac/fwsignal.c| 23 --- 5 files changed, 30 insertions(+), 8 deletions(-) -- 2.19.1
Re: [PATCH 2/3] brcmfmac: add credit numbers updating support
On 2018/10/30 下午 07:04, Arend van Spriel wrote: > On 10/29/2018 11:27 AM, Wright Feng wrote: >> The credit numbers are static and tunable per chip in firmware side. >> However the credit number may be changed that is based on packet pool >> length and will send BRCMF_E_FIFO_CREDIT_MAP event to notify host driver >> updates the credit numbers during interface up. >> The purpose of this patch is making host driver has ability of updating >> the credit numbers when receiving the BRCMF_E_FIFO_CREDIT_MAP event. > > Reviewed-by: Arend van Spriel >> Signed-off-by: Wright Feng >> --- >> .../broadcom/brcm80211/brcmfmac/fwsignal.c | 23 >> ++ >> 1 file changed, 15 insertions(+), 8 deletions(-) >> >> diff --git >> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c >> index f3cbf78..e0910c5 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c > > [...] > >> @@ -1595,19 +1599,21 @@ static int brcmf_fws_notify_credit_map(struct >> brcmf_if *ifp, >> brcmf_err("event payload too small (%d)\n", e->datalen); >> return -EINVAL; >> } >> - if (fws->creditmap_received) >> - return 0; >> >> fws->creditmap_received = true; > > I think the creditmap_received struct member is no longer needed. I will keep this because we still need it for checking whether flow control is active or not. > >> brcmf_dbg(TRACE, "enter: credits %pM\n", credits); >> brcmf_fws_lock(fws); >> for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { >> - if (*credits) >> + fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i]; >> + fws->init_fifo_credit[i] = credits[i]; >> + if (fws->fifo_credit[i] > 0) >> fws->fifo_credit_map |= 1 << i; >> else >> fws->fifo_credit_map &= ~(1 << i); >> - fws->fifo_credit[i] = *credits++; >> + if (fws->fifo_credit[i] < 0) >> + brcmf_err("fifo_credit[%d] value is negative(%d)\n", >> + i, fws->fifo_credit[i]); > > This looks like it should not happen so maybe warrants a WARN or WARN_ONCE? I will replace those 2 lines with WARN_ONCE. Thanks for the suggestion. -Wright > >> } >> brcmf_fws_schedule_deq(fws); >> brcmf_fws_unlock(fws); >
Re: [PATCH 3/3] brcmfmac: make firmware frameburst mode a module parameter
On 2018/10/30 下午 07:33, Arend van Spriel wrote: > On 10/29/2018 11:27 AM, Wright Feng wrote: >> This patch is for adding a new module parameter "frameburst". >> With setting "frameburst=1" in module parameters, firmware frameburst >> mode >> will be enabled. The feature can enable per-packet framebursting in >> firmware side and get higher TX throughput in High Throughput(HT) mode. > > I am not sure about every firmware image, but in recent branches here I > see firmware enables frameburst by default. So not sure about the > motivation to add this. You could also consider adding this to the > nl80211 api. I am sure other vendors have similar features. > > Regards, > Arend > The newer firmware may set firmware by default, but Some firmwares in upstream do not, like 7.35.349.28 for 4354-sdio. Before adding new API in ops and ATTR in nl80211, I think keeping the frameburst module parameter is good for user to enhance TX throughput. And I will find time to add new API after finishing my internal task. -Wright >> Signed-off-by: Wright Feng >> --- >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +++ >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 5 + >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 2 ++ >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h | 1 + >> 4 files changed, 15 insertions(+) >
Re: [PATCH 1/3] brcmfmac: calling skb_orphan before sending skb to SDIO bus
On 2018/10/30 上午 02:50, Franky Lin wrote: > On Mon, Oct 29, 2018 at 3:27 AM Wright Feng wrote: >> >> Linux 3.6 introduces TSQ which has a per socket threshold for TCP Tx >> packets to reduce latency. In fcmode 1 and fcmode 2, host driver enqueues >> skb in hanger and TCP doesn't push new skb until host frees the skb when >> receiving fwstatus event. So using skb_orphan before sending skb to bus >> will make the skb removing the ownership of socket. With this patch, we >> are able to get better throughput in fcmode 1 and fcmode 2. >> >> Tested 43455 TCP throughput in 20 MHz bandwidth with / without this patch. >> fcmode 0: 59.5 / 59.6 (mbps) >> fcmode 1: 59.3 / 23.4 (mbps) >> fcmode 2: 59.6 / 21.5 (mbps) >> >> Signed-off-by: Wright Feng >> --- >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >> index b2e1ab5..519b25d 100644 >> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c >> @@ -2298,6 +2298,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio >> *bus, uint maxframes) >>_out); >> if (pkt == NULL) >> break; >> + skb_orphan(pkt); > > TSQ allows device driver to tweak for a deeper queue now. [1]. We > should use that instead of orphaning the packet before handing over to > firmware which would remove the bufferbloat protection by TSQ. > > Thanks, > -Franky > Since the aggregation problem has been fixed by setting sk_pacing_shift, I will submit v2 without this one. Thanks for the information. -Wright > [1] > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3a9b76fd0db9f > >> __skb_queue_tail(, pkt); >> } >> spin_unlock_bh(>txq_lock); >> -- >> 1.9.1 >>
[PATCH 3/3] brcmfmac: make firmware frameburst mode a module parameter
This patch is for adding a new module parameter "frameburst". With setting "frameburst=1" in module parameters, firmware frameburst mode will be enabled. The feature can enable per-packet framebursting in firmware side and get higher TX throughput in High Throughput(HT) mode. Signed-off-by: Wright Feng --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 5 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 2 ++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h | 1 + 4 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 230a378..4a05d3f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6638,6 +6638,13 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) brcmf_configure_arp_nd_offload(ifp, true); + if (ifp->drvr->settings->frameburst) { + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); + if (err) + brcmf_info("setting frameburst mode failed\n"); + brcmf_dbg(INFO, "frameburst mode enabled\n"); + } + cfg->dongle_up = true; default_conf_out: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 94044a7..0ad4c31 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -78,6 +78,10 @@ module_param_named(iapp, brcmf_iapp_enable, int, 0); MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); +static int brcmf_frameburst; +module_param_named(frameburst, brcmf_frameburst, int, 0); +MODULE_PARM_DESC(frameburst, "Enable firmware frameburst feature"); + #ifdef DEBUG /* always succeed brcmf_bus_started() */ static int brcmf_ignore_probe_fail; @@ -419,6 +423,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, settings->fcmode = brcmf_fcmode; settings->roamoff = !!brcmf_roamoff; settings->iapp = !!brcmf_iapp_enable; + settings->frameburst = !!brcmf_frameburst; #ifdef DEBUG settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; #endif diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index a34642c..b919752 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -47,6 +47,7 @@ struct brcmf_mp_global_t { * @feature_disable: Feature_disable bitmask. * @fcmode: FWS flow control. * @roamoff: Firmware roaming off? + * @frameburst: Firmware frame burst mode. * @ignore_probe_fail: Ignore probe failure. * @country_codes: If available, pointer to struct for translating country codes * @bus: Bus specific platform data. Only SDIO at the mmoment. @@ -57,6 +58,7 @@ struct brcmf_mp_device { int fcmode; boolroamoff; booliapp; + boolframeburst; boolignore_probe_fail; struct brcmfmac_pd_cc *country_codes; union { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 63b1287..b6b183b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -80,6 +80,7 @@ #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 #define BRCMF_C_SET_ASSOC_PREFER 205 #define BRCMF_C_GET_VALID_CHANNELS 217 +#define BRCMF_C_SET_FAKEFRAG 219 #define BRCMF_C_GET_KEY_PRIMARY235 #define BRCMF_C_SET_KEY_PRIMARY236 #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 -- 1.9.1
[PATCH 0/3] brcmfmac: throughput enhancement for SDIO and flow control mode
These are for throughput enhancement with SDIO bus or with flow control mode enabled, and also introuce a new module parameter to enhance TX throughput as well. Wright Feng (3): brcmfmac: calling skb_orphan before sending skb to SDIO bus brcmfmac: add credit numbers updating support brcmfmac: make firmware frameburst mode a module parameter .../broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 + .../wireless/broadcom/brcm80211/brcmfmac/common.h | 2 ++ .../wireless/broadcom/brcm80211/brcmfmac/fwil.h| 1 + .../broadcom/brcm80211/brcmfmac/fwsignal.c | 23 ++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 1 + 6 files changed, 31 insertions(+), 8 deletions(-) -- 1.9.1
[PATCH 1/3] brcmfmac: calling skb_orphan before sending skb to SDIO bus
Linux 3.6 introduces TSQ which has a per socket threshold for TCP Tx packets to reduce latency. In fcmode 1 and fcmode 2, host driver enqueues skb in hanger and TCP doesn't push new skb until host frees the skb when receiving fwstatus event. So using skb_orphan before sending skb to bus will make the skb removing the ownership of socket. With this patch, we are able to get better throughput in fcmode 1 and fcmode 2. Tested 43455 TCP throughput in 20 MHz bandwidth with / without this patch. fcmode 0: 59.5 / 59.6 (mbps) fcmode 1: 59.3 / 23.4 (mbps) fcmode 2: 59.6 / 21.5 (mbps) Signed-off-by: Wright Feng --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index b2e1ab5..519b25d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -2298,6 +2298,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) _out); if (pkt == NULL) break; + skb_orphan(pkt); __skb_queue_tail(, pkt); } spin_unlock_bh(>txq_lock); -- 1.9.1
[PATCH 2/3] brcmfmac: add credit numbers updating support
The credit numbers are static and tunable per chip in firmware side. However the credit number may be changed that is based on packet pool length and will send BRCMF_E_FIFO_CREDIT_MAP event to notify host driver updates the credit numbers during interface up. The purpose of this patch is making host driver has ability of updating the credit numbers when receiving the BRCMF_E_FIFO_CREDIT_MAP event. Signed-off-by: Wright Feng --- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 23 ++ 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f3cbf78..e0910c5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -511,6 +511,7 @@ struct brcmf_fws_info { struct work_struct fws_dequeue_work; u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; int fifo_credit[BRCMF_FWS_FIFO_COUNT]; + int init_fifo_credit[BRCMF_FWS_FIFO_COUNT]; int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1]; int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; u32 fifo_credit_map; @@ -1237,6 +1238,9 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, } fws->fifo_credit[fifo] += credits; + if (fws->fifo_credit[fifo] > fws->init_fifo_credit[fifo]) + fws->fifo_credit[fifo] = fws->init_fifo_credit[fifo]; + } static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) @@ -1595,19 +1599,21 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, brcmf_err("event payload too small (%d)\n", e->datalen); return -EINVAL; } - if (fws->creditmap_received) - return 0; fws->creditmap_received = true; brcmf_dbg(TRACE, "enter: credits %pM\n", credits); brcmf_fws_lock(fws); for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { - if (*credits) + fws->fifo_credit[i] += credits[i] - fws->init_fifo_credit[i]; + fws->init_fifo_credit[i] = credits[i]; + if (fws->fifo_credit[i] > 0) fws->fifo_credit_map |= 1 << i; else fws->fifo_credit_map &= ~(1 << i); - fws->fifo_credit[i] = *credits++; + if (fws->fifo_credit[i] < 0) + brcmf_err("fifo_credit[%d] value is negative(%d)\n", + i, fws->fifo_credit[i]); } brcmf_fws_schedule_deq(fws); brcmf_fws_unlock(fws); @@ -2013,7 +2019,7 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) } for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) { - if (fws->fifo_credit[lender_ac]) { + if (fws->fifo_credit[lender_ac] > 0) { fws->credits_borrowed[lender_ac]++; fws->fifo_credit[lender_ac]--; if (fws->fifo_credit[lender_ac] == 0) @@ -2210,8 +2216,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) } continue; } - while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && - (fifo == BRCMF_FWS_FIFO_BCMC))) { + while ((fws->fifo_credit[fifo] > 0) || + ((!fws->bcmc_credit_check) && + (fifo == BRCMF_FWS_FIFO_BCMC))) { skb = brcmf_fws_deq(fws, fifo); if (!skb) break; @@ -,7 +2229,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) break; } if ((fifo == BRCMF_FWS_FIFO_AC_BE) && - (fws->fifo_credit[fifo] == 0) && + (fws->fifo_credit[fifo] <= 0) && (!fws->bus_flow_blocked)) { while (brcmf_fws_borrow_credit(fws) == 0) { skb = brcmf_fws_deq(fws, fifo); -- 1.9.1
[PATCH v4] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware(), and then driver got failed when bringing up legacy chips. We expect the CLM blob file for legacy chip is not existence in firmware path, but the -ENOENT error is transferred to -EAGAIN in firmware_class.c with user helper. Because of that, we continue with CLM data currently present in firmware if getting error from doing request_firmware(). Cc: sta...@vger.kernel.org # v4.15.y Reviewed-by: Arend van Spriel <arend.vanspr...@broadcom.com> Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: remove retry from patch v1 v3: remove redundant log print v4: modify log print --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..9be0b05 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { - if (err == -ENOENT) { - brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); - return 0; - } - brcmf_err("request CLM blob file failed (%d)\n", err); - return err; + brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n", + err); + return 0; } chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); -- 1.9.1
[PATCH v3] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware(), and then driver got failed when bringing up legacy chips. We expect the CLM blob file for legacy chip is not existence in firmware path, but the -ENOENT error is transferred to -EAGAIN in firmware_class.c with user helper. Because of that, we continue with CLM data currently present in firmware if getting error from doing request_firmware(). Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: remove retry from patch v1 v3: remove redundant log print --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..b0ef0e7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { - if (err == -ENOENT) { - brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); - return 0; - } - brcmf_err("request CLM blob file failed (%d)\n", err); - return err; + brcmf_info("no clm_blob available(%d), device may have limited channels available\n", + err); + return 0; } chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); -- 1.9.1
Re: [PATCH v2] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
On 2018/1/16 上午 03:54, Arend van Spriel wrote: On 1/15/2018 11:09 AM, Wright Feng wrote: [...] --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..aaab0e6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,12 +182,12 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { -if (err == -ENOENT) { -brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); -return 0; -} -brcmf_err("request CLM blob file failed (%d)\n", err); -return err; +if (err == -ENOENT || err == -EAGAIN) +brcmf_info("continue with CLM data in FW\n"); +else +brcmf_err("request clm_blob failed(%d) continue with CLM data in FW\n", + err); Don't see much value in doing it this way. Either way we need to inform the user about the consequence of this, ie.: brcmf_info("no clm_blob available (%d). device may have limited channels available\n", err); +return 0; } Regards, Arend Thanks for the comment, I will post patch v3 with your suggestion later. The patch will include one brcmf_info print and returning 0 regardless of errors from request_firmware. Regards, Wright
Re: [PATCH v2] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
On 2018/1/12 下午 07:16, Kalle Valo wrote: Arend van Spriel <arend.vanspr...@broadcom.com> writes: On 1/12/2018 8:44 AM, Wright Feng wrote: For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware() for blob file. _Why_ is the -EAGAIN returned? Is it because of user space, due to timing when loading the brcmfmac module or what? You should explain the problem in detail in the commit log and why this is the right approach to fix the problem. Based on the commit log to me this still looks like a random attempt to workaround a bug, not a proper fix. It is not about the timing issue, it is about "the clm blob is not existence in firmware path for legacy firmware with CLM data built-in" and the -ENOENT error is transferred to -EAGAIN in firmware_class.c. Here is explanation of -EAGAIN returned in detail. In drivers/base/firmware_class.c:__fw_state_wait_common, it returns -ENOENT to indicate the clm_blob file is not found via user helper. However, in drivers/base/firmware_class.c:_request_firmware_load, all errors with fw status aborted are transferred to: 1. -ERESTARTSYS: The signal is pending and the task is interruptible. Before 76098b36b5db ("firmware: send -EINTR on signal abort on fallback mechanism"), all errors with fw status aborted are transferred to -EAGAIN. 2. -EAGAIN: All others fw status aborted(include -ENOENT) except for -ERESTARTSYS. And that's why I handle -EAGAIN error to let driver using CLM data in firmware. In this case, brcmf_bus_started gets error and failed to bring up legacy chips. Because of that, we should continue with CLM data currently present in firmware if getting -EAGAIN when doing request_firmware(). Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: remove retry from patch v1 --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..0baab4c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,7 +182,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { - if (err == -ENOENT) { + if (err == -ENOENT || err == -EAGAIN) { brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); return 0; } Why don't we just fall-back to "CLM in firmware" regardless of the error code? Indeed, I was thinking the same. For the firmwares with CLM data built-in, it is okay to continue the bringing-up flow. But when users put clm_blob file to firmware path, the corresponding firmware may not have CLM data built-in. If we fall-back to use empty CLM data in firmware when hitting other errors like "-ENOMEM" or "-EINTR", the country code revision will be null and users will meet error when trying to connect to access point. It is fine to fall-back to "CLM in firmware" regardless of the error code, but it would be better to print error log to indicate the error if the returned error codes are not what we expected. Please let me know your opinion of below commit log and diff, if it is okay to you, I will post Patch v3 later. For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware() for blob file. So, it got failed when bring up legacy chips. We expect the CLM blob files is not existence in firmware path, however the -ENOENT error is transferred to -EAGAIN in firmware_class.c. Because of that, we continue with CLM data currently present in firmware if getting error in doing request_firmware(). --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..aaab0e6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,12 +182,12 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { - if (err == -ENOENT) { - brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); - return 0; - } - brcmf_err("request CLM blob file failed (%d)\n", err); - return err; + if (err == -ENOENT || err == -EAGAIN) + brcmf_info("continue with CLM data in FW\n"); +
[PATCH v2] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware() for blob file. In this case, brcmf_bus_started gets error and failed to bring up legacy chips. Because of that, we should continue with CLM data currently present in firmware if getting -EAGAIN when doing request_firmware(). Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: remove retry from patch v1 --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..0baab4c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,7 +182,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(, clm_name, dev); if (err) { - if (err == -ENOENT) { + if (err == -ENOENT || err == -EAGAIN) { brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); return 0; } -- 1.9.1
[PATCH v2] brcmfmac: Support 43455 save-restore (SR) feature if FW include -sr
From: Double Lo <double...@cypress.com> This patch will add 43455 into the save-restore(SR) capable chip list, so the SR engine will be enabled with 43455 FW which built-in the -sr function. Signed-off-by: Double Lo <double...@cypress.com> Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: Add Wright's signed-off-by --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index c5d1a1c..f7b30ce 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1338,6 +1338,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) switch (pub->chip) { case BRCM_CC_4354_CHIP_ID: case BRCM_CC_4356_CHIP_ID: + case BRCM_CC_4345_CHIP_ID: /* explicitly check SR engine enable bit */ pmu_cc3_mask = BIT(2); /* fall-through */ -- 1.9.1
Re: brcmfmac: Support 43455 save-restore (SR) feature if FW include -sr
On 2017/12/14 下午 08:39, Kalle Valo wrote: Wright Feng <wright.f...@cypress.com> wrote: From: Double Lo <double...@cypress.com> This patch will add 43455 into the save-restore(SR) capable chip list, so the SR engine will be enabled with 43455 FW which built-in the -sr function. Signed-off-by: Double Lo <double...@cypress.com> Signed-off-by: Wright Feng <wright.f...@cypress.com> Wright's s-o-b is missing: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#signed-off-by_missing Kalle, Thanks for reminding, please let me know if I have to send [Patch v2] for this.
Re: [PATCH] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
Hi Kalle, On 2017/12/12 下午 08:57, Kalle Valo wrote: Wright Feng <wright.f...@cypress.com> writes: For legacy chips w/o CLM blob files, kernel with user helper function enables returns -EAGAIN when we request_firmware() for blob file: "request_firmware() -> _request_firmware() -> fw_load_from_user_helper() -> _request_firmware_load() -> retval=-EAGAIN" We should do one more retry Who says that we should do one more retry? and continue brcmf_c_process_clm_blob if getting -EAGAIN from request_firmware function. Signed-off-by: Wright Feng <wright.f...@cypress.com> [...] @@ -180,11 +183,18 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) return err; } - err = request_firmware(, clm_name, dev); + do { + err = request_firmware(, clm_name, dev); + } while (err == -EAGAIN && retries++ < CLM_LOAD_RETRIES); This looks like a REALLY ugly workaround, please think three times before submitting something like this. And if you still decide to submit it, put a good effort on the commit log to explain why the hack would be acceptable. Have you investigated why you are getting the -EGAIN, user space not ready during boot or something like that? I didn't notice below commit 76098b36b5db ("firmware: send -EINTR on signal abort on fallback mechanism") has been merged on July 2017, sorry for that. Before commit 76098b36b5db, user helper sent -EAGAIN for all errors including "getting interrupted" and "file not found". The one more retry was for the sysfs got interrupted, and what we expected was the driver should get "-EAGAIN" when clm blob file was not found for legacy wifi chip. Since commit 76098b36b5db changed the error code for interrupted, I will remove the retry mechanism and keep remaining change for Patch v2. Thanks for the review. commit 76098b36b5db1a509e5af94128b08f950692c7f8 Author: Luis R. Rodriguez <mcg...@kernel.org> Date: Thu Jul 20 13:13:39 2017 -0700 firmware: send -EINTR on signal abort on fallback mechanism Right now we send -EAGAIN to a syfs write which got interrupted. Userspace can't tell what happened though, send -EINTR if we were killed due to a signal so userspace can tell things apart. This is only applicable to the fallback mechanism. Regards, Wright
[PATCH] brcmfmac: fix CLM load error for legacy chips when user helper is enabled
For legacy chips w/o CLM blob files, kernel with user helper function enables returns -EAGAIN when we request_firmware() for blob file: "request_firmware() -> _request_firmware() -> fw_load_from_user_helper() -> _request_firmware_load() -> retval=-EAGAIN" We should do one more retry and continue brcmf_c_process_clm_blob if getting -EAGAIN from request_firmware function. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..56e2654 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -45,6 +45,8 @@ #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ +#define CLM_LOAD_RETRIES 1 /* # of retries to load clm_blob file */ + static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0); MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]"); @@ -170,6 +172,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) u16 dl_flag = DL_BEGIN; u32 status; s32 err; + uint retries = 0; brcmf_dbg(TRACE, "Enter\n"); @@ -180,11 +183,18 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) return err; } - err = request_firmware(, clm_name, dev); + do { + err = request_firmware(, clm_name, dev); + } while (err == -EAGAIN && retries++ < CLM_LOAD_RETRIES); if (err) { if (err == -ENOENT) { brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); return 0; + } else if (err == -EAGAIN) { + brcmf_dbg(INFO, "reached maximum retries(%d)\n", + CLM_LOAD_RETRIES); + brcmf_dbg(INFO, "continue with CLM data in firmware\n"); + return 0; } brcmf_err("request CLM blob file failed (%d)\n", err); return err; -- 1.9.1
[PATCH] brcmfmac: enlarge buffer size of caps to 512 bytes
The buffer size of return of cap iovar is greater than 256 bytes in some firmwares. For instance, the return size of cap iovar is 271 bytes in 4373 13.10.246.79 firmare. It makes feature capability parsing failed because caps buffer is default value. So we enlarge caps buffer size to 512 bytes and add the error print for cap iovar error. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 53ae302..47de35a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -130,13 +130,19 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, } } +#define MAX_CAPS_BUFFER_SIZE 512 static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) { - char caps[256]; + char caps[MAX_CAPS_BUFFER_SIZE]; enum brcmf_feat_id id; - int i; + int i, err; + + err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); + if (err) { + brcmf_err("could not get firmware cap (%d)\n", err); + return; + } - brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); brcmf_dbg(INFO, "[ %s]\n", caps); for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) { -- 1.9.1
[PATCH] brcmfmac: Support 43455 save-restore (SR) feature if FW include -sr
From: Double LoThis patch will add 43455 into the save-restore(SR) capable chip list, so the SR engine will be enabled with 43455 FW which built-in the -sr function. Signed-off-by: Double Lo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index c5d1a1c..f7b30ce 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1338,6 +1338,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) switch (pub->chip) { case BRCM_CC_4354_CHIP_ID: case BRCM_CC_4356_CHIP_ID: + case BRCM_CC_4345_CHIP_ID: /* explicitly check SR engine enable bit */ pmu_cc3_mask = BIT(2); /* fall-through */ -- 1.9.1
Re: [PATCH] brcmfmac: transfer firmware error to Linux error code in fwil
Hi Arend, On 2017/11/23 下午 06:41, Arend van Spriel wrote: On 11/22/2017 10:11 AM, Wright Feng wrote: fil_cmd_data_set and fil_cmd_data_get return proprietary error code when getting error from firmware layer. The vendor tools or utilities that uses libnl may stuck in some commands when wl is down. For example, issue "scan" command after issuing "down" command, the "scan" command will be the blocking call and stuck as no response from libnl. It is caused by that firmware returns BCME_NOTUP(-4) when wl is down, but the -4 is -EINTR in Linux kernel, so libnl catches the error and not passes to upper layer. Because of that, the fwil should return Linux error code instead of the proprietary error code, and the tools or utilities should get the real firmware error code by command "bcmerror" or "bcmerrorstr" after receiving the error from libnl. Hi Wright, I recall you had a discussion (on the wireless list?) with Franky about this, but I did not chime in at that time. I am not a proponent for mapping our firmware errors to linux errors. It is tempting to do so because there is clear overlap for some, but still it is quirky and has no value in my opinion. This issue was already addressed in the past although not specifically for fixing the -EINTR case. I did some digging in the git history. Here was my original change: Yes, Franky and I had a discussion in "[PATCH] brcmfmac: return -EPERM when getting error in vendor command handler" on wireless list, that's why I made a new patch for mapping firmware error code to Linux error. Like you said, some of firmware errors do not have good corresponding value in Linux, so returning generic error is good to me. commit 9c6476668025e76a8365be783f2649fe3259b91c Author: Arend van Spriel <ar...@broadcom.com> Date: Tue Oct 28 14:56:09 2014 +0100 brcmfmac: do not use firmware error code in driver Passing the firmware error codes up the driver may be mapped to linux error numbers which may impact proper fault analysis. So better pass up a generic failure code, ie. -EBADE and only show firmware error code in FIL debug message. Reviewed-by: Franky (Zhenhui) Lin <fran...@broadcom.com> Reviewed-by: Hante Meuleman <meule...@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <de...@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <piete...@broadcom.com> Signed-off-by: Arend van Spriel <ar...@broadcom.com> Signed-off-by: John W. Linville <linvi...@tuxdriver.com> The idea here was to have a single error code and have a debug message showing the firmware error string. This single error code could be used by vendor tools (not really an upstream concern) to query the driver for the firmware error code through a vendor specific command. Now what happened is that Hante while inspecting logs with only error messages observed -EBADE and wanted to know firmware error. So he made the following patch a year later: commit 21000b3f3da45a5a33de3815f3c2b3584102960e Author: Hante Meuleman <meule...@broadcom.com> Date: Wed Nov 25 11:32:38 2015 +0100 brcmfmac: Return actual error by fwil. FWIL is always mapping back errors to EBADE. This is not very conventient when trying to understand problems by reading logs. Some callers print the error code, but that is quite useless when the exact error code is not returned. It also makes it impossible to differentiate based on error code. This patch changes the return of EBADE into the actual error code. Reviewed-by: Arend Van Spriel <ar...@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <fran...@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <piete...@broadcom.com> Signed-off-by: Hante Meuleman <meule...@broadcom.com> Signed-off-by: Arend van Spriel <ar...@broadcom.com> Signed-off-by: Kalle Valo <kv...@codeaurora.org> However, the consequence of this was that we ended up returning firmware error codes into the kernel domain and user-space > Below the change I came up with. Let me know what you think. Thanks for the info, now I know the whole history. And I have 2 comments below. Regards, Arend ---8< commit e340892a4bb5a74248b19504bb972497d38a4a03 Author: Arend van Spriel <arend.vanspr...@broadcom.com> Date: Thu Nov 23 11:13:41 2017 +0100 brcmfmac: separate firmware errors from i/o errors When using the firmware api it can fail simply because firmware does not like the request or it fails due to issues in the host interface. Currently, there is only a single error code which is confusing. So adding a parameter to pass the firmware error separately and in case of a firmware error always return -EBADE to user-space. Reviewed-by: Hante Meuleman <ha
[PATCH] brcmfmac: transfer firmware error to Linux error code in fwil
fil_cmd_data_set and fil_cmd_data_get return proprietary error code when getting error from firmware layer. The vendor tools or utilities that uses libnl may stuck in some commands when wl is down. For example, issue "scan" command after issuing "down" command, the "scan" command will be the blocking call and stuck as no response from libnl. It is caused by that firmware returns BCME_NOTUP(-4) when wl is down, but the -4 is -EINTR in Linux kernel, so libnl catches the error and not passes to upper layer. Because of that, the fwil should return Linux error code instead of the proprietary error code, and the tools or utilities should get the real firmware error code by command "bcmerror" or "bcmerrorstr" after receiving the error from libnl. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c| 12 ++-- .../wireless/broadcom/brcm80211/brcmfmac/fwil.c| 80 -- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 13 ++-- .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++-- 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 9f2d0b0..44faae4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) static int brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) + void *buf, uint len, bool *is_fwerr) { struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; struct brcmf_proto_bcdc_dcmd *msg = >msg; @@ -212,8 +212,10 @@ static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) } /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) + if (flags & BCDC_DCMD_ERROR) { + *is_fwerr = true; ret = le32_to_cpu(msg->status); + } done: return ret; @@ -221,7 +223,7 @@ static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) static int brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, - void *buf, uint len) + void *buf, uint len, bool *is_fwerr) { struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; struct brcmf_proto_bcdc_dcmd *msg = >msg; @@ -250,8 +252,10 @@ static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) } /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) + if (flags & BCDC_DCMD_ERROR) { + *is_fwerr = true; ret = le32_to_cpu(msg->status); + } done: return ret; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c index f6a2df9..1a1beaa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c @@ -32,6 +32,70 @@ #define MAX_HEX_DUMP_LEN 64 +static u32 brcmf_fil_errormap[] = { + 0, /* BCME_OK */ + EIO,/* BCME_ERROR */ + EINVAL, /* BCME_BADARG */ + EINVAL, /* BCME_BADOPTION */ + ENETDOWN, /* BCME_NOTUP */ + EIO,/* BCME_NOTDOWN */ + EIO,/* BCME_NOTAP */ + EIO,/* BCME_NOTSTA */ + EINVAL, /* BCME_BADKEYIDX */ + EIO,/* BCME_RADIOOFF */ + EIO,/* BCME_NOTBANDLOCKED */ + EIO,/* BCME_NOCLK */ + EINVAL, /* BCME_BADRATESET */ + EINVAL, /* BCME_BADBAND */ + EINVAL, /* BCME_BUFTOOSHORT */ + EINVAL, /* BCME_BUFTOOLONG */ + EBUSY, /* BCME_BUSY */ + ENOTCONN, /* BCME_NOTASSOCIATED */ + EINVAL, /* BCME_BADSSIDLEN */ + EINVAL, /* BCME_OUTOFRANGECHAN */ + EINVAL, /* BCME_BADCHAN */ + EFAULT, /* BCME_BADADDR */ + ENOMEM, /* BCME_NORESOURCE */ + ENOTSUPP, /* BCME_UNSUPPORTED */ + EINVAL, /* BCME_BADLEN */ + EIO,/* BCME_NOTREADY */ + EPERM, /* BCME_EPERM */ + ENOMEM, /* BCME_NOMEM */ + ENOTCONN, /* BCME_ASSOCIATED */ + EINVAL, /* BCME_RANGE */ + ENXIO, /* BCME_NOTFOUND */ + EIO,/* BCME_WME_NOT_ENABLED */ + ENXIO, /* BCME_TSPEC_NOTFOUND */ + ENOTSUPP, /* BCME_ACM_NOTSUPPORTED */ + ENOTCONN, /* BCME_NOT_WME_ASSOCIATION */ +
[PATCH v7] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Reviewed-by: Arend van Spriel Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail v3: Add error handling in brcmf_c_get_clm_name function v4: Correct the length of dload_buf in brcmf_c_download function v5: Remove unnecessary cast and alignment v6: Add debug log for the case of no CLM file present v7: Rebase and remove unnecessary magic number --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 157 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 258 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 163ddc4..0b76a61 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..6a59d06 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + s32 err; + + flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flag); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = sizeof(*dload_buf) + len - 1; + + err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + if (!ptr) { + err = -ENOENT; +
[PATCH v6] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail v3: Add error handling in brcmf_c_get_clm_name function v4: Correct the length of dload_buf in brcmf_c_download function v5: Remove unnecessary cast and alignment v6: Add debug log for the case of no CLM file present --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 162 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 263 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..5397727 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + s32 err; + + flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flag); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = sizeof(*dload_buf) + len - 1; + + err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + if (!ptr) { + err = -ENOENT; + goto done; + } + + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") >
Re: [PATCH] brcmfmac: return -EPERM when getting error in vendor command handler
Hi Franky, On 2017/9/6 上午 04:02, Franky Lin wrote: On Mon, Sep 4, 2017 at 12:34 AM, Wright Feng <wright.f...@cypress.com> wrote: Firmware returns proprietary error code when getting error in fil_cmd_data_set or fil_cmd_data_get. The vendor tools or utilities which uses libnl may stuck in some commands when wl is down. For example, issue "scan" command after issuing "down" command, the "scan" command will be the blocking call and stuck as no response from libnl. It is caused by that firmware returns BCME_NOTUP(-4) when wl is down, but the -4 is -EINTR in Linux kernel, so libnl catches the error and not passes to upper layer. Because of that, the driver should return Linux error code instead of the proprietary error code, and the tools or utilities need to get the real firmware error code by command "bcmerror" or "bcmerrorstr" after receiving the error. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 8eff275..2b88ba1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -80,8 +80,12 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, else ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf, ret_len); - if (ret != 0) + + if (ret != 0) { + brcmf_dbg(INFO, "error(%d), return -EPERM\n", ret); + ret = -EPERM; goto exit; + } It would be better to handle the conversion in brcmf_fil_cmd_data so everyone can benefit. Also please try to assign an appropriate error Thanks for the suggestion and sorry for replying the mail lately.(We got some mail server issue a couple days ago.) I will move the conversion to brcmf_proto_bcdc_query_dcmd/brcmf_proto_bcdc_set_dcmd for bcdc and brcmf_msgbuf_query_dcmd for msgbuf. code when possible to provide more information to the upper layer. For this case "ENETDOWN" seems to be a better fit for BCME_NOTUP. One more thing I need your suggestion. Some of firmware error codes do not have proper error code mapping to Linux, like "BCME_NOTUP", "BCME_ERROR", "BCME_NOTAP", "BCME_NOTSTA", "BCME_ASSOCIATED"... Is that okay using -EIO for those errors which do have proper mapping error code? Or do you know the error code for the generic error? Regards, Wright Thanks, Franky wr_pointer = dcmd_buf; while (ret_len > 0) { -- 1.9.1
[PATCH] brcmfmac: return -EPERM when getting error in vendor command handler
Firmware returns proprietary error code when getting error in fil_cmd_data_set or fil_cmd_data_get. The vendor tools or utilities which uses libnl may stuck in some commands when wl is down. For example, issue "scan" command after issuing "down" command, the "scan" command will be the blocking call and stuck as no response from libnl. It is caused by that firmware returns BCME_NOTUP(-4) when wl is down, but the -4 is -EINTR in Linux kernel, so libnl catches the error and not passes to upper layer. Because of that, the driver should return Linux error code instead of the proprietary error code, and the tools or utilities need to get the real firmware error code by command "bcmerror" or "bcmerrorstr" after receiving the error. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 8eff275..2b88ba1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -80,8 +80,12 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, else ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf, ret_len); - if (ret != 0) + + if (ret != 0) { + brcmf_dbg(INFO, "error(%d), return -EPERM\n", ret); + ret = -EPERM; goto exit; + } wr_pointer = dcmd_buf; while (ret_len > 0) { -- 1.9.1
[PATCH v5] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail v3: Add error handling in brcmf_c_get_clm_name function v4: Correct the length of dload_buf in brcmf_c_download function v5: Remove unnecessary cast and alignment --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 160 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 261 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..f6268e0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,138 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + s32 err; + + flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flag); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = sizeof(*dload_buf) + len - 1; + + err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + if (!ptr) { + err = -ENOENT; + goto done; + } + + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { + err = -E2BIG; + }
[PATCH v4] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail v3: Add error handling in brcmf_c_get_clm_name function v4: Correct the length of dload_buf in brcmf_c_download function --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 161 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 262 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..d09922b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,139 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + s32 err; + + flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flag); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = sizeof(*dload_buf) + len - 1; + len = len + 8 - (len % 8); + + err = brcmf_fil_iovar_data_set(ifp, "clmload", (void *)dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + if (!ptr) { + err = -ENOENT; + goto done; + } + + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { + err = -E2BIG; + }
[PATCH v3] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail v3: Add error handling in brcmf_c_get_clm_name function --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 161 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 262 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..f5f00fa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,139 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + u16 flags; + s32 err; + + flags = flag | (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flags); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = len + 8 - (len % 8); + + err = brcmf_fil_iovar_data_set(ifp, "clmload", (void *)dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + if (!ptr) { + err = -ENOENT; + goto done; + } + + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { + err = -E2BIG; + } else { + strlcpy(clm_name, fw_name, len); +
[PATCH v2] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. The CLM blob file is optional. If the file does not exist, the download process will be bypassed. It will not affect the driver loading. Signed-off-by: Chung-Hsien Hsu --- v2: Revise commit message to describe in more detail --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 156 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 257 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..6d30421 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,134 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + u16 flags; + s32 err; + + flags = flag | (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flags); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = len + 8 - (len % 8); + + err = brcmf_fil_iovar_data_set(ifp, "clmload", (void *)dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { + err = -E2BIG; + } else { + strlcpy(clm_name, fw_name, len); + strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); + } +done: + return err; +} + +static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) +{ +
[PATCH] brcmfmac: add CLM download support
From: Chung-Hsien HsuThe firmware for brcmfmac devices includes information regarding regulatory constraints. For certain devices this information is kept separately in a binary form that needs to be downloaded to the device. This patch adds support to download this so-called CLM blob file. It uses the same naming scheme as the other firmware files with extension of .clm_blob. Signed-off-by: Chung-Hsien Hsu --- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 156 + .../wireless/broadcom/brcm80211/brcmfmac/core.c| 2 + .../wireless/broadcom/brcm80211/brcmfmac/core.h| 2 + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 .../wireless/broadcom/brcm80211/brcmfmac/pcie.c| 19 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.c| 19 +++ .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ 8 files changed, 257 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index b55c329..df42e09 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { * @wowl_config: specify if dongle is configured for wowl when going to suspend * @get_ramsize: obtain size of device memory. * @get_memdump: obtain device memory dump in provided buffer. + * @get_fwname: obtain firmware name. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -87,6 +88,8 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); + int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + unsigned char *fw_name); }; @@ -214,6 +217,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) return bus->ops->get_memdump(bus->dev, data, len); } +static inline +int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +unsigned char *fw_name) +{ + return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 7a2b495..6d30421 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "core.h" @@ -28,6 +29,7 @@ #include "tracepoint.h" #include "common.h" #include "of.h" +#include "firmware.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -104,12 +106,134 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) brcmf_err("Set join_pref error (%d)\n", err); } +static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, + struct brcmf_dload_data_le *dload_buf, + u32 len) +{ + u16 flags; + s32 err; + + flags = flag | (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); + dload_buf->flag = cpu_to_le16(flags); + dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); + dload_buf->len = cpu_to_le32(len); + dload_buf->crc = cpu_to_le32(0); + len = len + 8 - (len % 8); + + err = brcmf_fil_iovar_data_set(ifp, "clmload", (void *)dload_buf, len); + + return err; +} + +static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) +{ + struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_rev_info *ri = >drvr->revinfo; + u8 fw_name[BRCMF_FW_NAME_LEN]; + u8 *ptr; + size_t len; + s32 err; + + memset(fw_name, 0, BRCMF_FW_NAME_LEN); + err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); + if (err) { + brcmf_err("get firmware name failed (%d)\n", err); + goto done; + } + + /* generate CLM blob file name */ + ptr = strrchr(fw_name, '.'); + len = ptr - fw_name + 1; + if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { + err = -E2BIG; + } else { + strlcpy(clm_name, fw_name, len); + strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); + } +done: + return err; +} + +static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) +{ + struct device *dev = ifp->drvr->bus_if->dev; + struct brcmf_dload_data_le *chunk_buf; + const struct firmware *clm = NULL; + u8 clm_name[BRCMF_FW_NAME_LEN]; + u32
[PATCH] brcmfmac: add setting carrier state ON for successful roaming
From: Chung-Hsien HsuAfter association, ping is not working when sweeping the channel at the AP side. It is caused by having incorrect carrier state (OFF) for the STA in successful roaming. This patch sets the carrier state ON for the case. Signed-off-by: Chung-Hsien Hsu --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 617199c..71f18b9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5552,10 +5552,13 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, u32 status = e->status; if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { - if (test_bit(BRCMF_VIF_STATUS_CONNECTED, >vif->sme_state)) + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, +>vif->sme_state)) { brcmf_bss_roaming_done(cfg, ifp->ndev, e); - else + } else { brcmf_bss_connect_done(cfg, ifp->ndev, e, true); + brcmf_net_setcarrier(ifp, true); + } } return 0; -- 1.9.1
[PATCH v2 2/3] brcmfmac: Add support for CYW4373 SDIO/USB chipset
From: Chi-Hsien LinAdd support for CYW4373 SDIO/USB chipset. CYW4373 is a 1x1 dual-band 11ac chipset with 20/40/80Mhz channel support. It's a WiFi/BT combo device. Signed-off-by: Chi-Hsien Lin --- v2: add new chip(4737) info in commit message --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 +++- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c| 9 - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 3 +++ include/linux/mmc/sdio_ids.h | 1 + 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 9b970dc..ea47f75 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -1108,6 +1108,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373), { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 05f22ff..c5d1a1c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -690,6 +690,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_4365_CHIP_ID: case BRCM_CC_4366_CHIP_ID: return 0x20; + case CY_CC_4373_CHIP_ID: + return 0x16; default: brcmf_err("unknown chip: %s\n", ci->pub.name); break; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 5653d6d..b1789b1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -616,6 +616,7 @@ struct sdiod_drive_str { BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt"); BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt"); BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt"); +BRCMF_FW_NVRAM_DEF(4373, "brcmfmac4373-sdio.bin", "brcmfmac4373-sdio.txt"); static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0x, 43143), @@ -633,7 +634,8 @@ struct sdiod_drive_str { BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x, 43430), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFC0, 43455), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0x, 4354), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0x, 4356) + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0x, 4356), + BRCMF_FW_NVRAM_ENTRY(CY_CC_4373_CHIP_ID, 0x, 4373) }; static void pkt_align(struct sk_buff *p, int len, int align) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 0eea48e..8f20a4b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -50,6 +50,7 @@ BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin"); BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin"); BRCMF_FW_DEF(43569, "brcmfmac43569.bin"); +BRCMF_FW_DEF(4373, "brcmfmac4373.bin"); static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0x, 43143), @@ -58,7 +59,8 @@ BRCMF_FW_ENTRY(BRCM_CC_43238_CHIP_ID, 0x0008, 43236B), BRCMF_FW_ENTRY(BRCM_CC_43242_CHIP_ID, 0x, 43242A), BRCMF_FW_ENTRY(BRCM_CC_43566_CHIP_ID, 0x, 43569), - BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0x, 43569) + BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0x, 43569), + BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0x, 4373) }; #define TRX_MAGIC 0x30524448 /* "HDR0" */ @@ -1463,15 +1465,20 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) #define LINKSYS_USB_DEVICE(dev_id) \ { USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id) } +#define CYPRESS_USB_DEVICE(dev_id) \ + { USB_DEVICE(CY_USB_VENDOR_ID_CYPRESS, dev_id) } + static struct usb_device_id brcmf_usb_devid_table[] = { BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID), BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID), BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
[PATCH v2 3/3] brcmfmac: fix wrong num_different_channels when mchan feature enabled
brcmfmac: fix wrong num_different_channels when mchan feature enabled When the device/firmware supports multi-channel, it can have P2P connection and regular connection with AP simultaneous. In this case, the num_different_channels in wiphy info was not correct when firmware supports multi-channel (The iw wiphy# info showed "#channels <= 1" in interface combinations). It caused association failed and error message "CTRL-EVENT-FREQ-CONFLICT error" in wpa_supplicant when P2P GO interface was running at the same time. The root cause is that the num_different_channels was always overridden to 1 in brcmf_setup_ifmodes even multi-channel was enabled. We correct the logic by moving num_different_channels setting forward. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- v2: Describe the motivation and reason for this patch in commit message --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 0281a22..0bb3b0b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6315,6 +6315,8 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) if (p2p) { if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) combo[c].num_different_channels = 2; + else + combo[c].num_different_channels = 1; wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE); @@ -6324,10 +6326,10 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); } else { + combo[c].num_different_channels = 1; c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); } - combo[c].num_different_channels = 1; combo[c].max_interfaces = i; combo[c].n_limits = i; combo[c].limits = c0_limits; -- 1.9.1
Re: [PATCH 3/3] brcmfmac: fix wrong num_different_channels when mchan feature enabled
On 2017/8/2 下午 09:40, Kalle Valo wrote: Arend van Spriel <arend.vanspr...@broadcom.com> writes: On 8/2/2017 11:32 AM, Kalle Valo wrote: Wright Feng <wright.f...@cypress.com> writes: The num_different_channels in wiphy info is not correct when firmware supports mchan. When mchan is on, num_different_channels is always overridden to 1 in brcmf_setup_ifmodes. Correct the logic by moving num_different_channels setting forward. Signed-off-by: Wright Feng <wright.f...@cypress.com> Does this fix a user visible bug? If yes, it would be nice to document that. Hi Kalle, Depends on the users expectation ;-) When the device/firmware supports multi-channel (better not use mchan abbreviation) it can have P2P connection and regular connection with AP simultaneous. So the current state is that this is not possible regardless whether mchan is supported. So the device is not used to fullest extent. Thanks, I understand now and I think your description should be also in the commit log so that others will also :) My usual mantra: the commit log should ALWAYS answer the question "_why_ the change is made?" and describe the reason what motivated to implement the patch. This is the most important part. It helps maintainers, backports, distros etc to make decisions if the patch is important for them or not. Hi Kalle and Arend, Thanks for your comment and suggestion, I will put them into commit message and resend v2 later.
Re: [PATCH 1/3] brcmfmac: set wpa_auth to WPA_AUTH_DISABLED in AP/opensecurity mode
On 2017/8/1 下午 08:41, Arend van Spriel wrote: On 01-08-17 10:48, Wright Feng wrote: When setting wpa_auth to WPA_AUTH_NONE(1) in AP mode with WEP secuirty, firmware will set privacy bit and add WPA OUI in VENDOR IE in beacon and probe response. It confuses the supplicant in sation client by the security type from softAP beacon and we will see [WPA-?] in scan result. So we set WPA_AUTH_DISABLED in softAP mode with opensecurity. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index a31ea10..54588d2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3854,6 +3854,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) { s32 err; + s32 wpa_val; /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); @@ -3868,7 +3869,11 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) return err; } /* set upper-layer auth */ - err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE); + if (brcmf_is_ibssmode(ifp->vif)) + wpa_val = WPA_AUTH_NONE; + else + wpa_val = WPA_AUTH_DISABLED; + err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val); Is WPA_AUTH_NONE ok for IBSS mode? Not sure why it is handled differently. Is it because you do not want to change things for IBSS mode as you did not try that? I would like to keep WPA_AUTH_NODE for IBSS mode because the comment of WPA_AUTH_NONE definition in brcmu_wifi.h is "none (IBSS)". It seems that WPA_AUTH_NONE is for IBSS mode. Regards, Arend
[PATCH 1/3] brcmfmac: set wpa_auth to WPA_AUTH_DISABLED in AP/opensecurity mode
When setting wpa_auth to WPA_AUTH_NONE(1) in AP mode with WEP secuirty, firmware will set privacy bit and add WPA OUI in VENDOR IE in beacon and probe response. It confuses the supplicant in sation client by the security type from softAP beacon and we will see [WPA-?] in scan result. So we set WPA_AUTH_DISABLED in softAP mode with opensecurity. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index a31ea10..54588d2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3854,6 +3854,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) { s32 err; + s32 wpa_val; /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); @@ -3868,7 +3869,11 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) return err; } /* set upper-layer auth */ - err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE); + if (brcmf_is_ibssmode(ifp->vif)) + wpa_val = WPA_AUTH_NONE; + else + wpa_val = WPA_AUTH_DISABLED; + err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val); if (err < 0) { brcmf_err("wpa_auth error %d\n", err); return err; -- 1.9.1
[PATCH 3/3] brcmfmac: fix wrong num_different_channels when mchan feature enabled
The num_different_channels in wiphy info is not correct when firmware supports mchan. When mchan is on, num_different_channels is always overridden to 1 in brcmf_setup_ifmodes. Correct the logic by moving num_different_channels setting forward. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 54588d2..3dcb139 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6318,6 +6318,8 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) if (p2p) { if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) combo[c].num_different_channels = 2; + else + combo[c].num_different_channels = 1; wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE); @@ -6327,10 +6329,10 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); } else { + combo[c].num_different_channels = 1; c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); } - combo[c].num_different_channels = 1; combo[c].max_interfaces = i; combo[c].n_limits = i; combo[c].limits = c0_limits; -- 1.9.1
[PATCH 2/3] brcmfmac: Add support for CYW4373 SDIO/USB chipset
From: Chi-Hsien LinThese changes add support for CYW4373 SDIO/USB chipset. Signed-off-by: Chi-Hsien Lin --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 ++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 +++- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c| 9 - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 3 +++ include/linux/mmc/sdio_ids.h | 1 + 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 9b970dc..ea47f75 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -1108,6 +1108,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373), { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 05f22ff..c5d1a1c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -690,6 +690,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_4365_CHIP_ID: case BRCM_CC_4366_CHIP_ID: return 0x20; + case CY_CC_4373_CHIP_ID: + return 0x16; default: brcmf_err("unknown chip: %s\n", ci->pub.name); break; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 5653d6d..b1789b1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -616,6 +616,7 @@ struct sdiod_drive_str { BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt"); BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt"); BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt"); +BRCMF_FW_NVRAM_DEF(4373, "brcmfmac4373-sdio.bin", "brcmfmac4373-sdio.txt"); static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0x, 43143), @@ -633,7 +634,8 @@ struct sdiod_drive_str { BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x, 43430), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFC0, 43455), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0x, 4354), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0x, 4356) + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0x, 4356), + BRCMF_FW_NVRAM_ENTRY(CY_CC_4373_CHIP_ID, 0x, 4373) }; static void pkt_align(struct sk_buff *p, int len, int align) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 0eea48e..8f20a4b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -50,6 +50,7 @@ BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin"); BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin"); BRCMF_FW_DEF(43569, "brcmfmac43569.bin"); +BRCMF_FW_DEF(4373, "brcmfmac4373.bin"); static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0x, 43143), @@ -58,7 +59,8 @@ BRCMF_FW_ENTRY(BRCM_CC_43238_CHIP_ID, 0x0008, 43236B), BRCMF_FW_ENTRY(BRCM_CC_43242_CHIP_ID, 0x, 43242A), BRCMF_FW_ENTRY(BRCM_CC_43566_CHIP_ID, 0x, 43569), - BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0x, 43569) + BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0x, 43569), + BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0x, 4373) }; #define TRX_MAGIC 0x30524448 /* "HDR0" */ @@ -1463,15 +1465,20 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) #define LINKSYS_USB_DEVICE(dev_id) \ { USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id) } +#define CYPRESS_USB_DEVICE(dev_id) \ + { USB_DEVICE(CY_USB_VENDOR_ID_CYPRESS, dev_id) } + static struct usb_device_id brcmf_usb_devid_table[] = { BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID), BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID), BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID), BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID), LINKSYS_USB_DEVICE(BRCM_USB_43235_LINKSYS_DEVICE_ID), +
[PATCH] brcmfmac: remove setting IBSS mode when stopping AP
From: Chi-hsien Lin <chi-hsien@cypress.com> Setting IBSS mode when stopping AP may affect functionality of INFRA mode on another interface. For instance, if user creates and stops hostap daemon on virtual interface, then association cannot work on primary interface because default BSS has been set to IBSS mode in firmware side. The IBSS mode should be set when cfg80211 changes the interface. Reviewed-by: Wright Feng <wright.f...@cypress.com> Signed-off-by: Chi-hsien Lin <chi-hsien@cypress.com> Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 944b83c..ce2a5b6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4658,9 +4658,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); if (err < 0) brcmf_err("setting AP mode failed %d\n", err); - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); - if (err < 0) - brcmf_err("setting INFRA mode failed %d\n", err); if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) brcmf_fil_iovar_int_set(ifp, "mbss", 0); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, -- 2.1.0
[PATCH V2] brcmfmac: update beacon IE after bss up and clear when AP stopped
Firmware doesn't update beacon/Probe Response vendor IEs correctly when bss is down, so we move brcmf_config_ap_mgmt_ie after BSS up. And host driver should clear IEs when AP stopped so that the IEs in host side will be synced with in firmware side. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- V2: word wrap the commit log --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b777e1b..d022605 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4578,8 +4578,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, brcmf_configure_opensecurity(ifp); } - brcmf_config_ap_mgmt_ie(ifp->vif, >beacon); - /* Parameters shared by all radio interfaces */ if (!mbss) { if ((supports_11d) && (is_11d != ifp->vif->is_11d)) { @@ -4708,6 +4706,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, WARN_ON(1); } + brcmf_config_ap_mgmt_ie(ifp->vif, >beacon); set_bit(BRCMF_VIF_STATUS_AP_CREATED, >vif->sme_state); brcmf_net_setcarrier(ifp, true); @@ -4764,6 +4763,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) brcmf_err("BRCMF_C_UP error %d\n", err); + + brcmf_vif_clear_mgmt_ies(ifp->vif); } else { bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx); bss_enable.enable = cpu_to_le32(0); -- 2.1.0
[PATCH] brcmfmac: update beacon IE when bss up and clear when stopped
Firmware doesn't update beacon vendor IEs when bss is down, so move brcmf_config_ap_mgmt_ie after BSS up. And host driver should clear IEs when AP stopped so that the IEs in host side will be synced with in firmware side. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b777e1b..d022605 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4578,8 +4578,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, brcmf_configure_opensecurity(ifp); } - brcmf_config_ap_mgmt_ie(ifp->vif, >beacon); - /* Parameters shared by all radio interfaces */ if (!mbss) { if ((supports_11d) && (is_11d != ifp->vif->is_11d)) { @@ -4708,6 +4706,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, WARN_ON(1); } + brcmf_config_ap_mgmt_ie(ifp->vif, >beacon); set_bit(BRCMF_VIF_STATUS_AP_CREATED, >vif->sme_state); brcmf_net_setcarrier(ifp, true); @@ -4764,6 +4763,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) brcmf_err("BRCMF_C_UP error %d\n", err); + + brcmf_vif_clear_mgmt_ies(ifp->vif); } else { bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx); bss_enable.enable = cpu_to_le32(0); -- 2.1.0
RE: [PATCH v2] brcmfmac: shut down AP and set IBSS mode only on primary interface
From: Rafał Miłecki [mailto:zaj...@gmail.com] > On 11 August 2016 at 07:44, Wright Feng <wright.f...@cypress.com> wrote: > > When stopping hostap on virtual interface, driver will set INFRA and > > AP mode that may affect the functionality on primary interface. For > > example, if we create and stop hostapd on virtual interface then > > association cannot work on primary interface because INFRA mode has > been set to IBSS. > > Hence we shut down AP and set IBSS mode only on primary interface. > > You also excluded from execution code setting BRCMF_C_SET_AP to 0. > Does it get a reset at some point? Maybe with a "bss" call? I'm wondering if > it's possible to use interface in managed mode if it was used as AP once. In this case, the virtual interface cannot be managed mode unless re-creating the interface. Driver should just exclude from setting INFRA mode when stopping AP with virtual interface, and I'll update this change in PATCH v3. Thanks for your review. > > -- > Rafał Regards, Wright This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
RE: [PATCH] brcmfmac: shut down AP and set IBSS mode only on primary interface
Hi Kalle and Arend, > -Original Message- > From: Kalle Valo [mailto:kv...@codeaurora.org] > Sent: Monday, August 15, 2016 4:05 PM > To: Arend Van Spriel <arend.vanspr...@broadcom.com> > Cc: Wright Feng <w...@cypress.com>; brcm80211-dev- > list@broadcom.com; franky@broadcom.com; > hante.meule...@broadcom.com; piete...@broadcom.com; Chi-Hsien Lin > <c...@cypress.com>; linux-wireless@vger.kernel.org > Subject: Re: [PATCH] brcmfmac: shut down AP and set IBSS mode only on > primary interface > > Arend Van Spriel <arend.vanspr...@broadcom.com> writes: > > >> This message and any attachments may contain Cypress (or its > >> subsidiaries) confidential information. If it has been received in > >> error, please advise the sender and immediately delete this message. > > > > Is there any way for you to get rid of this foot note. It may keep > > Kalle from taking this patch. > > Correct. I'll automatically drop patches with these kind of notices. I've removed the foot note and sent the [PATCH v2] to you on 8/11. Is that okay to you? > > -- > Kalle Valo This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] brcmfmac: shut down AP and set IBSS mode only on primary interface
When stopping hostap on virtual interface, driver will set INFRA and AP mode that may affect the functionality on primary interface. For example, if we create and stop hostapd on virtual interface then association cannot work on primary interface because INFRA mode has been set to IBSS. Hence we shut down AP and set IBSS mode only on primary interface. Signed-off-by: Wright Feng <wright.f...@cypress.com> --- V2:Remove the footnote from the mail. --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 2628d5e..0687ab9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4716,6 +4716,8 @@ exit: static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *primary_ndev = cfg_to_ndev(cfg); struct brcmf_if *ifp = netdev_priv(ndev); s32 err; struct brcmf_fil_bss_enable_le bss_enable; @@ -4723,7 +4725,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) brcmf_dbg(TRACE, "Enter\n"); - if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) { + if ((ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) && + (ndev == primary_ndev)) { /* Due to most likely deauths outstanding we sleep */ /* first to make sure they get processed by fw. */ msleep(400); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] brcmfmac: shut down AP and set IBSS mode only on primary interface
On 10-8-2016 12:15, Arend Van Spriel wrote: > On 10-8-2016 11:44, Wright Feng wrote: > > Hi Arend, > > > > Thanks for the reply. > > > > On 10-8-2016 10:26, Arend Van Spriel wrote: > >> On 10-8-2016 10:01, Wright Feng wrote: > >>> When stopping hostap on virtual interface, driver will set INFRA and > >>> AP mode that may affect the functionality on primary interface. For > >>> example, if we create and stop hostapd on virtual interface then > >>> association cannot work on primary interface because INFRA mode has > >> been set to IBSS. > >>> Hence we shut down AP and set IBSS mode only on primary interface. > >> > >> What is actually the use-case here. Can you elaborate? BRCMF_C_DOWN > >> command turns out to be effectively bring the whole stack down and > >> not just the supplied interface. I suppose you are hitting that issue here > >> as > well, right? > > We want to use AP mode to let client connecting in AP+STA mode with > 43438 wi-fi chip. > > After that, the AP mode will be stopped, and wpa_supplicant cannot > associate to the access point. > > I describe the steps in detail as below. > > 1. Create virtual interface and set mode to __ap 2. start > > wpa_supplicant on primary interface and connect to wireless router. > > 3. start hostap daemon on virtual interface and let client connecting. > > 4. stop hostap daemon > > 5. wpa_supplicant cannot associate to access point normally. > > > > Like you said, the issue may be hit by BRCMF_C_DOWN and same as > > BRCMF_C_SET_INFRA BRCMF_C_SET_INFRA is not just for the supplied > interface either. The default bss will be changed in firmware and let firmware > uses IBSS mode to join. > > About BRCMF_C_DOWN, driver will set BRCMF_C_UP command to bring > device back up so it can be used again. > > However, there is no way to set INFRA mode back except starting AP mode > again. > > Ok. > > >> > >> Regards, > >> Arend > >> > >>> Signed-off-by: Wright Feng <wright.f...@cypress.com> > >>> --- > >>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 > >> - > >>> 1 file changed, 4 insertions(+), 1 deletion(-) > >>> > >>> diff --git > >>> a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > >>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > >>> index 2628d5e..0687ab9 100644 > >>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > >>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > >>> @@ -4716,6 +4716,8 @@ exit: > >>> > >>> static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct > >>> net_device *ndev) { > >>> + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); > >>> + struct net_device *primary_ndev = cfg_to_ndev(cfg); > >>> struct brcmf_if *ifp = netdev_priv(ndev); > >>> s32 err; > >>> struct brcmf_fil_bss_enable_le bss_enable; @@ -4723,7 > >>> +4725,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, > >>> struct net_device *ndev) > >>> > >>> brcmf_dbg(TRACE, "Enter\n"); > >>> > >>> - if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) { > >>> + if ((ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) && > >>> + (ndev == primary_ndev)) { > >>> /* Due to most likely deauths outstanding we sleep */ > >>> /* first to make sure they get processed by fw. */ > >>> msleep(400); > >>> -- > >>> 1.9.1 > >>> > >>> > >>> This message and any attachments may contain Cypress (or its > >>> subsidiaries) > >> confidential information. If it has been received in error, please > >> advise the sender and immediately delete this message. > >>> > > > > This message and any attachments may contain Cypress (or its subsidiaries) > confidential information. If it has been received in error, please advise the > sender and immediately delete this message. > > Is there any way for you to get rid of this foot note. It may keep Kalle from > taking this patch. Other option is to take this patch through our internal > tree. No problem. I will remove the footnote from the PATCH v2. > > Regards, > Arend This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] brcmfmac: shut down AP and set IBSS mode only on primary interface
Hi Arend, Thanks for the reply. On 10-8-2016 10:26, Arend Van Spriel wrote: > On 10-8-2016 10:01, Wright Feng wrote: > > When stopping hostap on virtual interface, driver will set INFRA and > > AP mode that may affect the functionality on primary interface. For > > example, if we create and stop hostapd on virtual interface then > > association cannot work on primary interface because INFRA mode has > been set to IBSS. > > Hence we shut down AP and set IBSS mode only on primary interface. > > What is actually the use-case here. Can you elaborate? BRCMF_C_DOWN > command turns out to be effectively bring the whole stack down and not just > the supplied interface. I suppose you are hitting that issue here as well, > right? We want to use AP mode to let client connecting in AP+STA mode with 43438 wi-fi chip. After that, the AP mode will be stopped, and wpa_supplicant cannot associate to the access point. I describe the steps in detail as below. 1. Create virtual interface and set mode to __ap 2. start wpa_supplicant on primary interface and connect to wireless router. 3. start hostap daemon on virtual interface and let client connecting. 4. stop hostap daemon 5. wpa_supplicant cannot associate to access point normally. Like you said, the issue may be hit by BRCMF_C_DOWN and same as BRCMF_C_SET_INFRA BRCMF_C_SET_INFRA is not just for the supplied interface either. The default bss will be changed in firmware and let firmware uses IBSS mode to join. About BRCMF_C_DOWN, driver will set BRCMF_C_UP command to bring device back up so it can be used again. However, there is no way to set INFRA mode back except starting AP mode again. > > Regards, > Arend > > > Signed-off-by: Wright Feng <wright.f...@cypress.com> > > --- > > drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 > - > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > diff --git > > a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > > b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > > index 2628d5e..0687ab9 100644 > > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c > > @@ -4716,6 +4716,8 @@ exit: > > > > static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct > > net_device *ndev) { > > + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); > > + struct net_device *primary_ndev = cfg_to_ndev(cfg); > > struct brcmf_if *ifp = netdev_priv(ndev); > > s32 err; > > struct brcmf_fil_bss_enable_le bss_enable; @@ -4723,7 +4725,8 > > @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct > > net_device *ndev) > > > > brcmf_dbg(TRACE, "Enter\n"); > > > > - if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) { > > + if ((ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) && > > + (ndev == primary_ndev)) { > > /* Due to most likely deauths outstanding we sleep */ > > /* first to make sure they get processed by fw. */ > > msleep(400); > > -- > > 1.9.1 > > > > > > This message and any attachments may contain Cypress (or its subsidiaries) > confidential information. If it has been received in error, please advise the > sender and immediately delete this message. > > This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html