Commit 61730d4d authored by Piotr Haber's avatar Piotr Haber Committed by John W. Linville

brcmfmac: support critical protocol API for DHCP

Adds support for the critical protocol API provided by nl80211
which gives Wifi traffic priority over a Bluetooth (e)SCO connection
and disables scanning during DCHP negotiation.
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarPiotr Haber <phaber@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1687eee2
...@@ -30,7 +30,8 @@ brcmfmac-objs += \ ...@@ -30,7 +30,8 @@ brcmfmac-objs += \
p2p.o \ p2p.o \
dhd_cdc.o \ dhd_cdc.o \
dhd_common.o \ dhd_common.o \
dhd_linux.o dhd_linux.o \
btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \ dhd_sdio.o \
bcmsdh.o \ bcmsdh.o \
......
This diff is collapsed.
/*
* Copyright (c) 2013 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WL_BTCOEX_H_
#define WL_BTCOEX_H_
enum brcmf_btcoex_mode {
BRCMF_BTCOEX_DISABLED,
BRCMF_BTCOEX_ENABLED
};
int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
enum brcmf_btcoex_mode mode, u16 duration);
#endif /* WL_BTCOEX_H_ */
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "tracepoint.h" #include "tracepoint.h"
#include "fwil_types.h" #include "fwil_types.h"
#include "p2p.h" #include "p2p.h"
#include "btcoex.h"
#include "wl_cfg80211.h" #include "wl_cfg80211.h"
#include "fwil.h" #include "fwil.h"
...@@ -1051,6 +1052,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) ...@@ -1051,6 +1052,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
{ {
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
s32 err = 0; s32 err = 0;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
...@@ -1064,6 +1066,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) ...@@ -1064,6 +1066,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
} }
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
brcmf_dbg(TRACE, "Exit\n"); brcmf_dbg(TRACE, "Exit\n");
} }
...@@ -4013,6 +4017,39 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ...@@ -4013,6 +4017,39 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
return err; return err;
} }
static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
struct wireless_dev *wdev,
enum nl80211_crit_proto_id proto,
u16 duration)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
/* only DHCP support for now */
if (proto != NL80211_CRIT_PROTO_DHCP)
return -EINVAL;
/* suppress and abort scanning */
set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
brcmf_abort_scanning(cfg);
return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
}
static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
}
static struct cfg80211_ops wl_cfg80211_ops = { static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface, .add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface, .del_virtual_intf = brcmf_cfg80211_del_iface,
...@@ -4049,6 +4086,8 @@ static struct cfg80211_ops wl_cfg80211_ops = { ...@@ -4049,6 +4086,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
.start_p2p_device = brcmf_p2p_start_device, .start_p2p_device = brcmf_p2p_start_device,
.stop_p2p_device = brcmf_p2p_stop_device, .stop_p2p_device = brcmf_p2p_stop_device,
.crit_proto_start = brcmf_cfg80211_crit_proto_start,
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
#ifdef CONFIG_NL80211_TESTMODE #ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode .testmode_cmd = brcmf_cfg80211_testmode
#endif #endif
...@@ -4786,6 +4825,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, ...@@ -4786,6 +4825,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_err("P2P initilisation failed (%d)\n", err); brcmf_err("P2P initilisation failed (%d)\n", err);
goto cfg80211_p2p_attach_out; goto cfg80211_p2p_attach_out;
} }
err = brcmf_btcoex_attach(cfg);
if (err) {
brcmf_err("BT-coex initialisation failed (%d)\n", err);
brcmf_p2p_detach(&cfg->p2p);
goto cfg80211_p2p_attach_out;
}
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
&io_type); &io_type);
...@@ -4813,6 +4858,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) ...@@ -4813,6 +4858,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
struct brcmf_cfg80211_vif *tmp; struct brcmf_cfg80211_vif *tmp;
wl_deinit_priv(cfg); wl_deinit_priv(cfg);
brcmf_btcoex_detach(cfg);
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) { list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
brcmf_free_vif(vif); brcmf_free_vif(vif);
} }
......
...@@ -351,6 +351,7 @@ struct brcmf_cfg80211_vif_event { ...@@ -351,6 +351,7 @@ struct brcmf_cfg80211_vif_event {
* @wiphy: wiphy object for cfg80211 interface. * @wiphy: wiphy object for cfg80211 interface.
* @conf: dongle configuration. * @conf: dongle configuration.
* @p2p: peer-to-peer specific information. * @p2p: peer-to-peer specific information.
* @btcoex: Bluetooth coexistence information.
* @scan_request: cfg80211 scan request object. * @scan_request: cfg80211 scan request object.
* @usr_sync: mainly for dongle up/down synchronization. * @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information. * @bss_list: bss_list holding scanned ap information.
...@@ -384,6 +385,7 @@ struct brcmf_cfg80211_info { ...@@ -384,6 +385,7 @@ struct brcmf_cfg80211_info {
struct wiphy *wiphy; struct wiphy *wiphy;
struct brcmf_cfg80211_conf *conf; struct brcmf_cfg80211_conf *conf;
struct brcmf_p2p_info p2p; struct brcmf_p2p_info p2p;
struct brcmf_btcoex_info *btcoex;
struct cfg80211_scan_request *scan_request; struct cfg80211_scan_request *scan_request;
struct mutex usr_sync; struct mutex usr_sync;
struct brcmf_scan_results *bss_list; struct brcmf_scan_results *bss_list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment