Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352607
b: refs/heads/master
c: 5f4f9f1
h: refs/heads/master
i:
  352605: ddfab1d
  352603: 6c4d83f
  352599: 91fa2b3
  352591: eb2a27d
  352575: 49ad5f5
v: v3
  • Loading branch information
Arend van Spriel authored and John W. Linville committed Feb 8, 2013
1 parent 260a335 commit 9b80e87
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 93 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: de66efcadbb51935c8c668a38f2f1c187f349af9
refs/heads/master: 5f4f9f114eef4907b6077d19dd5ad7d0a27e0f80
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
#define BRCMF_E_REASON_MINTXRATE 9
#define BRCMF_E_REASON_TXFAIL 10

#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
#define BRCMF_E_REASON_DIRECTED_ROAM 6
#define BRCMF_E_REASON_TSPEC_REJECTED 7
Expand Down
64 changes: 52 additions & 12 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,26 @@ static int brcmf_p2p_request_p2p_if(struct brcmf_if *ifp, u8 ea[ETH_ALEN],
return err;
}

static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif)
{
struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
struct net_device *pri_ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(pri_ndev);
u8 *addr = vif->wdev.netdev->dev_addr;

return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN);
}

static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
{
struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
struct net_device *pri_ndev = cfg_to_ndev(cfg);
struct brcmf_if *ifp = netdev_priv(pri_ndev);
u8 *addr = vif->wdev.netdev->dev_addr;

return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
}

/**
* brcmf_p2p_add_vif() - create a new P2P virtual interface.
*
Expand Down Expand Up @@ -910,23 +930,43 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
struct brcmf_cfg80211_vif *vif;
unsigned long jiffie_timeout = msecs_to_jiffies(1500);
bool wait_for_disable = false;
int err;

brcmf_dbg(TRACE, "delete P2P vif\n");
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);

if (brcmf_cfg80211_vif_event_armed(cfg))
return -EBUSY;
switch (vif->wdev.iftype) {
case NL80211_IFTYPE_P2P_CLIENT:
if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
wait_for_disable = true;
break;

case NL80211_IFTYPE_P2P_GO:
if (!brcmf_p2p_disable_p2p_if(vif))
wait_for_disable = true;
break;

case NL80211_IFTYPE_P2P_DEVICE:
default:
return -ENOTSUPP;
break;
}

if (wait_for_disable)
wait_for_completion_timeout(&cfg->vif_disabled, 500);

brcmf_vif_clear_mgmt_ies(vif);

brcmf_cfg80211_arm_vif_event(cfg, vif);
/* wait for firmware event */
err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
msecs_to_jiffies(1500));
err = brcmf_p2p_release_p2p_if(vif);
if (!err)
/* wait for firmware event */
err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
jiffie_timeout);
brcmf_cfg80211_arm_vif_event(cfg, NULL);
if (wdev->netdev)
brcmf_dbg(INFO, "deleting vif \"%s\"\n", wdev->netdev->name);
else
brcmf_dbg(INFO, "deleting vif \"wdev-%u\"\n",
wdev->identifier);
brcmf_err("enter - not supported yet\n");
return -EOPNOTSUPP;
brcmf_free_vif(vif);

return err;
}
199 changes: 119 additions & 80 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,103 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
}
}

static void brcmf_set_mpc(struct net_device *ndev, int mpc)
{
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;

if (check_vif_up(ifp->vif)) {
err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
if (err) {
brcmf_err("fail to set mpc\n");
return;
}
brcmf_dbg(INFO, "MPC : %d\n", mpc);
}
}

static s32
brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
bool aborted, bool fw_abort)
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
s32 err = 0;

brcmf_dbg(SCAN, "Enter\n");

/* clear scan request, because the FW abort can cause a second call */
/* to this functon and might cause a double cfg80211_scan_done */
scan_request = cfg->scan_request;
cfg->scan_request = NULL;

if (timer_pending(&cfg->escan_timeout))
del_timer_sync(&cfg->escan_timeout);

if (fw_abort) {
/* Do a scan abort to stop the driver's scan engine */
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
memset(&params_le, 0, sizeof(params_le));
memset(params_le.bssid, 0xFF, ETH_ALEN);
params_le.bss_type = DOT11_BSSTYPE_ANY;
params_le.scan_type = 0;
params_le.channel_num = cpu_to_le32(1);
params_le.nprobes = cpu_to_le32(1);
params_le.active_time = cpu_to_le32(-1);
params_le.passive_time = cpu_to_le32(-1);
params_le.home_time = cpu_to_le32(-1);
/* Scan is aborted by setting channel_list[0] to -1 */
params_le.channel_list[0] = cpu_to_le16(-1);
/* E-Scan (or anyother type) can be aborted by SCAN */
err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
brcmf_err("Scan abort failed\n");
}
/*
* e-scan can be initiated by scheduled scan
* which takes precedence.
*/
if (cfg->sched_escan) {
brcmf_dbg(SCAN, "scheduled scan completed\n");
cfg->sched_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
brcmf_set_mpc(ndev, 1);
} else if (scan_request) {
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
brcmf_set_mpc(ndev, 1);
}
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("Scan complete while device not scanning\n");
return -EPERM;
}

return err;
}

static
int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
struct net_device *ndev = wdev->netdev;

/* vif event pending in firmware */
if (brcmf_cfg80211_vif_event_armed(cfg))
return -EBUSY;

