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 @@ ...@@ -20,6 +20,10 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
enum brcmf_fil_p2p_if_types { enum brcmf_fil_p2p_if_types {
BRCMF_FIL_P2P_IF_CLIENT, BRCMF_FIL_P2P_IF_CLIENT,
BRCMF_FIL_P2P_IF_GO, BRCMF_FIL_P2P_IF_GO,
...@@ -39,6 +43,21 @@ struct brcmf_fil_chan_info_le { ...@@ -39,6 +43,21 @@ struct brcmf_fil_chan_info_le {
__le32 scan_channel; __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 { struct brcmf_fil_bss_enable_le {
__le32 bsscfg_idx; __le32 bsscfg_idx;
__le32 enable; __le32 enable;
......
...@@ -89,6 +89,8 @@ enum brcmf_p2p_status { ...@@ -89,6 +89,8 @@ enum brcmf_p2p_status {
* @ssid: ssid for P2P GO. * @ssid: ssid for P2P GO.
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state. * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
* @remain_on_channel: contains copy of struct used by cfg80211. * @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_p2p_info {
struct brcmf_cfg80211_info *cfg; struct brcmf_cfg80211_info *cfg;
...@@ -100,6 +102,8 @@ struct brcmf_p2p_info { ...@@ -100,6 +102,8 @@ struct brcmf_p2p_info {
struct brcmf_ssid ssid; struct brcmf_ssid ssid;
u8 listen_channel; u8 listen_channel;
struct ieee80211_channel remain_on_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, void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg,
...@@ -126,5 +130,11 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp); ...@@ -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, int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, const struct brcmf_event_msg *e,
void *data); 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_ */ #endif /* WL_CFGP2P_H_ */
...@@ -2494,7 +2494,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, ...@@ -2494,7 +2494,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
return err; 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; struct escan_info *escan = &cfg->escan_info;
...@@ -3949,6 +3949,10 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -3949,6 +3949,10 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
s32 err = 0; s32 err = 0;
s32 ie_offset; s32 ie_offset;
s32 ie_len; 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"); brcmf_dbg(TRACE, "Enter\n");
...@@ -3986,11 +3990,44 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ...@@ -3986,11 +3990,44 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
ie_len); ie_len);
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
GFP_KERNEL); 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 { } else {
brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control); brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len); brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len);
} }
exit:
return err; return err;
} }
...@@ -4703,6 +4740,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg) ...@@ -4703,6 +4740,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
brcmf_p2p_notify_listen_complete); brcmf_p2p_notify_listen_complete);
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX, brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
brcmf_p2p_notify_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) 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, ...@@ -498,5 +498,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev, struct net_device *ndev,
bool aborted, bool fw_abort); bool aborted, bool fw_abort);
void brcmf_set_mpc(struct net_device *ndev, int mpc); void brcmf_set_mpc(struct net_device *ndev, int mpc);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
#endif /* _wl_cfg80211_h_ */ #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