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

19 files changed:
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/core.h
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath11k/pcic.c
drivers/net/wireless/ath/ath11k/qmi.c
drivers/net/wireless/ath/ath11k/reg.c
drivers/net/wireless/ath/ath11k/wmi.c
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/mci.c
drivers/net/wireless/ath/carl9170/Makefile
drivers/net/wireless/ath/carl9170/wlan.h
drivers/net/wireless/ath/wil6210/debugfs.c

index a184c09d2f0fc9a8ee67a6345634ba6fae97b1fd..19f61225a7085f89f44bdb80ebb0e71a818be6e3 100644 (file)
@@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb)
        }
 }
 
+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)
 {
@@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
        }
 
        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);
index 400f332a7ff015fe4aaaf213d615142e420cc5ad..5eb131ab916fd0a56581602680dc98d2f63480c6 100644 (file)
@@ -99,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA988X_HW_2_0_VERSION,
@@ -138,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9887_HW_1_0_VERSION,
@@ -178,6 +180,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA6174_HW_3_2_VERSION,
@@ -213,6 +216,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = true,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
@@ -252,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
@@ -291,6 +296,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA6174_HW_3_0_VERSION,
@@ -330,6 +336,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA6174_HW_3_2_VERSION,
@@ -373,6 +380,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = true,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA99X0_HW_2_0_DEV_VERSION,
@@ -418,6 +426,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9984_HW_1_0_DEV_VERSION,
@@ -470,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9888_HW_2_0_DEV_VERSION,
@@ -519,6 +529,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9377_HW_1_0_DEV_VERSION,
@@ -558,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9377_HW_1_1_DEV_VERSION,
@@ -599,6 +611,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA9377_HW_1_1_DEV_VERSION,
@@ -631,6 +644,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = QCA4019_HW_1_0_DEV_VERSION,
@@ -677,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
                .use_fw_tx_credits = true,
+               .delay_unmap_buffer = false,
        },
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
@@ -709,6 +724,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .dynamic_sar_support = true,
                .hw_restart_disconnect = true,
                .use_fw_tx_credits = false,
+               .delay_unmap_buffer = true,
        },
 };
 
index 6d1784f74bea497e7ac1c34a70504e6d4b023960..5bfeecb95fca2381cf0b153773759aeb0380033e 100644 (file)
@@ -56,6 +56,15 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
        ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
                   ep->eid, skb);
 
+       /* A corner case where the copy completion is reaching to host but still
+        * copy engine is processing it due to which host unmaps corresponding
+        * memory and causes SMMU fault, hence as workaround adding delay
+        * the unmapping memory to avoid SMMU faults.
+        */
+       if (ar->hw_params.delay_unmap_buffer &&
+           ep->ul_pipe_id == 3)
+               mdelay(2);
+
        hdr = (struct ath10k_htc_hdr *)skb->data;
        ath10k_htc_restore_tx_skb(ep->htc, skb);
 
index f06cf39204e2c11c7f11bcfcdc3978c88243c34a..c051a22fce145f1203a6a13b35b5140b6279d4e7 100644 (file)
@@ -1108,8 +1108,10 @@ struct htt_rx_in_ord_ind {
        u8 reserved;
        __le16 msdu_count;
        union {
-               struct htt_rx_in_ord_msdu_desc msdu_descs32[0];
-               struct htt_rx_in_ord_msdu_desc_ext msdu_descs64[0];
+               DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc,
+                                  msdu_descs32);
+               DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc_ext,
+                                  msdu_descs64);
        } __packed;
 } __packed;
 
index 1b99f3a39a1134bcca75fe729c0fe5f1acdbf3ac..9643031a4427ada6a69b7455a89f3bc57229a2e7 100644 (file)
@@ -637,6 +637,8 @@ struct ath10k_hw_params {
        bool hw_restart_disconnect;
 
        bool use_fw_tx_credits;
+
+       bool delay_unmap_buffer;
 };
 
 struct htt_resp;
index 876410a47d1d2088b4e83b913cc6a338e926c81c..6b6aa3c36744876df49180fb9955b02cff9a446b 100644 (file)
@@ -584,7 +584,14 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
                        ath10k_warn(ar, "did not find station from tdls peer event");
                        goto exit;
                }
+
                arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
+               if (!arvif) {
+                       ath10k_warn(ar, "no vif for vdev_id %d found",
+                                   __le32_to_cpu(ev->vdev_id));
+                       goto exit;
+               }
+
                ieee80211_tdls_oper_request(
                                        arvif->vif, station->addr,
                                        NL80211_TDLS_TEARDOWN,
index b99180bc81723b150476942667080bad6d80555b..0ab2f190f1ecb0a8c98d641f6f8ad8729a0cb119 100644 (file)
@@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct work_struct *work)
        }
 }
 
-static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
+void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
 {
        struct ath11k *ar;
        struct ath11k_pdev *pdev;
@@ -1677,6 +1677,10 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
                             ath11k_mac_tx_mgmt_pending_free, ar);
                idr_destroy(&ar->txmgmt_idr);
                wake_up(&ar->txmgmt_empty_waitq);
+
+               ar->monitor_vdev_id = -1;
+               clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
+               clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
        }
 
        wake_up(&ab->wmi_ab.tx_credits_wq);
@@ -1730,9 +1734,6 @@ static void ath11k_core_restart(struct work_struct *work)
        struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
        int ret;
 
-       if (!ab->is_reset)
-               ath11k_core_pre_reconfigure_recovery(ab);
-
        ret = ath11k_core_reconfigure_on_crash(ab);
        if (ret) {
                ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
index cf2f52cc4e30de528391dc9c4a9678e01ca810fa..22460b0abf037317a4c26d2ad04bdf81501cdd10 100644 (file)
@@ -505,6 +505,8 @@ struct ath11k_sta {
        u64 ps_start_jiffies;
        u64 ps_total_duration;
        bool peer_current_ps_valid;
+
+       u32 bw_prev;
 };
 
 #define ATH11K_MIN_5G_FREQ 4150
@@ -1157,6 +1159,7 @@ int ath11k_core_check_smbios(struct ath11k_base *ab);
 void ath11k_core_halt(struct ath11k *ar);
 int ath11k_core_resume(struct ath11k_base *ab);
 int ath11k_core_suspend(struct ath11k_base *ab);
+void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
 
 const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
                                                    const char *filename);
index 3cbcbb93a1a7a1c6556b15c794f51ad5ea056933..6426a38f8961aa7eed526868e779840a15fbfc7e 100644 (file)
@@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = {
 #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,
@@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
        struct scan_req_params arg;
        int ret = 0;
        int i;
+       u32 scan_timeout;
 
        mutex_lock(&ar->conf_mutex);
 
@@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
                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);
@@ -3689,10 +3713,8 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
                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 +4237,11 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
        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);
@@ -4239,6 +4262,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
        arsta->changed = 0;
 
        bw = arsta->bw;
+       bw_prev = arsta->bw_prev;
        nss = arsta->nss;
        smps = arsta->smps;
 
@@ -4252,26 +4276,57 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
                           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);
                }
        }
 
@@ -4352,6 +4407,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
                }
        }
 
+err_rc_bw_changed:
        mutex_unlock(&ar->conf_mutex);
 }
 
@@ -4505,6 +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,
@@ -4590,6 +4674,12 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
                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 +4803,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
        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 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
        }
 }
 
+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)
 {
@@ -6373,18 +6477,16 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
 
        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 +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 +6530,6 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
        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;
 
@@ -6453,29 +6550,13 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
                                    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;
@@ -9015,6 +9096,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
                                      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..30d66147223f49cb98e05e4cd38ee71380493bf9 100644 (file)
@@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)
        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.
+                        */
                }
        }
 
index 51de2208b7899cf6eab025299498113ba221e269..145f20a681bd1c1ad88057ebdc301ca1ea15a241 100644 (file)
@@ -19,6 +19,7 @@
 #define SLEEP_CLOCK_SELECT_INTERNAL_BIT        0x02
 #define HOST_CSTATE_BIT                        0x04
 #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
+#define PLATFORM_CAP_PCIE_PME_D3COLD   0x10
 
 #define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING="
 
@@ -1752,6 +1753,8 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
        if (ab->hw_params.global_reset)
                req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET;
 
+       req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD;
+
        ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n");
 
        ret = qmi_txn_init(&ab->qmi.handle, &txn,
@@ -1961,7 +1964,7 @@ static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
                        continue;
 
                dma_free_coherent(ab->dev,
-                                 ab->qmi.target_mem[i].size,
+                                 ab->qmi.target_mem[i].prev_size,
                                  ab->qmi.target_mem[i].vaddr,
                                  ab->qmi.target_mem[i].paddr);
                ab->qmi.target_mem[i].vaddr = NULL;
@@ -1982,12 +1985,12 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
                 * in such case, no need to allocate memory for FW again.
                 */
                if (chunk->vaddr) {
-                       if (chunk->prev_type == chunk->type ||
+                       if (chunk->prev_type == chunk->type &&
                            chunk->prev_size == chunk->size)
                                continue;
 
                        /* cannot reuse the existing chunk */
-                       dma_free_coherent(ab->dev, chunk->size,
+                       dma_free_coherent(ab->dev, chunk->prev_size,
                                          chunk->vaddr, chunk->paddr);
                        chunk->vaddr = NULL;
                }
@@ -3158,6 +3161,9 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
                case ATH11K_QMI_EVENT_SERVER_EXIT:
                        set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
                        set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
+
+                       if (!ab->is_reset)
+                               ath11k_core_pre_reconfigure_recovery(ab);
                        break;
                case ATH11K_QMI_EVENT_REQUEST_MEM:
                        ret = ath11k_qmi_event_mem_request(qmi);
index 7ee3ff69dfc85b62a6550b9c2342250be148479c..6fae4e61ede7f09d29411225e3f6e318f5cfa65f 100644 (file)
@@ -287,11 +287,7 @@ int ath11k_regd_update(struct ath11k *ar)
                goto err;
        }
 
-       rtnl_lock();
-       wiphy_lock(ar->hw->wiphy);
-       ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy);
-       wiphy_unlock(ar->hw->wiphy);
-       rtnl_unlock();
+       ret = regulatory_set_wiphy_regd(ar->hw->wiphy, regd_copy);
 
        kfree(regd_copy);
 
index fad9f8d308a207ab35a402af24deb61fd66bb2df..2a8a3e3dcff66d1aaf9b53d9aeee6fd205f266ec 100644 (file)
@@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
        }
 
        ath11k_dbg(ab, ATH11K_DBG_WMI,
-                  "peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
+                  "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
                   ev->peer_macaddr.addr, ev->peer_ps_state,
                   ev->ps_supported_bitmap, ev->peer_ps_valid,
                   ev->peer_ps_timestamp);
index 9bdfcee2f448e8394a66fdeebc8ae9bd2a2219df..eff94bcd1f0ab07c668d447c6793ca7ff51b0292 100644 (file)
@@ -45,11 +45,6 @@ ath9k_hw-y:= \
                ar9003_eeprom.o \
                ar9003_paprd.o
 
-# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_mac.o += -Wno-array-bounds
-endif
-
 ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o
 
 ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
index 4d9002a9d082c459ffd44db2c2ad4b78d405c19c..1a2e0c7eeb023cb133cf008c28674ed7ed45c931 100644 (file)
@@ -708,14 +708,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
        struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
        struct hif_device_usb *hif_dev = rx_buf->hif_dev;
        struct sk_buff *skb = rx_buf->skb;
-       struct sk_buff *nskb;
        int ret;
 
        if (!skb)
                return;
 
        if (!hif_dev)
-               goto free;
+               goto free_skb;
 
        switch (urb->status) {
        case 0:
@@ -724,7 +723,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
        case -ECONNRESET:
        case -ENODEV:
        case -ESHUTDOWN:
-               goto free;
+               goto free_skb;
        default:
                skb_reset_tail_pointer(skb);
                skb_trim(skb, 0);
@@ -735,25 +734,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
        if (likely(urb->actual_length != 0)) {
                skb_put(skb, urb->actual_length);
 
-               /* Process the command first */
+               /*
+                * Process the command first.
+                * skb is either freed here or passed to be
+                * managed to another callback function.
+                */
                ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
                                 skb->len, USB_REG_IN_PIPE);
 
-
-               nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
-               if (!nskb) {
+               skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
+               if (!skb) {
                        dev_err(&hif_dev->udev->dev,
                                "ath9k_htc: REG_IN memory allocation failure\n");
-                       urb->context = NULL;
-                       return;
+                       goto free_rx_buf;
                }
 
-               rx_buf->skb = nskb;
+               rx_buf->skb = skb;
 
                usb_fill_int_urb(urb, hif_dev->udev,
                                 usb_rcvintpipe(hif_dev->udev,
                                                 USB_REG_IN_PIPE),
-                                nskb->data, MAX_REG_IN_BUF_SIZE,
+                                skb->data, MAX_REG_IN_BUF_SIZE,
                                 ath9k_hif_usb_reg_in_cb, rx_buf, 1);
        }
 
@@ -762,12 +763,13 @@ resubmit:
        ret = usb_submit_urb(urb, GFP_ATOMIC);
        if (ret) {
                usb_unanchor_urb(urb);
-               goto free;
+               goto free_skb;
        }
 
        return;
-free:
+free_skb:
        kfree_skb(skb);
+free_rx_buf:
        kfree(rx_buf);
        urb->context = NULL;
 }
@@ -780,14 +782,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
        spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
        list_for_each_entry_safe(tx_buf, tx_buf_tmp,
                                 &hif_dev->tx.tx_buf, list) {
-               usb_get_urb(tx_buf->urb);
-               spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
-               usb_kill_urb(tx_buf->urb);
                list_del(&tx_buf->list);
                usb_free_urb(tx_buf->urb);
                kfree(tx_buf->buf);
                kfree(tx_buf);
-               spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
        }
        spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
