Commit 18e2f61d authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville

brcmfmac: P2P action frame tx.

With this patch it is possible to send action frames.
Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e6da3400
......@@ -20,6 +20,10 @@
#include <linux/if_ether.h>
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
enum brcmf_fil_p2p_if_types {
BRCMF_FIL_P2P_IF_CLIENT,
BRCMF_FIL_P2P_IF_GO,
......@@ -39,6 +43,21 @@ struct brcmf_fil_chan_info_le {
__le32 scan_channel;
};
struct brcmf_fil_action_frame_le {
u8 da[ETH_ALEN];
__le16 len;
__le32 packet_id;
u8 data[BRCMF_FIL_ACTION_FRAME_SIZE];
};
struct brcmf_fil_af_params_le {
__le32 channel;
__le32 dwell_time;
u8 bssid[ETH_ALEN];
u8 pad[2];
struct brcmf_fil_action_frame_le action_frame;
};
struct brcmf_fil_bss_enable_le {
__le32 bsscfg_idx;
__le32 enable;
......
......@@ -89,6 +89,8 @@ enum brcmf_p2p_status {
* @ssid: ssid for P2P GO.
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
* @remain_on_channel: contains copy of struct used by cfg80211.
* @next_af_subtype: expected action frame subtype.
* @send_af_done: indication that action frame tx is complete.
*/
struct brcmf_p2p_info {
struct brcmf_cfg80211_info *cfg;
......@@ -100,6 +102,8 @@ struct brcmf_p2p_info {
struct brcmf_ssid ssid;
u8 listen_channel;
struct ieee80211_channel remain_on_channel;
u8 next_af_subtype;
struct completion send_af_done;
};
void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg,
......@@ -126,5 +130,11 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
const struct brcmf_event_msg *e,
void *data);
int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
const struct brcmf_event_msg *e,
void *data);
bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
struct brcmf_fil_af_params_le *af_params);
#endif /* WL_CFGP2P_H_ */
......@@ -2494,7 +2494,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
return err;
}
static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
{
struct escan_info *escan = &cfg->escan_info;
......@@ -3949,6 +3949,10 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
s32 err = 0;
s32 ie_offset;
s32 ie_len;
struct brcmf_fil_action_frame_le *action_frame;
struct brcmf_fil_af_params_le *af_params;
bool ack;
s32 chan_nr;
brcmf_dbg(TRACE, "Enter\n");
......@@ -3986,11 +3990,44 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
ie_len);
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
GFP_KERNEL);
} else if (ieee80211_is_action(mgmt->frame_control)) {
af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
if (af_params == NULL) {
brcmf_err("unable to allocate frame\n");
err = -ENOMEM;
goto exit;
}
action_frame = &af_params->action_frame;
/* Add the packet Id */
action_frame->packet_id = cpu_to_le32(*cookie);
/* Add BSSID */
memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN);
memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
/* Add the length exepted for 802.11 header */
action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
/* Add the channel */
chan_nr = ieee80211_frequency_to_channel(chan->center_freq);
af_params->channel = cpu_to_le32(chan_nr);
memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],
le16_to_cpu(action_frame->len));
brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n",
*cookie, le16_to_cpu(action_frame->len),
chan->center_freq);
ack = brcmf_p2p_send_action_frame(cfg, wdev->netdev,
af_params);
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
GFP_KERNEL);
kfree(af_params);
} else {
brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len);
}
exit:
return err;
}
......@@ -4703,6 +4740,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
brcmf_p2p_notify_listen_complete);
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
brcmf_p2p_notify_action_frame_rx);
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE,
brcmf_p2p_notify_action_tx_complete);
}
static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
......
......@@ -498,5 +498,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev,
bool aborted, bool fw_abort);
void brcmf_set_mpc(struct net_device *ndev, int mpc);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
#endif /* _wl_cfg80211_h_ */
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