Commit 3743bec6 authored by Jia Ding's avatar Jia Ding Committed by Johannes Berg
parent 5cd5a8a3
...@@ -836,6 +836,8 @@ static int hwsim_get_chanwidth(enum nl80211_chan_width bw) ...@@ -836,6 +836,8 @@ static int hwsim_get_chanwidth(enum nl80211_chan_width bw)
case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
return 160; return 160;
case NL80211_CHAN_WIDTH_320:
return 320;
case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_5:
return 5; return 5;
case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_10:
......
...@@ -109,7 +109,11 @@ struct wiphy; ...@@ -109,7 +109,11 @@ struct wiphy;
* on this channel. * on this channel.
* @IEEE80211_CHAN_16MHZ: 16 MHz bandwidth is permitted * @IEEE80211_CHAN_16MHZ: 16 MHz bandwidth is permitted
* on this channel. * on this channel.
* * @IEEE80211_CHAN_NO_320MHZ: If the driver supports 320 MHz on the band,
* this flag indicates that a 320 MHz channel cannot use this
* channel as the control or any of the secondary channels.
* This may be due to the driver or due to regulatory bandwidth
* restrictions.
*/ */
enum ieee80211_channel_flags { enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = 1<<0, IEEE80211_CHAN_DISABLED = 1<<0,
...@@ -131,6 +135,7 @@ enum ieee80211_channel_flags { ...@@ -131,6 +135,7 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_4MHZ = 1<<16, IEEE80211_CHAN_4MHZ = 1<<16,
IEEE80211_CHAN_8MHZ = 1<<17, IEEE80211_CHAN_8MHZ = 1<<17,
IEEE80211_CHAN_16MHZ = 1<<18, IEEE80211_CHAN_16MHZ = 1<<18,
IEEE80211_CHAN_NO_320MHZ = 1<<19,
}; };
#define IEEE80211_CHAN_NO_HT40 \ #define IEEE80211_CHAN_NO_HT40 \
......
...@@ -4684,6 +4684,8 @@ enum nl80211_key_mode { ...@@ -4684,6 +4684,8 @@ enum nl80211_key_mode {
* @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel
* @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel
* @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel
* @NL80211_CHAN_WIDTH_320: 320 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
*/ */
enum nl80211_chan_width { enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_20_NOHT,
...@@ -4699,6 +4701,7 @@ enum nl80211_chan_width { ...@@ -4699,6 +4701,7 @@ enum nl80211_chan_width {
NL80211_CHAN_WIDTH_4, NL80211_CHAN_WIDTH_4,
NL80211_CHAN_WIDTH_8, NL80211_CHAN_WIDTH_8,
NL80211_CHAN_WIDTH_16, NL80211_CHAN_WIDTH_16,
NL80211_CHAN_WIDTH_320,
}; };
/** /**
......
...@@ -181,6 +181,9 @@ static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width) ...@@ -181,6 +181,9 @@ static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
mhz = 160; mhz = 160;
break; break;
case NL80211_CHAN_WIDTH_320:
mhz = 320;
break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return -1; return -1;
...@@ -271,6 +274,17 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) ...@@ -271,6 +274,17 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
case NL80211_CHAN_WIDTH_16: case NL80211_CHAN_WIDTH_16:
/* all checked above */ /* all checked above */
break; break;
case NL80211_CHAN_WIDTH_320:
if (chandef->center_freq1 == control_freq + 150 ||
chandef->center_freq1 == control_freq + 130 ||
chandef->center_freq1 == control_freq + 110 ||
chandef->center_freq1 == control_freq + 90 ||
chandef->center_freq1 == control_freq - 90 ||
chandef->center_freq1 == control_freq - 110 ||
chandef->center_freq1 == control_freq - 130 ||
chandef->center_freq1 == control_freq - 150)
break;
fallthrough;
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
if (chandef->center_freq1 == control_freq + 70 || if (chandef->center_freq1 == control_freq + 70 ||
chandef->center_freq1 == control_freq + 50 || chandef->center_freq1 == control_freq + 50 ||
...@@ -307,7 +321,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) ...@@ -307,7 +321,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
EXPORT_SYMBOL(cfg80211_chandef_valid); EXPORT_SYMBOL(cfg80211_chandef_valid);
static void chandef_primary_freqs(const struct cfg80211_chan_def *c, static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
u32 *pri40, u32 *pri80) u32 *pri40, u32 *pri80, u32 *pri160)
{ {
int tmp; int tmp;
...@@ -315,9 +329,11 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, ...@@ -315,9 +329,11 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
case NL80211_CHAN_WIDTH_40: case NL80211_CHAN_WIDTH_40:
*pri40 = c->center_freq1; *pri40 = c->center_freq1;
*pri80 = 0; *pri80 = 0;
*pri160 = 0;
break; break;
case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80P80:
*pri160 = 0;
*pri80 = c->center_freq1; *pri80 = c->center_freq1;
/* n_P20 */ /* n_P20 */
tmp = (30 + c->chan->center_freq - c->center_freq1)/20; tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
...@@ -327,6 +343,7 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, ...@@ -327,6 +343,7 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
*pri40 = c->center_freq1 - 20 + 40 * tmp; *pri40 = c->center_freq1 - 20 + 40 * tmp;
break; break;
case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_160:
*pri160 = c->center_freq1;
/* n_P20 */ /* n_P20 */
tmp = (70 + c->chan->center_freq - c->center_freq1)/20; tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
/* n_P40 */ /* n_P40 */
...@@ -337,6 +354,20 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, ...@@ -337,6 +354,20 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
tmp /= 2; tmp /= 2;
*pri80 = c->center_freq1 - 40 + 80 * tmp; *pri80 = c->center_freq1 - 40 + 80 * tmp;
break; break;
case NL80211_CHAN_WIDTH_320:
/* n_P20 */
tmp = (150 + c->chan->center_freq - c->center_freq1) / 20;
/* n_P40 */
tmp /= 2;
/* freq_P40 */
*pri40 = c->center_freq1 - 140 + 40 * tmp;
/* n_P80 */
tmp /= 2;
*pri80 = c->center_freq1 - 120 + 80 * tmp;
/* n_P160 */
tmp /= 2;
*pri160 = c->center_freq1 - 80 + 160 * tmp;
break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
...@@ -346,7 +377,7 @@ const struct cfg80211_chan_def * ...@@ -346,7 +377,7 @@ const struct cfg80211_chan_def *
cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
const struct cfg80211_chan_def *c2) const struct cfg80211_chan_def *c2)
{ {
u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80, c1_pri160, c2_pri160;
/* If they are identical, return */ /* If they are identical, return */
if (cfg80211_chandef_identical(c1, c2)) if (cfg80211_chandef_identical(c1, c2))
...@@ -381,14 +412,31 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, ...@@ -381,14 +412,31 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
c2->width == NL80211_CHAN_WIDTH_20) c2->width == NL80211_CHAN_WIDTH_20)
return c1; return c1;
chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); chandef_primary_freqs(c1, &c1_pri40, &c1_pri80, &c1_pri160);
chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); chandef_primary_freqs(c2, &c2_pri40, &c2_pri80, &c2_pri160);
if (c1_pri40 != c2_pri40) if (c1_pri40 != c2_pri40)
return NULL; return NULL;
WARN_ON(!c1_pri80 && !c2_pri80); if (c1->width == NL80211_CHAN_WIDTH_40)
if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) return c2;
if (c2->width == NL80211_CHAN_WIDTH_40)
return c1;
if (c1_pri80 != c2_pri80)
return NULL;
if (c1->width == NL80211_CHAN_WIDTH_80 &&
c2->width > NL80211_CHAN_WIDTH_80)
return c2;
if (c2->width == NL80211_CHAN_WIDTH_80 &&
c1->width > NL80211_CHAN_WIDTH_80)
return c1;
WARN_ON(!c1_pri160 && !c2_pri160);
if (c1_pri160 && c2_pri160 && c1_pri160 != c2_pri160)
return NULL; return NULL;
if (c1->width > c2->width) if (c1->width > c2->width)
...@@ -960,7 +1008,10 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, ...@@ -960,7 +1008,10 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
struct ieee80211_sta_vht_cap *vht_cap; struct ieee80211_sta_vht_cap *vht_cap;
struct ieee80211_edmg *edmg_cap; struct ieee80211_edmg *edmg_cap;
u32 width, control_freq, cap; u32 width, control_freq, cap;
bool ext_nss_cap, support_80_80 = false; bool ext_nss_cap, support_80_80 = false, support_320 = false;
const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_supported_band *sband;
int i;
if (WARN_ON(!cfg80211_chandef_valid(chandef))) if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return false; return false;
...@@ -1062,6 +1113,32 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, ...@@ -1062,6 +1113,32 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
(vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))) (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)))
return false; return false;
break; break;
case NL80211_CHAN_WIDTH_320:
prohibited_flags |= IEEE80211_CHAN_NO_320MHZ;
width = 320;
if (chandef->chan->band != NL80211_BAND_6GHZ)
return false;
sband = wiphy->bands[NL80211_BAND_6GHZ];
if (!sband)
return false;
for (i = 0; i < sband->n_iftype_data; i++) {
iftd = &sband->iftype_data[i];
if (!iftd->eht_cap.has_eht)
continue;
if (iftd->eht_cap.eht_cap_elem.phy_cap_info[0] &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) {
support_320 = true;
break;
}
}
if (!support_320)
return false;
break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return false; return false;
......
...@@ -10589,6 +10589,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) ...@@ -10589,6 +10589,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
NL80211_EXT_FEATURE_VHT_IBSS)) NL80211_EXT_FEATURE_VHT_IBSS))
return -EINVAL; return -EINVAL;
break; break;
case NL80211_CHAN_WIDTH_320:
return -EINVAL;
default: default:
return -EINVAL; return -EINVAL;
} }
......
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