1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Wed, 5 Jun 2024 18:39:55 +0200
3 Subject: [PATCH] wifi: mac80211: add wiphy radio assignment and
6 Validate number of channels and interface combinations per radio.
7 Assign each channel context to a radio.
9 Signed-off-by: Felix Fietkau <nbd@nbd.name>
12 --- a/net/mac80211/chan.c
13 +++ b/net/mac80211/chan.c
14 @@ -680,14 +680,15 @@ static int ieee80211_add_chanctx(struct
15 static struct ieee80211_chanctx *
16 ieee80211_new_chanctx(struct ieee80211_local *local,
17 const struct ieee80211_chan_req *chanreq,
18 - enum ieee80211_chanctx_mode mode)
19 + enum ieee80211_chanctx_mode mode,
22 struct ieee80211_chanctx *ctx;
25 lockdep_assert_wiphy(local->hw.wiphy);
27 - ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
28 + ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
30 return ERR_PTR(-ENOMEM);
32 @@ -1040,6 +1041,8 @@ ieee80211_replace_chanctx(struct ieee802
33 struct ieee80211_chanctx *curr_ctx)
35 struct ieee80211_chanctx *new_ctx, *ctx;
36 + struct wiphy *wiphy = local->hw.wiphy;
37 + const struct wiphy_radio *radio;
39 if (!curr_ctx || (curr_ctx->replace_state ==
40 IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
41 @@ -1069,6 +1072,12 @@ ieee80211_replace_chanctx(struct ieee802
42 if (!list_empty(&ctx->reserved_links))
45 + if (ctx->conf.radio_idx >= 0) {
46 + radio = &wiphy->radio[ctx->conf.radio_idx];
47 + if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
54 @@ -1098,6 +1107,34 @@ ieee80211_replace_chanctx(struct ieee802
59 +ieee80211_find_available_radio(struct ieee80211_local *local,
60 + const struct ieee80211_chan_req *chanreq,
63 + struct wiphy *wiphy = local->hw.wiphy;
64 + const struct wiphy_radio *radio;
68 + if (!wiphy->n_radio)
71 + for (i = 0; i < wiphy->n_radio; i++) {
72 + radio = &wiphy->radio[i];
73 + if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
76 + if (!ieee80211_can_create_new_chanctx(local, i))
86 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
87 const struct ieee80211_chan_req *chanreq,
88 enum ieee80211_chanctx_mode mode,
89 @@ -1106,6 +1143,7 @@ int ieee80211_link_reserve_chanctx(struc
90 struct ieee80211_sub_if_data *sdata = link->sdata;
91 struct ieee80211_local *local = sdata->local;
92 struct ieee80211_chanctx *new_ctx, *curr_ctx;
95 lockdep_assert_wiphy(local->hw.wiphy);
97 @@ -1115,8 +1153,10 @@ int ieee80211_link_reserve_chanctx(struc
99 new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
101 - if (ieee80211_can_create_new_chanctx(local, -1))
102 - new_ctx = ieee80211_new_chanctx(local, chanreq, mode);
103 + if (ieee80211_can_create_new_chanctx(local, -1) &&
104 + ieee80211_find_available_radio(local, chanreq, &radio_idx))
105 + new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
108 new_ctx = ieee80211_replace_chanctx(local, chanreq,
110 @@ -1724,6 +1764,7 @@ int ieee80211_link_use_channel(struct ie
111 struct ieee80211_local *local = sdata->local;
112 struct ieee80211_chanctx *ctx;
113 u8 radar_detect_width = 0;
117 lockdep_assert_wiphy(local->hw.wiphy);
118 @@ -1751,8 +1792,12 @@ int ieee80211_link_use_channel(struct ie
119 __ieee80211_link_release_channel(link);
121 ctx = ieee80211_find_chanctx(local, chanreq, mode);
123 - ctx = ieee80211_new_chanctx(local, chanreq, mode);
125 + if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
126 + ctx = ERR_PTR(-EBUSY);
128 + ctx = ieee80211_new_chanctx(local, chanreq, mode, radio_idx);