]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Fix offloaded ACS regression for the 60 GHz band
authorNoam Shaked <nshaked@codeaurora.org>
Tue, 10 Mar 2020 01:16:02 +0000 (18:16 -0700)
committerJouni Malinen <j@w1.fi>
Mon, 23 Mar 2020 20:29:04 +0000 (22:29 +0200)
Addition of chan_2ghz_or_5ghz_to_freq() broke 60 GHz ACS, because it
assumes reported ACS channel is on either 2.4 or 5 GHz band. Fix this
by converting chan_2ghz_or_5ghz_to_freq() to a more generic
chan_to_freq(). The new function uses hw_mode to support 60 GHz.

Fixes: 41cac481a889 ("ACS: Use frequency params in ACS (offload) completed event interface")
Signed-off-by: Noam Shaked <nshaked@codeaurora.org>
src/drivers/driver_nl80211_event.c

index b634a2d1229367da82a34f87fbf9bee174abc16b..49d81d785ebb81ce1bb830e4477d7820891d130b 100644 (file)
@@ -1753,8 +1753,41 @@ static enum hostapd_hw_mode get_qca_hw_mode(u8 hw_mode)
 }
 
 
-static unsigned int chan_2ghz_or_5ghz_to_freq(u8 chan)
+static unsigned int chan_to_freq(struct wpa_driver_nl80211_data *drv,
+                                u8 chan, enum hostapd_hw_mode hw_mode)
 {
+       if (hw_mode == NUM_HOSTAPD_MODES) {
+               /* For drivers that do not report ACS_HW_MODE */
+               u16 num_modes, flags;
+               struct hostapd_hw_modes *modes;
+               u8 dfs_domain;
+               int i;
+
+               modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes,
+                                                   &flags, &dfs_domain);
+               if (!modes) {
+                       wpa_printf(MSG_DEBUG,
+                                  "nl80211: Fetching hardware mode failed");
+                       goto try_2_4_or_5;
+               }
+               if (num_modes == 1)
+                       hw_mode = modes[0].mode;
+
+               for (i = 0; i < num_modes; i++) {
+                       os_free(modes[i].channels);
+                       os_free(modes[i].rates);
+               }
+
+               os_free(modes);
+       }
+
+       if (hw_mode == HOSTAPD_MODE_IEEE80211AD) {
+               if (chan >= 1 && chan <= 6)
+                       return 56160 + (2160 * chan);
+               return 0;
+       }
+
+try_2_4_or_5:
        if (chan >= 1 && chan <= 13)
                return 2407 + 5 * chan;
        if (chan == 14)
@@ -1785,13 +1818,30 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
                return;
 
        os_memset(&event, 0, sizeof(event));
+       event.acs_selected_channels.hw_mode = NUM_HOSTAPD_MODES;
+
+       if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
+               u8 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
+
+               event.acs_selected_channels.hw_mode = get_qca_hw_mode(hw_mode);
+               if (event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES ||
+                   event.acs_selected_channels.hw_mode ==
+                   HOSTAPD_MODE_IEEE80211ANY) {
+                       wpa_printf(MSG_DEBUG,
+                                  "nl80211: Invalid hw_mode %d in ACS selection event",
+                                  hw_mode);
+                       return;
+               }
+       }
+
        if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) {
                event.acs_selected_channels.pri_freq = nla_get_u32(
                        tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]);
        } else {
                chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
                event.acs_selected_channels.pri_freq =
-                       chan_2ghz_or_5ghz_to_freq(chan);
+                       chan_to_freq(drv, chan,
+                                    event.acs_selected_channels.hw_mode);
        }
 
        if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) {
@@ -1801,7 +1851,8 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
                chan = nla_get_u8(
                        tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
                event.acs_selected_channels.sec_freq =
-                       chan_2ghz_or_5ghz_to_freq(chan);
+                       chan_to_freq(drv, chan,
+                                    event.acs_selected_channels.hw_mode);
        }
 
        if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
@@ -1813,20 +1864,6 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
        if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
                event.acs_selected_channels.ch_width =
                        nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
-       if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
-               u8 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
-
-               event.acs_selected_channels.hw_mode = get_qca_hw_mode(hw_mode);
-               if (event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES ||
-                   event.acs_selected_channels.hw_mode ==
-                   HOSTAPD_MODE_IEEE80211ANY) {
-                       wpa_printf(MSG_DEBUG,
-                                  "nl80211: Invalid hw_mode %d in ACS selection event",
-                                  hw_mode);
-                       return;
-               }
-       }
-
        wpa_printf(MSG_INFO,
                   "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
                   event.acs_selected_channels.pri_freq,