@@ -1329,10 +1327,24 @@ static int send_eject_command(struct usb_interface *interface)
 static int ath9k_hif_usb_probe(struct usb_interface *interface,
                               const struct usb_device_id *id)
 {
+       struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out;
        struct usb_device *udev = interface_to_usbdev(interface);
+       struct usb_host_interface *alt;
        struct hif_device_usb *hif_dev;
        int ret = 0;
 
+       /* Verify the expected endpoints are present */
+       alt = interface->cur_altsetting;
+       if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 ||
+           usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE ||
+           usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE ||
+           usb_endpoint_num(int_in) != USB_REG_IN_PIPE ||
+           usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) {
+               dev_err(&udev->dev,
+                       "ath9k_htc: Device endpoint numbers are not the expected ones\n");
+               return -ENODEV;
+       }
+
        if (id->driver_info == STORAGE_DEVICE)
                return send_eject_command(interface);
 
index 039bf0c35fbed6cf89d18b4e4cb2498b5288ff47..3363fc4e89661a98d1e1a96a7b3cccf5dafd15fb 100644 (file)
@@ -266,7 +266,9 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc)
                        stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
                                ATH_MCI_INQUIRY_PRIO;
        } else {
-               u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
+               static const u8 prof_prio[] = {
+                       50, 90, 94, 52
+               }; /* RFCOMM, A2DP, HID, PAN */
 
                stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
                stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
@@ -644,7 +646,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        struct ath9k_channel *chan = ah->curchan;
-       u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
+       static const u32 channelmap[] = {
+               0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff
+       };
        int i;
        s16 chan_start, chan_end;
        u16 wlan_chan;
index 7463baa62fa8749f7f9f1bf280b00f2ca6d8f2dd..1a81868ce26d99012bcbd7858e7c1d2b90975516 100644 (file)
@@ -3,8 +3,3 @@ carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o
 carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o
 
 obj-$(CONFIG_CARL9170) += carl9170.o
-
-# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_cmd.o += -Wno-array-bounds
-endif
index 0a4e42e806b9608544e4819df0753e9ed4bedf6e..ded2c6d0a75980339fab2245e75bd82930dc5155 100644 (file)
@@ -271,7 +271,7 @@ struct ar9170_tx_frame {
 
        union {
                struct ieee80211_hdr i3e;
-               u8 payload[0];
+               DECLARE_FLEX_ARRAY(u8, payload);
        } data;
 } __packed;
 
index 04d1aa0e2d35769347063cf0d4f632558f4f05db..c021ebcddee76fb1b57cbfe6443eadd90b20fd45 100644 (file)
@@ -2154,7 +2154,7 @@ static const struct file_operations fops_led_blink_time = {
 };
 
 /*---------FW capabilities------------*/
-static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data)
+static int fw_capabilities_show(struct seq_file *s, void *data)
 {
        struct wil6210_priv *wil = s->private;
 
@@ -2163,22 +2163,10 @@ static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data)
 
        return 0;
 }
-
-static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, wil_fw_capabilities_debugfs_show,
-                          inode->i_private);
-}
-
-static const struct file_operations fops_fw_capabilities = {
-       .open           = wil_fw_capabilities_seq_open,
-       .release        = single_release,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-};
+DEFINE_SHOW_ATTRIBUTE(fw_capabilities);
 
 /*---------FW version------------*/
-static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)
+static int fw_version_show(struct seq_file *s, void *data)
 {
        struct wil6210_priv *wil = s->private;
 
@@ -2189,19 +2177,7 @@ static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)
 
        return 0;
 }
-
-static int wil_fw_version_seq_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, wil_fw_version_debugfs_show,
-                          inode->i_private);
-}
-
-static const struct file_operations fops_fw_version = {
-       .open           = wil_fw_version_seq_open,
-       .release        = single_release,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-};
+DEFINE_SHOW_ATTRIBUTE(fw_version);
 
 /*---------suspend_stats---------*/
 static ssize_t wil_write_suspend_stats(struct file *file,
@@ -2366,8 +2342,8 @@ static const struct {
        {"recovery", 0644,              &fops_recovery},
        {"led_cfg",     0644,           &fops_led_cfg},
        {"led_blink_time",      0644,   &fops_led_blink_time},
-       {"fw_capabilities",     0444,   &fops_fw_capabilities},
-       {"fw_version",  0444,           &fops_fw_version},
+       {"fw_capabilities",     0444,   &fw_capabilities_fops},
+       {"fw_version",  0444,           &fw_version_fops},
        {"suspend_stats",       0644,   &fops_suspend_stats},
        {"compressed_rx_status", 0644,  &fops_compressed_rx_status},
        {"srings",      0444,           &srings_fops},