if (ndev) {
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
cfg->escan_info.ndev == ndev)
brcmf_notify_escan_complete(cfg, ndev, true,
true);

brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
}

switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_STATION:
Expand Down Expand Up @@ -525,21 +619,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
return err;
}

static void brcmf_set_mpc(struct net_device *ndev, int mpc)
{
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;

if (check_vif_up(ifp->vif)) {
err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
if (err) {
brcmf_err("fail to set mpc\n");
return;
}
brcmf_dbg(INFO, "MPC : %d\n", mpc);
}
}

static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
struct cfg80211_scan_request *request)
{
Expand Down Expand Up @@ -619,69 +698,6 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
}

static s32
brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
bool aborted, bool fw_abort)
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
s32 err = 0;

brcmf_dbg(SCAN, "Enter\n");

/* clear scan request, because the FW abort can cause a second call */
/* to this functon and might cause a double cfg80211_scan_done */
scan_request = cfg->scan_request;
cfg->scan_request = NULL;

if (timer_pending(&cfg->escan_timeout))
del_timer_sync(&cfg->escan_timeout);

if (fw_abort) {
/* Do a scan abort to stop the driver's scan engine */
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
memset(&params_le, 0, sizeof(params_le));
memset(params_le.bssid, 0xFF, ETH_ALEN);
params_le.bss_type = DOT11_BSSTYPE_ANY;
params_le.scan_type = 0;
params_le.channel_num = cpu_to_le32(1);
params_le.nprobes = cpu_to_le32(1);
params_le.active_time = cpu_to_le32(-1);
params_le.passive_time = cpu_to_le32(-1);
params_le.home_time = cpu_to_le32(-1);
/* Scan is aborted by setting channel_list[0] to -1 */
params_le.channel_list[0] = cpu_to_le16(-1);
/* E-Scan (or anyother type) can be aborted by SCAN */
err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
brcmf_err("Scan abort failed\n");
}
/*
* e-scan can be initiated by scheduled scan
* which takes precedence.
*/
if (cfg->sched_escan) {
brcmf_dbg(SCAN, "scheduled scan completed\n");
cfg->sched_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
brcmf_set_mpc(ndev, 1);
} else if (scan_request) {
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
brcmf_set_mpc(ndev, 1);
}
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("Scan complete while device not scanning\n");
return -EPERM;
}

return err;
}

static s32
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
struct cfg80211_scan_request *request, u16 action)
Expand Down Expand Up @@ -3474,6 +3490,22 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
return err;
}

s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
{
s32 pktflags[] = {
BRCMF_VNDR_IE_PRBREQ_FLAG,
BRCMF_VNDR_IE_PRBRSP_FLAG,
BRCMF_VNDR_IE_BEACON_FLAG
};
int i;

for (i = 0; i < ARRAY_SIZE(pktflags); i++)
brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);

memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));
return 0;
}

static s32
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ap_settings *settings)
Expand Down Expand Up @@ -4260,6 +4292,12 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
struct station_info sinfo;

brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
ndev != cfg_to_ndev(cfg)) {
brcmf_dbg(CONN, "AP mode link down\n");
complete(&cfg->vif_disabled);
return 0;
}

if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
(reason == BRCMF_E_STATUS_SUCCESS)) {
Expand Down Expand Up @@ -4316,6 +4354,8 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
}
brcmf_link_down(ifp->vif);
brcmf_init_prof(ndev_to_prof(ndev));
if (ndev != cfg_to_ndev(cfg))
complete(&cfg->vif_disabled);
} else if (brcmf_is_nonetwork(cfg, e)) {
if (brcmf_is_ibssmode(ifp->vif))
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
Expand Down Expand Up @@ -4401,7 +4441,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,

case BRCMF_E_IF_DEL:
ifp->vif = NULL;
brcmf_free_vif(vif);
mutex_unlock(&event->vif_event_lock);
/* event may not be upon user request */
if (brcmf_cfg80211_vif_event_armed(cfg))
Expand Down Expand Up @@ -4507,7 +4546,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
mutex_init(&cfg->usr_sync);
brcmf_init_escan(cfg);
brcmf_init_conf(cfg->conf);

init_completion(&cfg->vif_disabled);
return err;
}

Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,15 @@ struct brcmf_cfg80211_profile {
* @BRCMF_VIF_STATUS_READY: ready for operation.
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
*/
enum brcmf_vif_status {
BRCMF_VIF_STATUS_READY,
BRCMF_VIF_STATUS_CONNECTING,
BRCMF_VIF_STATUS_CONNECTED,
BRCMF_VIF_STATUS_DISCONNECTING,
BRCMF_VIF_STATUS_AP_CREATING,
BRCMF_VIF_STATUS_AP_CREATED
};
Expand Down Expand Up @@ -405,6 +407,7 @@ struct brcmf_cfg80211_info {
struct list_head vif_list;
u8 vif_cnt;
struct brcmf_cfg80211_vif_event vif_event;
struct completion vif_disabled;
};

/**
Expand Down Expand Up @@ -479,6 +482,7 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);

s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
const u8 *vndr_ie_buf, u32 vndr_ie_len);
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
u16 channel_to_chanspec(struct ieee80211_channel *ch);
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
Expand Down

0 comments on commit 9b80e87

Please sign in to comment.