Skip to content

Commit

Permalink
wifi: cfg80211: annotate iftype_data pointer with sparse
Browse files Browse the repository at this point in the history
There were are a number of cases in mac80211 and iwlwifi (at
least) that used the sband->iftype_data pointer directly,
instead of using the accessors to find the right array entry
to use.

Make sparse warn when such a thing is done.

To not have a lot of casts, add two helper functions/macros

 - ieee80211_set_sband_iftype_data()
 - for_each_sband_iftype_data()

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
jmberg-intel committed Sep 11, 2023
1 parent 05f1362 commit e8c1841
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 79 deletions.
15 changes: 9 additions & 6 deletions drivers/net/wireless/ath/ath11k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -5893,17 +5893,19 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar,
ar->mac.iftype[NL80211_BAND_2GHZ],
NL80211_BAND_2GHZ);
band = &ar->mac.sbands[NL80211_BAND_2GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
band->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(band,
ar->mac.iftype[NL80211_BAND_2GHZ],
count);
}

if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
count = ath11k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_5GHZ],
NL80211_BAND_5GHZ);
band = &ar->mac.sbands[NL80211_BAND_5GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
band->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(band,
ar->mac.iftype[NL80211_BAND_5GHZ],
count);
}

if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
Expand All @@ -5912,8 +5914,9 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar,
ar->mac.iftype[NL80211_BAND_6GHZ],
NL80211_BAND_6GHZ);
band = &ar->mac.sbands[NL80211_BAND_6GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
band->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(band,
ar->mac.iftype[NL80211_BAND_6GHZ],
count);
}
}

Expand Down
12 changes: 6 additions & 6 deletions drivers/net/wireless/ath/ath12k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -4647,8 +4647,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
count);
}

if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
Expand All @@ -4657,8 +4657,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
count);
}

if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
Expand All @@ -4668,8 +4668,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
_ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
count);
}
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1077,8 +1077,8 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,

memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));

sband->iftype_data = iftype_data;
sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa);
_ieee80211_set_sband_iftype_data(sband, iftype_data,
ARRAY_SIZE(iwl_he_eht_capa));

for (i = 0; i < sband->n_iftype_data; i++)
iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
Expand Down
9 changes: 3 additions & 6 deletions drivers/net/wireless/mediatek/mt76/mt7915/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,26 +1127,23 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);

band = &phy->mt76->sband_2g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);
}

if (phy->mt76->cap.has_5ghz) {
data = phy->iftype[NL80211_BAND_5GHZ];
n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);

band = &phy->mt76->sband_5g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);
}

if (phy->mt76->cap.has_6ghz) {
data = phy->iftype[NL80211_BAND_6GHZ];
n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);

band = &phy->mt76->sband_6g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);
}
}

Expand Down
9 changes: 3 additions & 6 deletions drivers/net/wireless/mediatek/mt76/mt7921/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,22 @@ void mt7921_set_stream_he_caps(struct mt792x_phy *phy)
n = mt7921_init_he_caps(phy, NL80211_BAND_2GHZ, data);

band = &phy->mt76->sband_2g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);
}

if (phy->mt76->cap.has_5ghz) {
data = phy->iftype[NL80211_BAND_5GHZ];
n = mt7921_init_he_caps(phy, NL80211_BAND_5GHZ, data);

band = &phy->mt76->sband_5g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);

if (phy->mt76->cap.has_6ghz) {
data = phy->iftype[NL80211_BAND_6GHZ];
n = mt7921_init_he_caps(phy, NL80211_BAND_6GHZ, data);

band = &phy->mt76->sband_6g.sband;
band->iftype_data = data;
band->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(band, data, n);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/mediatek/mt76/mt7996/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
n++;
}

sband->iftype_data = data;
sband->n_iftype_data = n;
_ieee80211_set_sband_iftype_data(sband, data, n);
}

void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy)
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/wireless/quantenna/qtnfmac/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1335,7 +1335,7 @@ static int qtnf_cmd_band_fill_iftype(const u8 *data,
return -EINVAL;
}

