Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
authorKalle Valo <kvalo@kernel.org>
Sat, 29 Oct 2022 05:25:50 +0000 (08:25 +0300)
committerKalle Valo <kvalo@kernel.org>
Sat, 29 Oct 2022 05:25:50 +0000 (08:25 +0300)
ath.git patches for v6.2. Major changes:

ath11k

* support configuring channel dwell time during scan

1  2 
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/pcic.c

index a184c09d2f0fc9a8ee67a6345634ba6fae97b1fd,ce3d613fa36c440b773832d4f2dae59569e52b3e..19f61225a7085f89f44bdb80ebb0e71a818be6e3
@@@ -241,6 -241,11 +241,11 @@@ static void ar5523_cmd_tx_cb(struct ur
        }
  }
  
+ static void ar5523_cancel_tx_cmd(struct ar5523 *ar)
+ {
+       usb_kill_urb(ar->tx_cmd.urb_tx);
+ }
  static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
                      int ilen, void *odata, int olen, int flags)
  {
        }
  
        if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) {
+               ar5523_cancel_tx_cmd(ar);
                cmd->odata = NULL;
                ar5523_err(ar, "timeout waiting for command %02x reply\n",
                           code);
@@@ -1355,7 -1361,6 +1361,7 @@@ static const struct ieee80211_ops ar552
        .start                  = ar5523_start,
        .stop                   = ar5523_stop,
        .tx                     = ar5523_tx,
 +      .wake_tx_queue          = ieee80211_handle_wake_tx_queue,
        .set_rts_threshold      = ar5523_set_rts_threshold,
        .add_interface          = ar5523_add_interface,
        .remove_interface       = ar5523_remove_interface,
index 3cbcbb93a1a7a1c6556b15c794f51ad5ea056933,6d83a178a8915873e1940db06415238856a67c93..6426a38f8961aa7eed526868e779840a15fbfc7e
@@@ -241,7 -241,10 +241,10 @@@ const struct htt_rx_ring_tlv_filter ath
  #define ath11k_a_rates (ath11k_legacy_rates + 4)
  #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4)
  
- #define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */
+ #define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD              200 /* in msecs */
+ /* Overhead due to the processing of channel switch events from FW */
+ #define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD   10 /* in msecs */
  
  static const u32 ath11k_smps_map[] = {
        [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
@@@ -2081,7 -2084,7 +2084,7 @@@ static void ath11k_peer_assoc_h_he(stru
        struct cfg80211_chan_def def;
        const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
        enum nl80211_band band;
 -      u16 *he_mcs_mask;
 +      u16 he_mcs_mask[NL80211_HE_NSS_MAX];
        u8 max_nss, he_mcs;
        u16 he_tx_mcs = 0, v = 0;
        int i, he_nss, nss_idx;
                return;
  
        band = def.chan->band;
 -      he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
 +      memcpy(he_mcs_mask, arvif->bitrate_mask.control[band].he_mcs,
 +             sizeof(he_mcs_mask));
  
        if (ath11k_peer_assoc_h_he_masked(he_mcs_mask))
                return;
@@@ -3612,6 -3614,7 +3615,7 @@@ static int ath11k_mac_op_hw_scan(struc
        struct scan_req_params arg;
        int ret = 0;
        int i;
+       u32 scan_timeout;
  
        mutex_lock(&ar->conf_mutex);
  
                ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
        }
  
+       /* if duration is set, default dwell times will be overwritten */
+       if (req->duration) {
+               arg.dwell_time_active = req->duration;
+               arg.dwell_time_active_2g = req->duration;
+               arg.dwell_time_active_6g = req->duration;
+               arg.dwell_time_passive = req->duration;
+               arg.dwell_time_passive_6g = req->duration;
+               arg.burst_duration = req->duration;
+               scan_timeout = min_t(u32, arg.max_rest_time *
+                               (arg.num_chan - 1) + (req->duration +
+                               ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
+                               arg.num_chan, arg.max_scan_time);
+       } else {
+               scan_timeout = arg.max_scan_time;
+       }
+       /* Add a margin to account for event/command processing */
+       scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD;
        ret = ath11k_start_scan(ar, &arg);
        if (ret) {
                ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
                spin_unlock_bh(&ar->data_lock);
        }
  
-       /* Add a 200ms margin to account for event/command processing */
        ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
-                                    msecs_to_jiffies(arg.max_scan_time +
-                                                     ATH11K_MAC_SCAN_TIMEOUT_MSECS));
+                                    msecs_to_jiffies(scan_timeout));
  
  exit:
        kfree(arg.chan_list);
@@@ -4215,10 -4236,11 +4237,11 @@@ static void ath11k_sta_rc_update_wk(str
        const u8 *ht_mcs_mask;
        const u16 *vht_mcs_mask;
        const u16 *he_mcs_mask;
-       u32 changed, bw, nss, smps;
+       u32 changed, bw, nss, smps, bw_prev;
        int err, num_vht_rates, num_he_rates;
        const struct cfg80211_bitrate_mask *mask;
        struct peer_assoc_params peer_arg;
+       enum wmi_phy_mode peer_phymode;
  
        arsta = container_of(wk, struct ath11k_sta, update_wk);
        sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
        arsta->changed = 0;
  
        bw = arsta->bw;
+       bw_prev = arsta->bw_prev;
        nss = arsta->nss;
        smps = arsta->smps;
  
                           ath11k_mac_max_he_nss(he_mcs_mask)));
  
        if (changed & IEEE80211_RC_BW_CHANGED) {
-               /* Send peer assoc command before set peer bandwidth param to
-                * avoid the mismatch between the peer phymode and the peer
-                * bandwidth.
-                */
-               ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true);
-               peer_arg.is_assoc = false;
-               err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
-               if (err) {
-                       ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n",
-                                   sta->addr, arvif->vdev_id, err);
-               } else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
+               /* Get the peer phymode */
+               ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
+               peer_phymode = peer_arg.peer_phymode;
+               ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n",
+                          sta->addr, bw, peer_phymode);
+               if (bw > bw_prev) {
+                       /* BW is upgraded. In this case we send WMI_PEER_PHYMODE
+                        * followed by WMI_PEER_CHWIDTH
+                        */
+                       ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n",
+                                  sta->addr, bw, bw_prev);
+                       err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+                                                       WMI_PEER_PHYMODE, peer_phymode);
+                       if (err) {
+                               ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
+                                           sta->addr, peer_phymode, err);
+                               goto err_rc_bw_changed;
+                       }
                        err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
                                                        WMI_PEER_CHWIDTH, bw);
                        if (err)
                                ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
                                            sta->addr, bw, err);
                } else {
-                       ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
-                                   sta->addr, arvif->vdev_id);
+                       /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
+                        * followed by WMI_PEER_PHYMODE
+                        */
+                       ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n",
+                                  sta->addr, bw, bw_prev);
+                       err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+                                                       WMI_PEER_CHWIDTH, bw);
+                       if (err) {
+                               ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
+                                           sta->addr, bw, err);
+                               goto err_rc_bw_changed;
+                       }
+                       err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+                                                       WMI_PEER_PHYMODE, peer_phymode);
+                       if (err)
+                               ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
+                                           sta->addr, peer_phymode, err);
                }
        }
  
                }
        }
  
+ err_rc_bw_changed:
        mutex_unlock(&ar->conf_mutex);
  }
  
@@@ -4505,6 -4560,34 +4561,34 @@@ exit
        return ret;
  }
  
+ static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
+                                             struct ieee80211_sta *sta)
+ {
+       u32 bw = WMI_PEER_CHWIDTH_20MHZ;
+       switch (sta->deflink.bandwidth) {
+       case IEEE80211_STA_RX_BW_20:
+               bw = WMI_PEER_CHWIDTH_20MHZ;
+               break;
+       case IEEE80211_STA_RX_BW_40:
+               bw = WMI_PEER_CHWIDTH_40MHZ;
+               break;
+       case IEEE80211_STA_RX_BW_80:
+               bw = WMI_PEER_CHWIDTH_80MHZ;
+               break;
+       case IEEE80211_STA_RX_BW_160:
+               bw = WMI_PEER_CHWIDTH_160MHZ;
+               break;
+       default:
+               ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n",
+                           sta->deflink.bandwidth, sta->addr);
+               bw = WMI_PEER_CHWIDTH_20MHZ;
+               break;
+       }
+       return bw;
+ }
  static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif,
                                   struct ieee80211_sta *sta,
                if (ret)
                        ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
                                    sta->addr);
+               spin_lock_bh(&ar->data_lock);
+               /* Set arsta bw and prev bw */
+               arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
+               arsta->bw_prev = arsta->bw;
+               spin_unlock_bh(&ar->data_lock);
        } else if (old_state == IEEE80211_STA_ASSOC &&
                   new_state == IEEE80211_STA_AUTHORIZED) {
                spin_lock_bh(&ar->ab->base_lock);
@@@ -4713,28 -4802,8 +4803,8 @@@ static void ath11k_mac_op_sta_rc_update
        spin_lock_bh(&ar->data_lock);
  
        if (changed & IEEE80211_RC_BW_CHANGED) {
-               bw = WMI_PEER_CHWIDTH_20MHZ;
-               switch (sta->deflink.bandwidth) {
-               case IEEE80211_STA_RX_BW_20:
-                       bw = WMI_PEER_CHWIDTH_20MHZ;
-                       break;
-               case IEEE80211_STA_RX_BW_40:
-                       bw = WMI_PEER_CHWIDTH_40MHZ;
-                       break;
-               case IEEE80211_STA_RX_BW_80:
-                       bw = WMI_PEER_CHWIDTH_80MHZ;
-                       break;
-               case IEEE80211_STA_RX_BW_160:
-                       bw = WMI_PEER_CHWIDTH_160MHZ;
-                       break;
-               default:
-                       ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
-                                   sta->deflink.bandwidth, sta->addr);
-                       bw = WMI_PEER_CHWIDTH_20MHZ;
-                       break;
-               }
+               bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
+               arsta->bw_prev = arsta->bw;
                arsta->bw = bw;
        }
  
@@@ -6163,6 -6232,40 +6233,40 @@@ void ath11k_mac_11d_scan_stop_all(struc
        }
  }
  
+ static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif)
+ {
+       unsigned long time_left;
+       struct ieee80211_vif *vif = arvif->vif;
+       int ret = 0;
+       lockdep_assert_held(&ar->conf_mutex);
+       reinit_completion(&ar->vdev_delete_done);
+       ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
+       if (ret) {
+               ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n",
+                           arvif->vdev_id, ret);
+               return ret;
+       }
+       time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
+                                               ATH11K_VDEV_DELETE_TIMEOUT_HZ);
+       if (time_left == 0) {
+               ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
+               return -ETIMEDOUT;
+       }
+       ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id);
+       ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
+       ar->num_created_vdevs--;
+       ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
+                  vif->addr, arvif->vdev_id);
+       return ret;
+ }
  static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif)
  {
  
        ath11k_dp_vdev_tx_attach(ar, arvif);
  
+       ath11k_debugfs_add_interface(arvif);
        if (vif->type != NL80211_IFTYPE_MONITOR &&
            test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) {
                ret = ath11k_mac_monitor_vdev_create(ar);
-               if (ret) {
+               if (ret)
                        ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d",
                                    ret);
-                       goto err_peer_del;
-               }
        }
  
-       ath11k_debugfs_add_interface(arvif);
        mutex_unlock(&ar->conf_mutex);
  
        return 0;
@@@ -6400,16 -6501,12 +6502,12 @@@ err_peer_del
        }
  
  err_vdev_del:
