Skip to content

Instantly share code, notes, and snippets.

@dberlin
Created November 28, 2023 18:31
Show Gist options
  • Save dberlin/31401500fcd83d5cee0effac49a5dce4 to your computer and use it in GitHub Desktop.
Save dberlin/31401500fcd83d5cee0effac49a5dce4 to your computer and use it in GitHub Desktop.
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 326c1fb07257..cdb67ebff97e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -100,6 +100,14 @@
#define PKT_TOKEN_IDX 15
#define IDLE_TOKEN_IDX 12
+
+#define MGMT_AUTH_FRAME_DWELL_TIME 4000
+#define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100)
+#define BRCMF_EXTAUTH_START 1
+#define BRCMF_EXTAUTH_ABORT 2
+#define BRCMF_EXTAUTH_FAIL 3
+#define BRCMF_EXTAUTH_SUCCESS 4
+
struct brcmf_dump_survey {
u32 obss;
u32 ibss;
@@ -1365,7 +1373,7 @@ static int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16
static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
{
- return brcmf_set_wsec(ifp, pmk_data, pmk_len, 0);
+ return brcmf_set_wsec(ifp, pmk_data, pmk_len, BRCMF_WSEC_PASSPHRASE);
}
static int brcmf_set_sae_password(struct brcmf_if *ifp, const u8 *pwd_data,
@@ -5399,6 +5407,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
s32 ie_len;
struct brcmf_fil_action_frame_le *action_frame;
struct brcmf_fil_af_params_le *af_params;
+
bool ack;
s32 chan_nr;
u32 freq;
@@ -5482,11 +5491,85 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
GFP_KERNEL);
kfree(af_params);
+ } else if (ieee80211_is_auth(mgmt->frame_control)) {
+ struct brcmf_mf_params_le *mf_params;
+ u32 mf_params_len;
+ s32 timeout;
+ u32 hw_channel;
+
+ reinit_completion(&vif->mgmt_tx);
+ clear_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
+ clear_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
+ clear_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED,
+ &vif->mgmt_tx_status);
+
+ mf_params_len = offsetof(struct brcmf_mf_params_le, data) +
+ (len - DOT11_MGMT_HDR_LEN);
+ mf_params = kzalloc(mf_params_len, GFP_KERNEL);
+ if (!mf_params) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ mf_params->dwell_time = cpu_to_le32(MGMT_AUTH_FRAME_DWELL_TIME);
+ mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
+ mf_params->frame_control = mgmt->frame_control;
+
+ if (chan) {
+ freq = chan->center_freq;
+ chan_nr = ieee80211_frequency_to_channel(freq);
+ mf_params->channel = cpu_to_le32(chan_nr);
+ } else {
+ brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL,
+ &hw_channel);
+ mf_params->channel = hw_channel;
+ }
+
+ memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN);
+ memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
+ mf_params->packet_id = cpu_to_le32(*cookie);
+ memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN],
+ le16_to_cpu(mf_params->len));
+
+ brcmf_dbg(
+ TRACE,
+ "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n",
+ le32_to_cpu(mf_params->packet_id),
+ le16_to_cpu(mf_params->frame_control),
+ le16_to_cpu(mf_params->len),
+ le32_to_cpu(mf_params->channel));
+
+ vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id);
+ set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status);
+
+ err = brcmf_fil_bsscfg_data_set(vif->ifp, "mgmt_frame",
+ mf_params, mf_params_len);
+ if (err) {
+ bphy_err(drvr, "Failed to send Auth frame: err=%d\n",
+ err);
+ goto tx_status;
+ }
+
+ timeout = wait_for_completion_timeout(
+ &vif->mgmt_tx, MGMT_AUTH_FRAME_WAIT_TIME);
+ if (test_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status)) {
+ brcmf_dbg(TRACE,
+ "TX Auth frame operation is success\n");
+ ack = true;
+ } else {
+ bphy_err(
+ drvr,
+ "TX Auth frame operation is failed: status=%ld)\n",
+ vif->mgmt_tx_status);
+ }
+tx_status:
+ cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
+ GFP_KERNEL);
+ kfree(mf_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;
}
@@ -5830,6 +5913,43 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
return brcmf_set_pmk(ifp, NULL, 0);
}
+static int
+brcmf_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_external_auth_params *params)
+{
+ struct brcmf_if *ifp;
+ struct brcmf_pub *drvr;
+ struct brcmf_auth_req_status_le auth_status;
+ int ret = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ ifp = netdev_priv(dev);
+ drvr = ifp->drvr;
+ if (params->status == WLAN_STATUS_SUCCESS) {
+ auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS);
+ } else {
+ bphy_err(drvr, "External authentication failed: status=%d\n",
+ params->status);
+ auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_FAIL);
+ }
+
+ memcpy(auth_status.peer_mac, params->bssid, ETH_ALEN);
+ auth_status.ssid_len = cpu_to_le32(
+ min_t(u8, params->ssid.ssid_len, IEEE80211_MAX_SSID_LEN));
+ memcpy(auth_status.ssid, params->ssid.ssid, auth_status.ssid_len);
+ memset(auth_status.pmkid, 0, WLAN_PMKID_LEN);
+ if (params->pmkid)
+ memcpy(auth_status.pmkid, params->pmkid, WLAN_PMKID_LEN);
+
+ ret = brcmf_fil_iovar_data_set(ifp, "auth_status", &auth_status,
+ sizeof(auth_status));
+ if (ret < 0)
+ bphy_err(drvr, "auth_status iovar failed: ret=%d\n", ret);
+
+ return ret;
+}
+
static struct cfg80211_ops brcmf_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -5877,6 +5997,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
.update_connect_params = brcmf_cfg80211_update_conn_params,
.set_pmk = brcmf_cfg80211_set_pmk,
.del_pmk = brcmf_cfg80211_del_pmk,
+ .external_auth = brcmf_cfg80211_external_auth,
};
struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings)
@@ -6666,6 +6787,162 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
return -EINVAL;
}
+static s32
+brcmf_notify_ext_auth_request(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e, void *data)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct cfg80211_external_auth_params params;
+ struct brcmf_auth_req_status_le *auth_req =
+ (struct brcmf_auth_req_status_le *)data;
+ s32 err = 0;
+
+ brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
+ brcmf_fweh_event_name(e->event_code), e->event_code);
+
+ if (e->datalen < sizeof(*auth_req)) {
+ bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
+ brcmf_fweh_event_name(e->event_code), e->event_code);
+ return -EINVAL;
+ }
+
+ memset(&params, 0, sizeof(params));
+ params.action = NL80211_EXTERNAL_AUTH_START;
+ params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE);
+ params.status = WLAN_STATUS_SUCCESS;
+ params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len));
+ memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
+ memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN);
+
+ err = cfg80211_external_auth_request(ifp->ndev, &params, GFP_ATOMIC);
+ if (err)
+ bphy_err(drvr, "Ext Auth request to supplicant failed (%d)\n",
+ err);
+
+ return err;
+}
+
+int brcmf_extract_mgmt_frame_data(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e, void *data,
+ u16 *chanspec, u32 *mgmt_frame_len,
+ u8 **mgmt_frame)
+{
+ struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
+ struct brcmf_rx_mgmt_data_v2 *rxframe_v2 =
+ (struct brcmf_rx_mgmt_data_v2 *)data;
+ struct brcmf_pub *drvr = ifp->drvr;
+ u16 version;
+
+ version = be16_to_cpu(rxframe->version);
+ if (version == 1) {
+ if (e->datalen < sizeof(*rxframe)) {
+ bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
+ brcmf_fweh_event_name(e->event_code),
+ e->event_code);
+ return -EINVAL;
+ }
+ *mgmt_frame_len =
+ e->datalen - sizeof(struct brcmf_rx_mgmt_data);
+ *mgmt_frame = (u8 *)(rxframe + 1);
+ *chanspec = be16_to_cpu(rxframe->chanspec);
+
+ } else if (version == 2) {
+ if (e->datalen < sizeof(*rxframe_v2)) {
+ bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
+ brcmf_fweh_event_name(e->event_code),
+ e->event_code);
+ return -EINVAL;
+ }
+ *mgmt_frame_len =
+ e->datalen - sizeof(struct brcmf_rx_mgmt_data_v2);
+
+ *mgmt_frame = (u8 *)(rxframe_v2 + 1);
+ *chanspec = be16_to_cpu(rxframe_v2->chanspec);
+ } else {
+ bphy_err(drvr, "Unsupported mgmt data version:%d\n", version);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static s32
+brcmf_notify_auth_frame_rx(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e, void *data)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_cfg80211_info *cfg = drvr->config;
+ struct wireless_dev *wdev;
+ u32 mgmt_frame_len;
+ u8 *frame;
+ struct brcmu_chan ch;
+ struct ieee80211_mgmt *mgmt_frame;
+ s32 freq;
+ u16 chanspec = 0;
+ s32 err;
+
+ brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
+ brcmf_fweh_event_name(e->event_code), e->event_code);
+ err = brcmf_extract_mgmt_frame_data(ifp, e, data, &chanspec, &mgmt_frame_len, &frame);
+ if (err) {
+ bphy_err(drvr, "Error extracting management frame data:%d\n", err);
+ return err;
+ }
+ wdev = &ifp->vif->wdev;
+ WARN_ON(!wdev);
+
+ ch.chspec = chanspec;
+ cfg->d11inf.decchspec(&ch);
+
+ mgmt_frame = kzalloc(mgmt_frame_len, GFP_KERNEL);
+ if (!mgmt_frame)
+ return -ENOMEM;
+
+ mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
+ memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
+ memcpy(mgmt_frame->sa, e->addr, ETH_ALEN);
+ brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid,
+ ETH_ALEN);
+ frame += offsetof(struct ieee80211_mgmt, u);
+ memcpy(&mgmt_frame->u, frame,
+ mgmt_frame_len - offsetof(struct ieee80211_mgmt, u));
+
+ freq = ieee80211_channel_to_frequency(
+ ch.control_ch_num, fwil_band_to_nl80211(ch.band));
+
+ cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
+ NL80211_RXMGMT_FLAG_EXTERNAL_AUTH);
+ kfree(mgmt_frame);
+ return 0;
+}
+
+static s32 brcmf_notify_mgmt_tx_status(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e,
+ void *data)
+{
+ struct brcmf_cfg80211_vif *vif = ifp->vif;
+ u32 *packet_id = (u32 *)data;
+
+ brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n",
+ brcmf_fweh_event_name(e->event_code), e->event_code,
+ e->status);
+
+ if (!test_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status) ||
+ (*packet_id != vif->mgmt_tx_id))
+ return 0;
+
+ if (e->event_code == BRCMF_E_MGMT_FRAME_TXSTATUS) {
+ if (e->status == BRCMF_E_STATUS_SUCCESS)
+ set_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
+ else
+ set_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
+ } else {
+ set_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, &vif->mgmt_tx_status);
+ }
+
+ complete(&vif->mgmt_tx);
+ return 0;
+}
+
static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
{
conf->frag_threshold = (u32)-1;
@@ -6708,6 +6985,14 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
brcmf_p2p_notify_action_tx_complete);
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
brcmf_p2p_notify_action_tx_complete);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_REQ,
+ brcmf_notify_ext_auth_request);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_EXT_AUTH_FRAME_RX,
+ brcmf_notify_auth_frame_rx);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_TXSTATUS,
+ brcmf_notify_mgmt_tx_status);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_MGMT_FRAME_OFF_CHAN_COMPLETE,
+ brcmf_notify_mgmt_tx_status);
brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
brcmf_notify_connect_status);
brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, brcmf_notify_rssi);
@@ -7742,6 +8027,7 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
},
[NL80211_IFTYPE_P2P_CLIENT] = {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index c1685c53b74d..64a8815a497d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -93,6 +93,21 @@
#define BRCMF_VIF_EVENT_TIMEOUT msecs_to_jiffies(1500)
+/**
+ * enum brcmf_mgmt_tx_status - mgmt frame tx status
+ *
+ * @BRCMF_MGMT_TX_ACK: mgmt frame acked
+ * @BRCMF_MGMT_TX_NOACK: mgmt frame not acked
+ * @BRCMF_MGMT_TX_OFF_CHAN_COMPLETED: off-channel complete
+ * @BRCMF_MGMT_TX_SEND_FRAME: mgmt frame tx is in progres
+ */
+enum brcmf_mgmt_tx_status {
+ BRCMF_MGMT_TX_ACK,
+ BRCMF_MGMT_TX_NOACK,
+ BRCMF_MGMT_TX_OFF_CHAN_COMPLETED,
+ BRCMF_MGMT_TX_SEND_FRAME
+};
+
/**
* enum brcmf_scan_status - scan engine status
*
@@ -227,6 +242,9 @@ struct brcmf_cfg80211_vif {
unsigned long sme_state;
struct vif_saved_ie saved_ie;
struct list_head list;
+ struct completion mgmt_tx;
+ unsigned long mgmt_tx_status;
+ u32 mgmt_tx_id;
u16 mgmt_rx_reg;
bool mbss;
int is_11d;
@@ -490,5 +508,8 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
void brcmf_cfg80211_free_netdev(struct net_device *ndev);
-
+s32 brcmf_extract_mgmt_frame_data(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e,
+ void *data, u16 *chanspec, u32 *mgmt_frame_len,
+ u8 **mgmt_frame);
#endif /* BRCMFMAC_CFG80211_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index 041e5efb852d..7c658dc7fe6d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -61,7 +61,7 @@ struct brcmf_cfg80211_info;
BRCMF_ENUM_DEF(IBSS_ASSOC, 39) \
BRCMF_ENUM_DEF(RADIO, 40) \
BRCMF_ENUM_DEF(PSM_WATCHDOG, 41) \
- BRCMF_ENUM_DEF(PROBREQ_MSG, 44) \
+ BRCMF_ENUM_DEF(PROBEREQ_MSG, 44) \
BRCMF_ENUM_DEF(SCAN_CONFIRM_IND, 45) \
BRCMF_ENUM_DEF(PSK_SUP, 46) \
BRCMF_ENUM_DEF(COUNTRY_CODE_CHANGED, 47) \
@@ -90,7 +90,13 @@ struct brcmf_cfg80211_info;
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
- BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
+ BRCMF_ENUM_DEF(PHY_TEMP, 111) \
+ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
+ BRCMF_ENUM_DEF(PROBEREQ_MSG_RX, 137) \
+ BRCMF_ENUM_DEF(EXT_AUTH_REQ, 187) \
+ BRCMF_ENUM_DEF(EXT_AUTH_FRAME_RX, 188) \
+ BRCMF_ENUM_DEF(MGMT_FRAME_TXSTATUS, 189) \
+ BRCMF_ENUM_DEF(MGMT_FRAME_OFF_CHAN_COMPLETE, 190)
#define BRCMF_ENUM_DEF(id, val) \
BRCMF_E_##id = (val),
@@ -102,7 +108,7 @@ enum brcmf_fweh_event_code {
* minimum length check in device firmware so it is
* hard-coded here.
*/
- BRCMF_E_LAST = 139
+ BRCMF_E_LAST = 196
};
#undef BRCMF_ENUM_DEF
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 39ad612802e2..b93d249a9f7f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -71,8 +71,8 @@
#define BRCMF_SCANSSID_INC_RNR 0x02 /* Include RNR channels*/
#define BRCMF_WSEC_MAX_PSK_LEN 32
-#define BRCMF_WSEC_PASSPHRASE BIT(0)
-
+#define BRCMF_WSEC_PASSPHRASE BIT(0) /* PSK password */
+#define BRCMF_WSEC_SAE_PASSPHRASE BIT(1) /* SAE password */
#define BRCMF_WSEC_MAX_SAE_PASSWORD_LEN 256
/* primary (ie tx) key */
@@ -811,6 +811,47 @@ struct brcmf_wsec_sae_pwd_le {
u8 key[BRCMF_WSEC_MAX_SAE_PASSWORD_LEN];
};
+/**
+ * struct brcmf_auth_req_status_le - external auth request and status update
+ *
+ * @flags: flags for external auth status
+ * @peer_mac: peer MAC address
+ * @ssid_len: length of ssid
+ * @ssid: ssid characters
+ */
+struct brcmf_auth_req_status_le {
+ __le16 flags;
+ u8 peer_mac[ETH_ALEN];
+ __le32 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 pmkid[WLAN_PMKID_LEN];
+};
+
+/**
+ * struct brcmf_mf_params_le - management frame parameters for mgmt_frame iovar
+ *
+ * @version: version of the iovar
+ * @dwell_time: dwell duration in ms
+ * @len: length of frame data
+ * @frame_control: frame control
+ * @channel: channel
+ * @da: peer MAC address
+ * @bssid: BSS network identifier
+ * @packet_id: packet identifier
+ * @data: frame data
+ */
+struct brcmf_mf_params_le {
+ __le32 version;
+ __le32 dwell_time;
+ __le16 len;
+ __le16 frame_control;
+ __le16 channel;
+ u8 da[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ __le32 packet_id;
+ u8 data[1];
+};
+
/* Used to get specific STA parameters */
struct brcmf_scb_val_le {
__le32 val;
@@ -972,6 +1013,18 @@ struct brcmf_rx_mgmt_data {
__be32 rate;
};
+#define BRCMF_MAX_PHY_CORE_NUM 4
+struct brcmf_rx_mgmt_data_v2 {
+ __be16 version;
+ __be16 length;
+ __be16 chanspec;
+ __be16 pad;
+ __be32 rssi;
+ __be32 mactime;
+ __be32 rate;
+ char per_core_rssi[BRCMF_MAX_PHY_CORE_NUM];
+};
+
/**
* struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct.
*
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 071b0706d137..e6be87631c4d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -1391,9 +1391,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct wireless_dev *wdev;
- u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data);
- struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
- u8 *frame = (u8 *)(rxframe + 1);
+ u32 mgmt_frame_len;
+ u8 *frame;
struct brcmf_p2p_pub_act_frame *act_frm;
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
struct brcmu_chan ch;
@@ -1401,13 +1400,18 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
s32 freq;
u16 mgmt_type;
u8 action;
+ u16 chanspec;
+ s32 err;
- if (e->datalen < sizeof(*rxframe)) {
- brcmf_dbg(SCAN, "Event data to small. Ignore\n");
- return 0;
+ err = brcmf_extract_mgmt_frame_data(ifp, e, data, &chanspec,
+ &mgmt_frame_len, &frame);
+ if (err) {
+ bphy_err(cfg, "Error extracting management frame data:%d\n",
+ err);
+ return err;
}
- ch.chspec = be16_to_cpu(rxframe->chanspec);
+ ch.chspec = chanspec;
cfg->d11inf.decchspec(&ch);
/* Check if wpa_supplicant has registered for this frame */
brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
@@ -1938,22 +1942,26 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct brcmf_cfg80211_vif *vif = ifp->vif;
- struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
struct brcmu_chan ch;
u8 *mgmt_frame;
u32 mgmt_frame_len;
s32 freq;
u16 mgmt_type;
+ s32 err;
+ u16 chanspec;
brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
e->reason);
- if (e->datalen < sizeof(*rxframe)) {
- brcmf_dbg(SCAN, "Event data to small. Ignore\n");
- return 0;
+ err = brcmf_extract_mgmt_frame_data(ifp, e, data, &chanspec,
+ &mgmt_frame_len, &mgmt_frame);
+ if (err) {
+ bphy_err(cfg, "Error extracting management frame data:%d\n",
+ err);
+ return err;
}
- ch.chspec = be16_to_cpu(rxframe->chanspec);
+ ch.chspec = chanspec;
cfg->d11inf.decchspec(&ch);
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
@@ -1981,8 +1989,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
if ((vif->mgmt_rx_reg & BIT(mgmt_type)) == 0)
return 0;
- mgmt_frame = (u8 *)(rxframe + 1);
- mgmt_frame_len = e->datalen - sizeof(*rxframe);
freq = ieee80211_channel_to_frequency(ch.control_ch_num,
ch.band == BRCMU_CHAN_BAND_2G ?
NL80211_BAND_2GHZ :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment