Commit 5bc8c1f2 authored by Johannes Berg's avatar Johannes Berg

cfg80211: allow passing frame type to cfg80211_inform_bss()

When using the cfg80211_inform_bss[_width]() functions drivers
cannot currently indicate whether the data was received in a
beacon or probe response. Fix that by passing a new enum that
indicates such (or unknown).

For good measure, use it in ath6kl.

Acked-by: Kalle Valo <kvalo@qca.qualcomm.com> [ath6kl]
Acked-by: Arend van Spriel <arend@broadcom.com> [brcmfmac]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0e227084
...@@ -717,6 +717,7 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, ...@@ -717,6 +717,7 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
memcpy(ie + 2, vif->ssid, vif->ssid_len); memcpy(ie + 2, vif->ssid, vif->ssid_len);
memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len); memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
bss = cfg80211_inform_bss(ar->wiphy, chan, bss = cfg80211_inform_bss(ar->wiphy, chan,
CFG80211_BSS_FTYPE_UNKNOWN,
bssid, 0, cap_val, 100, bssid, 0, cap_val, 100,
ie, 2 + vif->ssid_len + beacon_ie_len, ie, 2 + vif->ssid_len + beacon_ie_len,
0, GFP_KERNEL); 0, GFP_KERNEL);
......
...@@ -1092,7 +1092,6 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, ...@@ -1092,7 +1092,6 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
u8 *buf; u8 *buf;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
struct ath6kl *ar = wmi->parent_dev; struct ath6kl *ar = wmi->parent_dev;
struct ieee80211_mgmt *mgmt;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
if (len <= sizeof(struct wmi_bss_info_hdr2)) if (len <= sizeof(struct wmi_bss_info_hdr2))
...@@ -1138,39 +1137,15 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, ...@@ -1138,39 +1137,15 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
} }
} }
/* bss = cfg80211_inform_bss(ar->wiphy, channel,
* In theory, use of cfg80211_inform_bss() would be more natural here bih->frame_type == BEACON_FTYPE ?
* since we do not have the full frame. However, at least for now, CFG80211_BSS_FTYPE_BEACON :
* cfg80211 can only distinguish Beacon and Probe Response frames from CFG80211_BSS_FTYPE_PRESP,
* each other when using cfg80211_inform_bss_frame(), so let's build a bih->bssid, get_unaligned_le64((__le64 *)buf),
* fake IEEE 802.11 header to be able to take benefit of this. get_unaligned_le16(((__le16 *)buf) + 5),
*/ get_unaligned_le16(((__le16 *)buf) + 4),
mgmt = kmalloc(24 + len, GFP_ATOMIC); buf + 8 + 2 + 2, len - 8 - 2 - 2,
if (mgmt == NULL) (bih->snr - 95) * 100, GFP_ATOMIC);
return -EINVAL;
if (bih->frame_type == BEACON_FTYPE) {
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_BEACON);
memset(mgmt->da, 0xff, ETH_ALEN);
} else {
struct net_device *dev = vif->ndev;
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
memcpy(mgmt->da, dev->dev_addr, ETH_ALEN);
}
mgmt->duration = cpu_to_le16(0);
memcpy(mgmt->sa, bih->bssid, ETH_ALEN);
memcpy(mgmt->bssid, bih->bssid, ETH_ALEN);
mgmt->seq_ctrl = cpu_to_le16(0);
memcpy(&mgmt->u.beacon, buf, len);
bss = cfg80211_inform_bss_frame(ar->wiphy, channel, mgmt,
24 + len, (bih->snr - 95) * 100,
GFP_ATOMIC);
kfree(mgmt);
if (bss == NULL) if (bss == NULL)
return -ENOMEM; return -ENOMEM;
cfg80211_put_bss(ar->wiphy, bss); cfg80211_put_bss(ar->wiphy, bss);
......
...@@ -346,7 +346,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) ...@@ -346,7 +346,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
rx_mgmt_frame->bssid); rx_mgmt_frame->bssid);
cfg80211_put_bss(wiphy, bss); cfg80211_put_bss(wiphy, bss);
} else { } else {
wil_err(wil, "cfg80211_inform_bss() failed\n"); wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
} }
} else { } else {
cfg80211_rx_mgmt(wil->wdev, freq, signal, cfg80211_rx_mgmt(wil->wdev, freq, signal,
......
...@@ -2394,9 +2394,13 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, ...@@ -2394,9 +2394,13 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval); brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
brcmf_dbg(CONN, "Signal: %d\n", notify_signal); brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, bss = cfg80211_inform_bss(wiphy, notify_channel,
0, notify_capability, notify_interval, notify_ie, CFG80211_BSS_FTYPE_UNKNOWN,
notify_ielen, notify_signal, GFP_KERNEL); (const u8 *)bi->BSSID,
0, notify_capability,
notify_interval, notify_ie,
notify_ielen, notify_signal,
GFP_KERNEL);
if (!bss) if (!bss)
return -ENOMEM; return -ENOMEM;
...@@ -2498,9 +2502,11 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, ...@@ -2498,9 +2502,11 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval); brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
brcmf_dbg(CONN, "signal: %d\n", notify_signal); brcmf_dbg(CONN, "signal: %d\n", notify_signal);
bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, bss = cfg80211_inform_bss(wiphy, notify_channel,
0, notify_capability, notify_interval, CFG80211_BSS_FTYPE_UNKNOWN, bssid, 0,
notify_ie, notify_ielen, notify_signal, GFP_KERNEL); notify_capability, notify_interval,
notify_ie, notify_ielen, notify_signal,
GFP_KERNEL);
if (!bss) { if (!bss) {
err = -ENOMEM; err = -ENOMEM;
......
...@@ -653,6 +653,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, ...@@ -653,6 +653,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
if (channel && if (channel &&
!(channel->flags & IEEE80211_CHAN_DISABLED)) { !(channel->flags & IEEE80211_CHAN_DISABLED)) {
bss = cfg80211_inform_bss(wiphy, channel, bss = cfg80211_inform_bss(wiphy, channel,
CFG80211_BSS_FTYPE_UNKNOWN,
bssid, get_unaligned_le64(tsfdesc), bssid, get_unaligned_le64(tsfdesc),
capa, intvl, ie, ielen, capa, intvl, ie, ielen,
LBS_SCAN_RSSI_TO_MBM(rssi), LBS_SCAN_RSSI_TO_MBM(rssi),
...@@ -1754,6 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv, ...@@ -1754,6 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv,
bss = cfg80211_inform_bss(priv->wdev->wiphy, bss = cfg80211_inform_bss(priv->wdev->wiphy,
params->chandef.chan, params->chandef.chan,
CFG80211_BSS_FTYPE_UNKNOWN,
bssid, bssid,
0, 0,
capability, capability,
......
...@@ -1557,6 +1557,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) ...@@ -1557,6 +1557,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
band)); band));
bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
CFG80211_BSS_FTYPE_UNKNOWN,
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
0, ie_buf, ie_len, 0, GFP_KERNEL); 0, ie_buf, ie_len, 0, GFP_KERNEL);
cfg80211_put_bss(priv->wdev->wiphy, bss); cfg80211_put_bss(priv->wdev->wiphy, bss);
......
...@@ -1719,7 +1719,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, ...@@ -1719,7 +1719,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
bss = cfg80211_inform_bss(priv->wdev->wiphy, bss = cfg80211_inform_bss(priv->wdev->wiphy,
chan, bssid, timestamp, chan, CFG80211_BSS_FTYPE_UNKNOWN,
bssid, timestamp,
cap_info_bitmap, beacon_period, cap_info_bitmap, beacon_period,
ie_buf, ie_len, rssi, GFP_KERNEL); ie_buf, ie_len, rssi, GFP_KERNEL);
bss_priv = (struct mwifiex_bss_priv *)bss->priv; bss_priv = (struct mwifiex_bss_priv *)bss->priv;
......
...@@ -123,9 +123,10 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv, ...@@ -123,9 +123,10 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv,
beacon_interval = le16_to_cpu(bss->a.beacon_interv); beacon_interval = le16_to_cpu(bss->a.beacon_interv);
signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level)); signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level));
cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
capability, beacon_interval, ie_buf, ie_len, bss->a.bssid, timestamp, capability,
signal, GFP_KERNEL); beacon_interval, ie_buf, ie_len, signal,
GFP_KERNEL);
cfg80211_put_bss(wiphy, cbss); cfg80211_put_bss(wiphy, cbss);
} }
...@@ -156,9 +157,10 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, ...@@ -156,9 +157,10 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
ie = bss->data; ie = bss->data;
signal = SIGNAL_TO_MBM(bss->level); signal = SIGNAL_TO_MBM(bss->level);
cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
capability, beacon_interval, ie, ie_len, bss->bssid, timestamp, capability,
signal, GFP_KERNEL); beacon_interval, ie, ie_len, signal,
GFP_KERNEL);
cfg80211_put_bss(wiphy, cbss); cfg80211_put_bss(wiphy, cbss);
} }
......
...@@ -2022,9 +2022,10 @@ static bool rndis_bss_info_update(struct usbnet *usbdev, ...@@ -2022,9 +2022,10 @@ static bool rndis_bss_info_update(struct usbnet *usbdev,
capability = le16_to_cpu(fixed->capabilities); capability = le16_to_cpu(fixed->capabilities);
beacon_interval = le16_to_cpu(fixed->beacon_interval); beacon_interval = le16_to_cpu(fixed->beacon_interval);
bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, bss = cfg80211_inform_bss(priv->wdev.wiphy, channel,
timestamp, capability, beacon_interval, ie, ie_len, signal, CFG80211_BSS_FTYPE_UNKNOWN, bssid->mac,
GFP_KERNEL); timestamp, capability, beacon_interval,
ie, ie_len, signal, GFP_KERNEL);
cfg80211_put_bss(priv->wdev.wiphy, bss); cfg80211_put_bss(priv->wdev.wiphy, bss);
return (bss != NULL); return (bss != NULL);
...@@ -2711,9 +2712,10 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, ...@@ -2711,9 +2712,10 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
bssid, (u32)timestamp, capability, beacon_period, ie_len, bssid, (u32)timestamp, capability, beacon_period, ie_len,
ssid.essid, signal); ssid.essid, signal);
bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, bss = cfg80211_inform_bss(priv->wdev.wiphy, channel,
timestamp, capability, beacon_period, ie_buf, ie_len, CFG80211_BSS_FTYPE_UNKNOWN, bssid,
signal, GFP_KERNEL); timestamp, capability, beacon_period,
ie_buf, ie_len, signal, GFP_KERNEL);
cfg80211_put_bss(priv->wdev.wiphy, bss); cfg80211_put_bss(priv->wdev.wiphy, bss);
} }
......
...@@ -279,6 +279,7 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, ...@@ -279,6 +279,7 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
} }
bss = cfg80211_inform_bss(wiphy, notify_channel, bss = cfg80211_inform_bss(wiphy, notify_channel,
CFG80211_BSS_FTYPE_UNKNOWN,
pnetwork->network.MacAddress, pnetwork->network.MacAddress,
pnetwork->network.tsf, pnetwork->network.tsf,
pnetwork->network.capability, pnetwork->network.capability,
......
...@@ -422,6 +422,7 @@ static int prism2_scan(struct wiphy *wiphy, ...@@ -422,6 +422,7 @@ static int prism2_scan(struct wiphy *wiphy,
IEEE80211_BAND_2GHZ); IEEE80211_BAND_2GHZ);
bss = cfg80211_inform_bss(wiphy, bss = cfg80211_inform_bss(wiphy,
ieee80211_get_channel(wiphy, freq), ieee80211_get_channel(wiphy, freq),
CFG80211_BSS_FTYPE_UNKNOWN,
(const u8 *) &(msg2.bssid.data.data), (const u8 *) &(msg2.bssid.data.data),
msg2.timestamp.data, msg2.capinfo.data, msg2.timestamp.data, msg2.capinfo.data,
msg2.beaconperiod.data, msg2.beaconperiod.data,
......
...@@ -3767,11 +3767,25 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, ...@@ -3767,11 +3767,25 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
} }
/** /**
* cfg80211_inform_bss - inform cfg80211 of a new BSS * enum cfg80211_bss_frame_type - frame type that the BSS data came from
* @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
* from a beacon or probe response
* @CFG80211_BSS_FTYPE_BEACON: data comes from a beacon
* @CFG80211_BSS_FTYPE_PRESP: data comes from a probe response
*/
enum cfg80211_bss_frame_type {
CFG80211_BSS_FTYPE_UNKNOWN,
CFG80211_BSS_FTYPE_BEACON,
CFG80211_BSS_FTYPE_PRESP,
};
/**
* cfg80211_inform_bss_width - inform cfg80211 of a new BSS
* *
* @wiphy: the wiphy reporting the BSS * @wiphy: the wiphy reporting the BSS
* @rx_channel: The channel the frame was received on * @rx_channel: The channel the frame was received on
* @scan_width: width of the control channel * @scan_width: width of the control channel
* @ftype: frame type (if known)
* @bssid: the BSSID of the BSS * @bssid: the BSSID of the BSS
* @tsf: the TSF sent by the peer in the beacon/probe response (or 0) * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
* @capability: the capability field sent by the peer * @capability: the capability field sent by the peer
...@@ -3791,6 +3805,7 @@ struct cfg80211_bss * __must_check ...@@ -3791,6 +3805,7 @@ struct cfg80211_bss * __must_check
cfg80211_inform_bss_width(struct wiphy *wiphy, cfg80211_inform_bss_width(struct wiphy *wiphy,
struct ieee80211_channel *rx_channel, struct ieee80211_channel *rx_channel,
enum nl80211_bss_scan_width scan_width, enum nl80211_bss_scan_width scan_width,
enum cfg80211_bss_frame_type ftype,
const u8 *bssid, u64 tsf, u16 capability, const u8 *bssid, u64 tsf, u16 capability,
u16 beacon_interval, const u8 *ie, size_t ielen, u16 beacon_interval, const u8 *ie, size_t ielen,
s32 signal, gfp_t gfp); s32 signal, gfp_t gfp);
...@@ -3798,12 +3813,13 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, ...@@ -3798,12 +3813,13 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
static inline struct cfg80211_bss * __must_check static inline struct cfg80211_bss * __must_check
cfg80211_inform_bss(struct wiphy *wiphy, cfg80211_inform_bss(struct wiphy *wiphy,
struct ieee80211_channel *rx_channel, struct ieee80211_channel *rx_channel,
enum cfg80211_bss_frame_type ftype,
const u8 *bssid, u64 tsf, u16 capability, const u8 *bssid, u64 tsf, u16 capability,
u16 beacon_interval, const u8 *ie, size_t ielen, u16 beacon_interval, const u8 *ie, size_t ielen,
s32 signal, gfp_t gfp) s32 signal, gfp_t gfp)
{ {
return cfg80211_inform_bss_width(wiphy, rx_channel, return cfg80211_inform_bss_width(wiphy, rx_channel,
NL80211_BSS_CHAN_WIDTH_20, NL80211_BSS_CHAN_WIDTH_20, ftype,
bssid, tsf, capability, bssid, tsf, capability,
beacon_interval, ie, ielen, signal, beacon_interval, ie, ielen, signal,
gfp); gfp);
......
...@@ -884,6 +884,7 @@ struct cfg80211_bss* ...@@ -884,6 +884,7 @@ struct cfg80211_bss*
cfg80211_inform_bss_width(struct wiphy *wiphy, cfg80211_inform_bss_width(struct wiphy *wiphy,
struct ieee80211_channel *rx_channel, struct ieee80211_channel *rx_channel,
enum nl80211_bss_scan_width scan_width, enum nl80211_bss_scan_width scan_width,
enum cfg80211_bss_frame_type ftype,
const u8 *bssid, u64 tsf, u16 capability, const u8 *bssid, u64 tsf, u16 capability,
u16 beacon_interval, const u8 *ie, size_t ielen, u16 beacon_interval, const u8 *ie, size_t ielen,
s32 signal, gfp_t gfp) s32 signal, gfp_t gfp)
...@@ -911,7 +912,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, ...@@ -911,7 +912,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
tmp.pub.beacon_interval = beacon_interval; tmp.pub.beacon_interval = beacon_interval;
tmp.pub.capability = capability; tmp.pub.capability = capability;
/* /*
* Since we do not know here whether the IEs are from a Beacon or Probe * If we do not know here whether the IEs are from a Beacon or Probe
* Response frame, we need to pick one of the options and only use it * Response frame, we need to pick one of the options and only use it
* with the driver that does not provide the full Beacon/Probe Response * with the driver that does not provide the full Beacon/Probe Response
* frame. Use Beacon frame pointer to avoid indicating that this should * frame. Use Beacon frame pointer to avoid indicating that this should
...@@ -926,7 +927,17 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, ...@@ -926,7 +927,17 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
ies->from_beacon = false; ies->from_beacon = false;
memcpy(ies->data, ie, ielen); memcpy(ies->data, ie, ielen);
switch (ftype) {
case CFG80211_BSS_FTYPE_BEACON:
ies->from_beacon = true;
/* fall through to assign */
case CFG80211_BSS_FTYPE_UNKNOWN:
rcu_assign_pointer(tmp.pub.beacon_ies, ies); rcu_assign_pointer(tmp.pub.beacon_ies, ies);
break;
case CFG80211_BSS_FTYPE_PRESP:
rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
break;
}
rcu_assign_pointer(tmp.pub.ies, ies); rcu_assign_pointer(tmp.pub.ies, ies);
signal_valid = abs(rx_channel->center_freq - channel->center_freq) <= signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
......
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