kfree(band->iftype_data);
kfree((__force void *)band->iftype_data);
band->iftype_data = NULL;
band->n_iftype_data = tlv->n_iftype_data;
if (band->n_iftype_data == 0)
Expand All @@ -1347,7 +1347,8 @@ static int qtnf_cmd_band_fill_iftype(const u8 *data,
band->n_iftype_data = 0;
return -ENOMEM;
}
band->iftype_data = iftype_data;

_ieee80211_set_sband_iftype_data(band, iftype_data, tlv->n_iftype_data);

for (i = 0; i < band->n_iftype_data; i++)
qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/quantenna/qtnfmac/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
if (!wiphy->bands[band])
continue;

kfree(wiphy->bands[band]->iftype_data);
kfree((__force void *)wiphy->bands[band]->iftype_data);
wiphy->bands[band]->n_iftype_data = 0;

kfree(wiphy->bands[band]->channels);
Expand Down
15 changes: 7 additions & 8 deletions drivers/net/wireless/realtek/rtw89/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3359,8 +3359,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
idx++;
}

sband->iftype_data = iftype_data;
sband->n_iftype_data = idx;
_ieee80211_set_sband_iftype_data(sband, iftype_data, idx);
}

static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev)
Expand Down Expand Up @@ -3405,11 +3404,11 @@ static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev)
hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL;
if (sband_2ghz)
kfree(sband_2ghz->iftype_data);
kfree((__force void *)sband_2ghz->iftype_data);
if (sband_5ghz)
kfree(sband_5ghz->iftype_data);
kfree((__force void *)sband_5ghz->iftype_data);
if (sband_6ghz)
kfree(sband_6ghz->iftype_data);
kfree((__force void *)sband_6ghz->iftype_data);
kfree(sband_2ghz);
kfree(sband_5ghz);
kfree(sband_6ghz);
Expand All @@ -3421,11 +3420,11 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev)
struct ieee80211_hw *hw = rtwdev->hw;

if (hw->wiphy->bands[NL80211_BAND_2GHZ])
kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
if (hw->wiphy->bands[NL80211_BAND_5GHZ])
kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
if (hw->wiphy->bands[NL80211_BAND_6GHZ])
kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/realtek/rtw89/regd.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
return;

wiphy->bands[NL80211_BAND_6GHZ] = NULL;
kfree(sband->iftype_data);
kfree((__force void *)sband->iftype_data);
kfree(sband);
}

Expand Down
30 changes: 12 additions & 18 deletions drivers/net/wireless/virtual/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -4899,25 +4899,19 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {

static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband)
{
u16 n_iftype_data;

if (sband->band == NL80211_BAND_2GHZ) {
n_iftype_data = ARRAY_SIZE(sband_capa_2ghz);
sband->iftype_data =
(struct ieee80211_sband_iftype_data *)sband_capa_2ghz;
} else if (sband->band == NL80211_BAND_5GHZ) {
n_iftype_data = ARRAY_SIZE(sband_capa_5ghz);
sband->iftype_data =
(struct ieee80211_sband_iftype_data *)sband_capa_5ghz;
} else if (sband->band == NL80211_BAND_6GHZ) {
n_iftype_data = ARRAY_SIZE(sband_capa_6ghz);
sband->iftype_data =
(struct ieee80211_sband_iftype_data *)sband_capa_6ghz;
} else {
return;
switch (sband->band) {
case NL80211_BAND_2GHZ:
ieee80211_set_sband_iftype_data(sband, sband_capa_2ghz);
break;
case NL80211_BAND_5GHZ:
ieee80211_set_sband_iftype_data(sband, sband_capa_5ghz);
break;
case NL80211_BAND_6GHZ:
ieee80211_set_sband_iftype_data(sband, sband_capa_6ghz);
break;
default:
break;
}

sband->n_iftype_data = n_iftype_data;
}

#ifdef CONFIG_MAC80211_MESH
Expand Down
59 changes: 54 additions & 5 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,19 @@ struct ieee80211_sta_eht_cap {
u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN];
};

/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
#ifdef __CHECKER__
/*
* This is used to mark the sband->iftype_data pointer which is supposed
* to be an array with special access semantics (per iftype), but a lot
* of code got it wrong in the past, so with this marking sparse will be
* noisy when the pointer is used directly.
*/
# define __iftd __attribute__((noderef, address_space(__iftype_data)))
#else
# define __iftd
#endif /* __CHECKER__ */