-       ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
-       ar->num_created_vdevs--;
-       ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
-       ab->free_vdev_map |= 1LL << arvif->vdev_id;
+       ath11k_mac_vdev_delete(ar, arvif);
        spin_lock_bh(&ar->data_lock);
        list_del(&arvif->list);
        spin_unlock_bh(&ar->data_lock);
  
  err:
-       ath11k_debugfs_remove_interface(arvif);
        mutex_unlock(&ar->conf_mutex);
  
        return ret;
@@@ -6432,7 -6529,6 +6530,6 @@@ static void ath11k_mac_op_remove_interf
        struct ath11k *ar = hw->priv;
        struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
        struct ath11k_base *ab = ar->ab;
-       unsigned long time_left;
        int ret;
        int i;
  
                                    arvif->vdev_id, ret);
        }
  
-       reinit_completion(&ar->vdev_delete_done);
-       ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
+       ret = ath11k_mac_vdev_delete(ar, arvif);
        if (ret) {
-               ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n",
+               ath11k_warn(ab, "failed to delete vdev %d: %d\n",
                            arvif->vdev_id, ret);
                goto err_vdev_del;
        }
  
-       time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
-                                               ATH11K_VDEV_DELETE_TIMEOUT_HZ);
-       if (time_left == 0) {
-               ath11k_warn(ab, "Timeout in receiving vdev delete response\n");
-               goto err_vdev_del;
-       }
-       ab->free_vdev_map |= 1LL << (arvif->vdev_id);
-       ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
-       ar->num_created_vdevs--;
-       ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
-                  vif->addr, arvif->vdev_id);
        if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
                clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
                ar->monitor_vdev_id = -1;
@@@ -8539,7 -8619,6 +8620,7 @@@ err_fallback
  
  static const struct ieee80211_ops ath11k_ops = {
        .tx                             = ath11k_mac_op_tx,
 +      .wake_tx_queue                  = ieee80211_handle_wake_tx_queue,
        .start                          = ath11k_mac_op_start,
        .stop                           = ath11k_mac_op_stop,
        .reconfig_complete              = ath11k_mac_op_reconfig_complete,
@@@ -9015,6 -9094,9 +9096,9 @@@ static int __ath11k_mac_register(struc
                                      NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
        }
  
+       wiphy_ext_feature_set(ar->hw->wiphy,
+                             NL80211_EXT_FEATURE_SET_SCAN_DWELL);
        ath11k_reg_init(ar);
  
        if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
index 380f9d37b6449f0dd76fc3668c6d051605911851,d2f0112e8df019b0ccb73cbe1832efd9967eec3f..30d66147223f49cb98e05e4cd38ee71380493bf9
@@@ -218,9 -218,16 +218,16 @@@ int ath11k_pcic_read(struct ath11k_bas
        if (wakeup_required && ab->pci.ops->wakeup) {
                ret = ab->pci.ops->wakeup(ab);
                if (ret) {
-                       ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n",
-                                   start, ret);
-                       return ret;
+                       ath11k_warn(ab,
+                                   "wakeup failed, data may be invalid: %d",
+                                   ret);
+                       /* Even though wakeup() failed, continue processing rather
+                        * than returning because some parts of the data may still
+                        * be valid and useful in some cases, e.g. could give us
+                        * some clues on firmware crash.
+                        * Mislead due to invalid data could be avoided because we
+                        * are aware of the wakeup failure.
+                        */
                }
        }
  
@@@ -563,7 -570,7 +570,7 @@@ static int ath11k_pcic_ext_irq_config(s
                irq_grp->grp_id = i;
                init_dummy_netdev(&irq_grp->napi_ndev);
                netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
 -                             ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
 +                             ath11k_pcic_ext_grp_napi_poll);
  
                if (ab->hw_params.ring_mask->tx[i] ||
                    ab->hw_params.ring_mask->rx[i] ||