1. 28 Sep, 2021 34 commits
  2. 24 Sep, 2021 3 commits
  3. 21 Sep, 2021 3 commits
    • Bryan O'Donoghue's avatar
      wcn36xx: Implement Idle Mode Power Save · 0e159d2c
      Bryan O'Donoghue authored
      Idle Mode Power Save (IMPS) is a power saving mechanism which when called
      by wcn36xx will cause the radio hardware to enter power collapse.
      
      This particular call maps nicely to a simple conjunction/disjunction around
      IEEE80211_CONF_CHANGE_IDLE and IEEE80211_CONF_IDLE.
      
      Here we enter idle when we are not associated with an AP. The kernel will
      incrementally toggle idle on/off in the process of trying to establish a
      connection, thus saving power until we are connected to the AP again, at
      which point we give way to BMPS if power_save is on.
      
      We've validated that with IMPS an apq8039 device which has the wcn36xx
      module loaded but, has not authenticated with an AP will get to VMIN on
      suspend and will not without IMPS.
      Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
      Tested-by: default avatarBenjamin Li <benl@squareup.com>
      Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
      Link: https://lore.kernel.org/r/20210909153320.2624649-1-bryan.odonoghue@linaro.org
      0e159d2c
    • Bryan O'Donoghue's avatar
      wcn36xx: Add ability for wcn36xx_smd_dump_cmd_req to pass two's complement · c0c2eb20
      Bryan O'Donoghue authored
      Qcom documents suggest passing of negative values to the dump command,
      however currently we convert from string to u32 not s32, so we cannot pass
      a two's complement value to the firmware in this way.
      
      There is in fact only one parameter which takes a two's complement value
      <tigger threshold> in the antenna diversity switch command.
      
      Downstream:
      iwpriv wlan0 dump 71 3 <schedule period> <trigger threshold> <hysteresis value>
      
      Upstream:
      echo "71 3 <schedule period> <trigger threshold> <hysteresis value>" > /sys/kernel/debug/ieee80211/phy0/wcn36xx/dump
      
      Fixes: 8e84c258 ("wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware")
      Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
      Reviewed-by: default avatarLoic Poulain <loic.poulain@linaro.org>
      Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
      Link: https://lore.kernel.org/r/20210909144428.2564650-3-bryan.odonoghue@linaro.org
      c0c2eb20
    • Bryan O'Donoghue's avatar
      wcn36xx: Fix Antenna Diversity Switching · 701668d3
      Bryan O'Donoghue authored
      We have been tracking a strange bug with Antenna Diversity Switching (ADS)
      on wcn3680b for a while.
      
      ADS is configured like this:
         A. Via a firmware configuration table baked into the NV area.
             1. Defines if ADS is enabled.
             2. Defines which GPIOs are connected to which antenna enable pin.
             3. Defines which antenna/GPIO is primary and which is secondary.
      
         B. WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, N)
            N is a bitmask of available antenna.
      
            Setting N to 3 indicates a bitmask of enabled antenna (1 | 2).
      
            Obviously then we can set N to 1 or N to 2 to fix to a particular
            antenna and disable antenna diversity.
      
         C. WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, XX)
            XX is the number of beacons between each antenna RSSI check.
            Setting this value to 50 means, every 50 received beacons, run the
            ADS algorithm.
      
         D. WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, YY)
            YY is a two's complement integer which specifies the RSSI decibel
            threshold below which ADS will run.
            We default to -60db here, meaning a measured RSSI <= -60db will
            trigger an ADS probe.
      
         E. WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, Z)
            Z is a hysteresis value, indicating a delta which the RSSI must
            exceed for the antenna switch to be valid.
      
            For example if HYST_THRESHOLD == 3 AntennaId1-RSSI == -60db and
            AntennaId-2-RSSI == -58db then firmware will not switch antenna.
            The threshold needs to be -57db or better to satisfy the criteria.
      
         F. A firmware feature bit also exists ANTENNA_DIVERSITY_SELECTION.
            This feature bit is used by the firmware to report if
            ANTENNA_DIVERSITY_SELECTION is supported. The host is not required to
            toggle this bit to enable or disable ADS.
      
      ADS works like this:
      
          A. Every XX beacons the firmware switches to or remains on the primary
             antenna.
      
          B. The firmware then sends a Request-To-Send (RTS) packet to the AP.
      
          C. The firmware waits for a Clear-To-Send (CTS) response from the AP.
      
          D. The firmware then notes the received RSSI on the CTS packet.
      
          E. The firmware then repeats steps A-D on the secondary antenna.
      
          F. Subsequently if the RSSI on the measured antenna is better than
             ASD_TRIGGER_THRESHOLD + the active antenna's RSSI then the
             measured antenna becomes the active antenna.
      
          G. If RSSI rises past ASD_TRIGGER_THRESHOLD then ADS doesn't run at
             all even if there is a substantially better RSSI on the alternative
             antenna.
      
      What we have been observing is that the RTS packet is being sent but the
      MAC address is a byte-swapped version of the target MAC. The ADS/RTS MAC is
      corrupted only when the link is encrypted, if the AP is open the RTS MAC is
      correct. Similarly if we configure the firmware to an RTS/CTS sequence for
      regular data - the transmitted RTS MAC is correctly formatted.
      
      Internally the wcn36xx firmware uses the indexes in the SMD commands to
      populate and extract data from specific entries in an STA lookup table. The
      AP's MAC appears a number of times in different indexes within this lookup
      table, so the MAC address extracted for the data-transmit RTS and the MAC
      address extracted for the ADS/RTS packet are not the same STA table index.
      
      Our analysis indicates the relevant firmware STA table index is
      "bssSelfStaIdx".
      
      There is an STA populate function responsible for formatting the MAC
      address of the bssSelfStaIdx including byte-swapping the MAC address.
      
      Its clear then that the required STA populate command did not run for
      bssSelfStaIdx.
      
      So taking a look at the sequence of SMD commands sent to the firmware we
      see the following downstream when moving from an unencrypted to encrypted
      BSS setup.
      
      - WLAN_HAL_CONFIG_BSS_REQ
      - WLAN_HAL_CONFIG_STA_REQ
      - WLAN_HAL_SET_STAKEY_REQ
      
      Upstream in wcn36xx we have
      
      - WLAN_HAL_CONFIG_BSS_REQ
      - WLAN_HAL_SET_STAKEY_REQ
      
      The solution then is to add the missing WLAN_HAL_CONFIG_STA_REQ between
      WLAN_HAL_CONFIG_BSS_REQ and WLAN_HAL_SET_STAKEY_REQ.
      
      No surprise WLAN_HAL_CONFIG_STA_REQ is the routine responsible for
      populating the STA lookup table in the firmware and once done the MAC sent
      by the ADS routine is in the correct byte-order.
      
      This bug is apparent with ADS but it is also the case that any other
      firmware routine that depends on the "bssSelfStaIdx" would retrieve
      malformed data on an encrypted link.
      
      Fixes: 3e977c5c ("wcn36xx: Define wcn3680 specific firmware parameters")
      Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
      Tested-by: default avatarBenjamin Li <benl@squareup.com>
      Reviewed-by: default avatarLoic Poulain <loic.poulain@linaro.org>
      Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
      Link: https://lore.kernel.org/r/20210909144428.2564650-2-bryan.odonoghue@linaro.org
      701668d3