wifi: ath11k: Add spectral scan support for 160 MHz
authorTamizh Chelvam Raja <quic_tamizhr@quicinc.com>
Sat, 24 Sep 2022 13:47:12 +0000 (16:47 +0300)
committerKalle Valo <quic_kvalo@quicinc.com>
Mon, 26 Sep 2022 09:40:12 +0000 (12:40 +0300)
There are two types of 160 MHz spectral scan support mentioned below

1. Fragmented approach
2. Single event approach

In this fragmented approach, single 160 MHz will be split as two
80 MHz buffer. First fft sample buffer will contain spectral scan
result of primary 80 MHz and the second fft sample buffer will contain
secondary 80 MHz and here cfreq1 and cfreq2 will be mentioned.
In case of 160 MHz on 36th channel will contain cfreq1 as 5210 and
cfreq2 as 5290. Chipsets which support this approach are IPQ8074/IPQ6018.

Replacing freq1 with freq2 in every secondary sepctral scan event to
distinguish between two different 80 MHz spectral event data.

In the 2nd approach each fft sample buffer will contain spectral scan
result for whole 160 MHz by mentioning cfreq1 as 5250 which is center
frequency of whole 160 MHz. Chipset which support this approach is QCN9074.

Host will receive spectral event from target for every 5 fft samples.

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01120-QCAHKSWPL-1
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01120-QCAHKSWP

Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220725055001.15194-1-quic_tamizhr@quicinc.com
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/hw.h
drivers/net/wireless/ath/ath11k/spectral.c
drivers/net/wireless/ath/ath11k/spectral.h

index 9894f90..b99180b 100644 (file)
@@ -70,6 +70,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 16,
                        .max_fft_bins = 512,
+                       .fragment_160mhz = true,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -149,6 +150,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 16,
                        .max_fft_bins = 512,
+                       .fragment_160mhz = true,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -228,6 +230,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 0,
                        .max_fft_bins = 0,
+                       .fragment_160mhz = false,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -308,6 +311,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 16,
                        .fft_hdr_len = 24,
                        .max_fft_bins = 1024,
+                       .fragment_160mhz = false,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -387,6 +391,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 0,
                        .max_fft_bins = 0,
+                       .fragment_160mhz = false,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -468,6 +473,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 0,
                        .max_fft_bins = 0,
+                       .fragment_160mhz = false,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -548,6 +554,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                        .summary_pad_sz = 0,
                        .fft_hdr_len = 0,
                        .max_fft_bins = 0,
+                       .fragment_160mhz = false,
                },
 
                .interface_modes = BIT(NL80211_IFTYPE_STATION) |
index f4a3083..8a3f248 100644 (file)
@@ -173,6 +173,7 @@ struct ath11k_hw_params {
                u8 summary_pad_sz;
                u8 fft_hdr_len;
                u16 max_fft_bins;
+               bool fragment_160mhz;
        } spectral;
 
        u16 interface_modes;
index 516a7b4..7058681 100644 (file)
@@ -30,6 +30,7 @@
 #define ATH11K_SPECTRAL_20MHZ                  20
 #define ATH11K_SPECTRAL_40MHZ                  40
 #define ATH11K_SPECTRAL_80MHZ                  80
+#define ATH11K_SPECTRAL_160MHZ                 160
 
 #define ATH11K_SPECTRAL_SIGNATURE              0xFA
 
@@ -183,6 +184,8 @@ static int ath11k_spectral_scan_trigger(struct ath11k *ar)
        if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED)
                return 0;
 
+       ar->spectral.is_primary = true;
+
        ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
                                              ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
                                              ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
@@ -585,6 +588,7 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
        u8 chan_width_mhz, bin_sz;
        int ret;
        u32 check_length;
+       bool fragment_sample = false;
 
        lockdep_assert_held(&ar->spectral.lock);
 
@@ -639,6 +643,13 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
        case ATH11K_SPECTRAL_80MHZ:
                fft_sample->chan_width_mhz = chan_width_mhz;
                break;
+       case ATH11K_SPECTRAL_160MHZ:
+               if (ab->hw_params.spectral.fragment_160mhz) {
+                       chan_width_mhz /= 2;
+                       fragment_sample = true;
+               }
+               fft_sample->chan_width_mhz = chan_width_mhz;
+               break;
        default:
                ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
                return -EINVAL;
@@ -663,6 +674,17 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
        freq = summary->meta.freq2;
        fft_sample->freq2 = __cpu_to_be16(freq);
 
+       /* If freq2 is available then the spectral scan results are fragmented
+        * as primary and secondary
+        */
+       if (fragment_sample && freq) {
+               if (!ar->spectral.is_primary)
+                       fft_sample->freq1 = cpu_to_be16(freq);
+
+               /* We have to toggle the is_primary to handle the next report */
+               ar->spectral.is_primary = !ar->spectral.is_primary;
+       }
+
        ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
                                  ab->hw_params.spectral.fft_sz);
 
index 0817442..96bfa16 100644 (file)
@@ -35,6 +35,7 @@ struct ath11k_spectral {
        u16 count;
        u8 fft_size;
        bool enabled;
+       bool is_primary;
 };
 
 #ifdef CONFIG_ATH11K_SPECTRAL