/**
* struct ieee80211_sband_iftype_data - sband data per interface type
*
Expand Down Expand Up @@ -543,9 +556,47 @@ struct ieee80211_supported_band {
struct ieee80211_sta_s1g_cap s1g_cap;
struct ieee80211_edmg edmg_cap;
u16 n_iftype_data;
const struct ieee80211_sband_iftype_data *iftype_data;
const struct ieee80211_sband_iftype_data __iftd *iftype_data;
};

/**
* _ieee80211_set_sband_iftype_data - set sband iftype data array
* @sband: the sband to initialize
* @iftd: the iftype data array pointer
* @n_iftd: the length of the iftype data array
*
* Set the sband iftype data array; use this where the length cannot
* be derived from the ARRAY_SIZE() of the argument, but prefer
* ieee80211_set_sband_iftype_data() where it can be used.
*/
static inline void
_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *sband,
const struct ieee80211_sband_iftype_data *iftd,
u16 n_iftd)
{
sband->iftype_data = (const void __iftd __force *)iftd;
sband->n_iftype_data = n_iftd;
}

/**
* ieee80211_set_sband_iftype_data - set sband iftype data array
* @sband: the sband to initialize
* @iftd: the iftype data array
*/
#define ieee80211_set_sband_iftype_data(sband, iftd) \
_ieee80211_set_sband_iftype_data(sband, iftd, ARRAY_SIZE(iftd))

/**
* for_each_sband_iftype_data - iterate sband iftype data entries
* @sband: the sband whose iftype_data array to iterate
* @i: iterator counter
* @iftd: iftype data pointer to set
*/
#define for_each_sband_iftype_data(sband, i, iftd) \
for (i = 0, iftd = (const void __force *)&(sband)->iftype_data[i]; \
i < (sband)->n_iftype_data; \
i++, iftd = (const void __force *)&(sband)->iftype_data[i])

/**
* ieee80211_get_sband_iftype_data - return sband data for a given iftype
* @sband: the sband to search for the STA on
Expand All @@ -557,6 +608,7 @@ static inline const struct ieee80211_sband_iftype_data *
ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
u8 iftype)
{
const struct ieee80211_sband_iftype_data *data;
int i;

if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
Expand All @@ -565,10 +617,7 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
if (iftype == NL80211_IFTYPE_AP_VLAN)
iftype = NL80211_IFTYPE_AP;

for (i = 0; i < sband->n_iftype_data; i++) {
const struct ieee80211_sband_iftype_data *data =
&sband->iftype_data[i];

for_each_sband_iftype_data(sband, i, data) {
if (data->types_mask & BIT(iftype))
return data;
}
Expand Down
7 changes: 2 additions & 5 deletions net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
supp_he = false;
supp_eht = false;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_supported_band *sband;

sband = local->hw.wiphy->bands[band];
Expand Down Expand Up @@ -1112,11 +1113,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
supp_ht = supp_ht || sband->ht_cap.ht_supported;
supp_vht = supp_vht || sband->vht_cap.vht_supported;

for (i = 0; i < sband->n_iftype_data; i++) {
const struct ieee80211_sband_iftype_data *iftd;

iftd = &sband->iftype_data[i];

for_each_sband_iftype_data(sband, i, iftd) {
supp_he = supp_he || iftd->he_cap.has_he;
supp_eht = supp_eht || iftd->eht_cap.has_eht;
}
Expand Down
5 changes: 2 additions & 3 deletions net/wireless/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2018-2022 Intel Corporation
* Copyright 2018-2023 Intel Corporation
*/

#include <linux/export.h>
Expand Down Expand Up @@ -1162,8 +1162,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
if (!sband)
return false;

for (i = 0; i < sband->n_iftype_data; i++) {
iftd = &sband->iftype_data[i];
for_each_sband_iftype_data(sband, i, iftd) {
if (!iftd->eht_cap.has_eht)
continue;

Expand Down

0 comments on commit e8c1841

Please sign in to comment.