Commit bb8152b3 authored by Zong-Zhe Yang's avatar Zong-Zhe Yang Committed by Kalle Valo

wifi: rtw89: create rtw89_chan centrally to avoid breakage

Sometimes we need to write current rtw89_chan outside set_channel(),
e.g. during HW scan, we adjust it to align FW process through C2H.
However, we don't have full parameters to fill entire rtw89_chan.
And it will breakage if we update only part of current rtw89_chan.
That is what we don't want to see because most flows throughout
driver treat rtw89_chan as a whole.

So, we divide struct rtw89_chan to basic part and derived part. The
basic part contains the parameters which we are always able to know.
And the derived part will be calculated by the basic part. Then, a
central function, rtw89_chan_create(), is added to deal with this.
Signed-off-by: default avatarZong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220809104952.61355-5-pkshih@realtek.com
parent cbb145b9
...@@ -4,6 +4,104 @@ ...@@ -4,6 +4,104 @@
#include "chan.h" #include "chan.h"
static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
u8 center_chan)
{
switch (band) {
default:
case RTW89_BAND_2G:
switch (center_chan) {
default:
case 1 ... 14:
return RTW89_CH_2G;
}
case RTW89_BAND_5G:
switch (center_chan) {
default:
case 36 ... 64:
return RTW89_CH_5G_BAND_1;
case 100 ... 144:
return RTW89_CH_5G_BAND_3;
case 149 ... 177:
return RTW89_CH_5G_BAND_4;
}
case RTW89_BAND_6G:
switch (center_chan) {
default:
case 1 ... 29:
return RTW89_CH_6G_BAND_IDX0;
case 33 ... 61:
return RTW89_CH_6G_BAND_IDX1;
case 65 ... 93:
return RTW89_CH_6G_BAND_IDX2;
case 97 ... 125:
return RTW89_CH_6G_BAND_IDX3;
case 129 ... 157:
return RTW89_CH_6G_BAND_IDX4;
case 161 ... 189:
return RTW89_CH_6G_BAND_IDX5;
case 193 ... 221:
return RTW89_CH_6G_BAND_IDX6;
case 225 ... 253:
return RTW89_CH_6G_BAND_IDX7;
}
}
}
static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
u32 center_freq,
u32 primary_freq)
{
u8 primary_chan_idx;
u32 offset;
switch (bw) {
default:
case RTW89_CHANNEL_WIDTH_20:
primary_chan_idx = RTW89_SC_DONT_CARE;
break;
case RTW89_CHANNEL_WIDTH_40:
if (primary_freq > center_freq)
primary_chan_idx = RTW89_SC_20_UPPER;
else
primary_chan_idx = RTW89_SC_20_LOWER;
break;
case RTW89_CHANNEL_WIDTH_80:
case RTW89_CHANNEL_WIDTH_160:
if (primary_freq > center_freq) {
offset = (primary_freq - center_freq - 10) / 20;
primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
} else {
offset = (center_freq - primary_freq - 10) / 20;
primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
}
break;
}
return primary_chan_idx;
}
void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
enum rtw89_band band, enum rtw89_bandwidth bandwidth)
{
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
u32 center_freq, primary_freq;
memset(chan, 0, sizeof(*chan));
chan->channel = center_chan;
chan->primary_channel = primary_chan;
chan->band_type = band;
chan->band_width = bandwidth;
center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
chan->freq = center_freq;
chan->subband_type = rtw89_get_subband_type(band, center_chan);
chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
primary_freq);
}
bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx, enum rtw89_sub_entity_idx idx,
const struct rtw89_chan *new) const struct rtw89_chan *new)
......
...@@ -21,6 +21,8 @@ static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active) ...@@ -21,6 +21,8 @@ static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active)
WRITE_ONCE(hal->entity_active, active); WRITE_ONCE(hal->entity_active, active);
} }
void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
enum rtw89_band band, enum rtw89_bandwidth bandwidth);
bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx, enum rtw89_sub_entity_idx idx,
const struct rtw89_chan *new); const struct rtw89_chan *new);
......
...@@ -233,10 +233,8 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef, ...@@ -233,10 +233,8 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
u32 primary_freq, center_freq; u32 primary_freq, center_freq;
u8 center_chan; u8 center_chan;
u8 bandwidth = RTW89_CHANNEL_WIDTH_20; u8 bandwidth = RTW89_CHANNEL_WIDTH_20;
u8 primary_chan_idx = 0;
u32 offset; u32 offset;
u8 band; u8 band;
u8 subband;
center_chan = channel->hw_value; center_chan = channel->hw_value;
primary_freq = channel->center_freq; primary_freq = channel->center_freq;
...@@ -246,15 +244,12 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef, ...@@ -246,15 +244,12 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
case NL80211_CHAN_WIDTH_20_NOHT: case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20:
bandwidth = RTW89_CHANNEL_WIDTH_20; bandwidth = RTW89_CHANNEL_WIDTH_20;
primary_chan_idx = RTW89_SC_DONT_CARE;
break; break;
case NL80211_CHAN_WIDTH_40: case NL80211_CHAN_WIDTH_40:
bandwidth = RTW89_CHANNEL_WIDTH_40; bandwidth = RTW89_CHANNEL_WIDTH_40;
if (primary_freq > center_freq) { if (primary_freq > center_freq) {
primary_chan_idx = RTW89_SC_20_UPPER;
center_chan -= 2; center_chan -= 2;
} else { } else {
primary_chan_idx = RTW89_SC_20_LOWER;
center_chan += 2; center_chan += 2;
} }
break; break;
...@@ -263,11 +258,9 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef, ...@@ -263,11 +258,9 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
bandwidth = nl_to_rtw89_bandwidth(width); bandwidth = nl_to_rtw89_bandwidth(width);
if (primary_freq > center_freq) { if (primary_freq > center_freq) {
offset = (primary_freq - center_freq - 10) / 20; offset = (primary_freq - center_freq - 10) / 20;
primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
center_chan -= 2 + offset * 4; center_chan -= 2 + offset * 4;
} else { } else {
offset = (center_freq - primary_freq - 10) / 20; offset = (center_freq - primary_freq - 10) / 20;
primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
center_chan += 2 + offset * 4; center_chan += 2 + offset * 4;
} }
break; break;
...@@ -289,68 +282,7 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef, ...@@ -289,68 +282,7 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
break; break;
} }
switch (band) { rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth);
default:
case RTW89_BAND_2G:
switch (center_chan) {
default:
case 1 ... 14:
subband = RTW89_CH_2G;
break;
}
break;
case RTW89_BAND_5G:
switch (center_chan) {
default:
case 36 ... 64:
subband = RTW89_CH_5G_BAND_1;
break;
case 100 ... 144:
subband = RTW89_CH_5G_BAND_3;
break;
case 149 ... 177:
subband = RTW89_CH_5G_BAND_4;
break;
}
break;
case RTW89_BAND_6G:
switch (center_chan) {
default:
case 1 ... 29:
subband = RTW89_CH_6G_BAND_IDX0;
break;
case 33 ... 61:
subband = RTW89_CH_6G_BAND_IDX1;
break;
case 65 ... 93:
subband = RTW89_CH_6G_BAND_IDX2;
break;
case 97 ... 125:
subband = RTW89_CH_6G_BAND_IDX3;
break;
case 129 ... 157:
subband = RTW89_CH_6G_BAND_IDX4;
break;
case 161 ... 189:
subband = RTW89_CH_6G_BAND_IDX5;
break;
case 193 ... 221:
subband = RTW89_CH_6G_BAND_IDX6;
break;
case 225 ... 253:
subband = RTW89_CH_6G_BAND_IDX7;
break;
}
break;
}
chan->channel = center_chan;
chan->freq = center_freq;
chan->primary_channel = channel->hw_value;
chan->band_type = band;
chan->band_width = bandwidth;
chan->subband_type = subband;
chan->pri_ch_idx = primary_chan_idx;
} }
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
......
...@@ -632,10 +632,14 @@ enum rtw89_sc_offset { ...@@ -632,10 +632,14 @@ enum rtw89_sc_offset {
struct rtw89_chan { struct rtw89_chan {
u8 channel; u8 channel;
u32 freq;
u8 primary_channel; u8 primary_channel;
enum rtw89_band band_type; enum rtw89_band band_type;
enum rtw89_bandwidth band_width; enum rtw89_bandwidth band_width;
/* The follow-up are derived from the above. We must ensure that it
* is assigned correctly in rtw89_chan_create() if new one is added.
*/
u32 freq;
enum rtw89_subband subband_type; enum rtw89_subband subband_type;
enum rtw89_sc_offset pri_ch_idx; enum rtw89_sc_offset pri_ch_idx;
}; };
......
...@@ -2388,11 +2388,8 @@ void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup) ...@@ -2388,11 +2388,8 @@ void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
scan_info->op_bw = cur->band_width; scan_info->op_bw = cur->band_width;
scan_info->op_band = cur->band_type; scan_info->op_band = cur->band_type;
} else { } else {
new = *cur; rtw89_chan_create(&new, scan_info->op_chan, scan_info->op_pri_ch,
new.primary_channel = scan_info->op_pri_ch; scan_info->op_band, scan_info->op_bw);
new.channel = scan_info->op_chan;
new.band_width = scan_info->op_bw;
new.band_type = scan_info->op_band;
rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new); rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
} }
} }
......
...@@ -3655,7 +3655,6 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h, ...@@ -3655,7 +3655,6 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
u32 len) u32 len)
{ {
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
struct rtw89_chan new; struct rtw89_chan new;
u8 reason, status, tx_fail, band; u8 reason, status, tx_fail, band;
u16 chan; u16 chan;
...@@ -3682,11 +3681,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h, ...@@ -3682,11 +3681,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
rtw89_hw_scan_complete(rtwdev, vif, false); rtw89_hw_scan_complete(rtwdev, vif, false);
break; break;
case RTW89_SCAN_ENTER_CH_NOTIFY: case RTW89_SCAN_ENTER_CH_NOTIFY:
new = *cur; rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20);
new.channel = chan;
new.primary_channel = chan;
new.band_type = band;
new.band_width = RTW89_CHANNEL_WIDTH_20;
rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new); rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
if (rtw89_is_op_chan(rtwdev, band, chan)) { if (rtw89_is_op_chan(rtwdev, band, chan)) {
rtw89_store_op_chan(rtwdev, false); rtw89_store_op_chan(rtwdev, false);
......
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