1 From patchwork Thu Sep 5 02:35:08 2024
2 Content-Type: text/plain; charset="utf-8"
4 Content-Transfer-Encoding: 7bit
5 X-Patchwork-Submitter: Kang Yang <quic_kangyang@quicinc.com>
6 X-Patchwork-Id: 13791624
7 X-Patchwork-Delegate: kvalo@adurom.com
8 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
10 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
11 (No client certificate requested)
12 by smtp.subspace.kernel.org (Postfix) with ESMTPS id D313D33CFC
13 for <linux-wireless@vger.kernel.org>; Thu, 5 Sep 2024 02:36:17 +0000 (UTC)
14 Authentication-Results: smtp.subspace.kernel.org;
15 arc=none smtp.client-ip=205.220.180.131
16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
17 t=1725503779; cv=none;
18 b=blv4mH95IN2AR7Rt90gw/V7DnZRtr3upgAP50X6ew3jh0CusPG6/OTO9CSJVthJnqHU3Y3GT88jaeMzb9+f2xzqgl7+E35TmwN3uf6dFmbp7CD8LL0W6xu76ZZgFGxzRspv9YoVy/fydZY6I4JRc2faWqI540+n9bHEXdSJTZMM=
19 ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
20 s=arc-20240116; t=1725503779; c=relaxed/simple;
21 bh=vjzfDc6UXtw2Li6Q3bAgcW0K1rcTpi3dAxkQgbT5ogI=;
22 h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
23 MIME-Version:Content-Type;
24 b=VMgF0PfIOoXmfB6EARb/O+dooXutjAm/cnemJ0RC7uc8TSIAusH1ffc6jF1XndEp+nPTWnuMQ5/d1cE/bPeIvSTxrtWaUepnKNjQDrNKm4NrqmjR446CT9t0VHG16RZ1cmCmU74qXnfgus4XfTqD093lc1N5Q/YRh/kwmcCzxhY=
25 ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
26 dmarc=pass (p=none dis=none) header.from=quicinc.com;
27 spf=pass smtp.mailfrom=quicinc.com;
28 dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
29 header.b=E5hktrdm; arc=none smtp.client-ip=205.220.180.131
30 Authentication-Results: smtp.subspace.kernel.org;
31 dmarc=pass (p=none dis=none) header.from=quicinc.com
32 Authentication-Results: smtp.subspace.kernel.org;
33 spf=pass smtp.mailfrom=quicinc.com
34 Authentication-Results: smtp.subspace.kernel.org;
35 dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
37 Received: from pps.filterd (m0279869.ppops.net [127.0.0.1])
38 by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
40 Thu, 5 Sep 2024 02:36:12 GMT
41 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
42 cc:content-transfer-encoding:content-type:date:from:in-reply-to
43 :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
44 No6X3gHpioHamjfMDccV8LJEZBGk/uDqbZ/fuGUTvJM=; b=E5hktrdmmOb3KcP6
45 Qi3M5Y06Yd8RxNJTps8WMEoXZ7xzROVuhmRmlG/mw21NjBMTTMgtjcaen/n8Anj3
46 Ash1VFK6s7PrLcwoUT/uui6hzleGE+X9Wh8DJXYnZKKWmeQ+8E0yEzNR0kt9FG0n
47 S+asFc8VYEJHid6QDNAfM9e4JqJgU3NGXYJBTBM2lpdbqeWU7LEYnVTGCqvOPaH2
48 K+QDwvNiNeXlqbaxnqCYimUrSDnTbSUoiVxSpTe9/muWWAB+6YuUbXRfTceqgcd1
49 xFIOE1KrtAowMOk5mO3tn6Tjl7nJzewVUm9hncBRfynP8k2jt1xosMezL42dmb56
51 Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com
53 by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 41bt674mq1-1
54 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
55 Thu, 05 Sep 2024 02:36:11 +0000 (GMT)
56 Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com
58 by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
60 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
61 Thu, 5 Sep 2024 02:36:10 GMT
62 Received: from kangyang.ap.qualcomm.com (10.80.80.8) by
63 nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server
64 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
65 15.2.1544.9; Wed, 4 Sep 2024 19:36:09 -0700
66 From: Kang Yang <quic_kangyang@quicinc.com>
67 To: <ath12k@lists.infradead.org>
68 CC: <linux-wireless@vger.kernel.org>, <quic_kangyang@quicinc.com>
69 Subject: [PATCH v3 1/4] wifi: ath12k: add configure country code for WCN7850
70 Date: Thu, 5 Sep 2024 10:35:08 +0800
71 Message-ID: <20240905023511.362-2-quic_kangyang@quicinc.com>
72 X-Mailer: git-send-email 2.34.1.windows.1
73 In-Reply-To: <20240905023511.362-1-quic_kangyang@quicinc.com>
74 References: <20240905023511.362-1-quic_kangyang@quicinc.com>
76 X-Mailing-List: linux-wireless@vger.kernel.org
77 List-Id: <linux-wireless.vger.kernel.org>
78 List-Subscribe: <mailto:linux-wireless+subscribe@vger.kernel.org>
79 List-Unsubscribe: <mailto:linux-wireless+unsubscribe@vger.kernel.org>
81 X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To
82 nalasex01b.na.qualcomm.com (10.47.209.197)
83 X-QCInternal: smtphost
84 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
86 X-Proofpoint-ORIG-GUID: FzfHe7cZy6IUVu8IKORVKLxkYG9f8WUl
87 X-Proofpoint-GUID: FzfHe7cZy6IUVu8IKORVKLxkYG9f8WUl
88 X-Proofpoint-Virus-Version: vendor=baseguard
89 engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29
90 definitions=2024-09-05_01,2024-09-04_01,2024-09-02_01
91 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
92 malwarescore=0 adultscore=0
93 bulkscore=0 mlxscore=0 impostorscore=0 suspectscore=0 phishscore=0
94 mlxlogscore=999 lowpriorityscore=0 spamscore=0 clxscore=1015
95 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1
96 engine=8.19.0-2407110000 definitions=main-2409050018
98 From: Wen Gong <quic_wgong@quicinc.com>
100 Add handler to send WMI_SET_CURRENT_COUNTRY_CMDID to firmware, which
101 is used for WCN7850 to update country code.
103 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
105 Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
106 Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
107 Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
109 drivers/net/wireless/ath/ath12k/wmi.c | 36 +++++++++++++++++++++++++++
110 drivers/net/wireless/ath/ath12k/wmi.h | 13 ++++++++++
111 2 files changed, 49 insertions(+)
113 --- a/drivers/net/wireless/ath/ath12k/wmi.c
114 +++ b/drivers/net/wireless/ath/ath12k/wmi.c
115 @@ -171,6 +171,8 @@ static const struct ath12k_wmi_tlv_polic
116 .min_len = sizeof(struct ath12k_wmi_p2p_noa_info) },
117 [WMI_TAG_P2P_NOA_EVENT] = {
118 .min_len = sizeof(struct wmi_p2p_noa_event) },
119 + [WMI_TAG_11D_NEW_COUNTRY_EVENT] = {
120 + .min_len = sizeof(struct wmi_11d_new_cc_event) },
123 static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len)
124 @@ -2363,7 +2365,10 @@ int ath12k_wmi_send_scan_start_cmd(struc
125 cmd->scan_id = cpu_to_le32(arg->scan_id);
126 cmd->scan_req_id = cpu_to_le32(arg->scan_req_id);
127 cmd->vdev_id = cpu_to_le32(arg->vdev_id);
128 - cmd->scan_priority = cpu_to_le32(arg->scan_priority);
129 + if (ar->state_11d == ATH12K_11D_PREPARING)
130 + arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM;
132 + arg->scan_priority = WMI_SCAN_PRIORITY_LOW;
133 cmd->notify_scan_events = cpu_to_le32(arg->notify_scan_events);
135 ath12k_wmi_copy_scan_event_cntrl_flags(cmd, arg);
136 @@ -3083,6 +3088,110 @@ out:
140 +int ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
141 + struct wmi_set_current_country_arg *arg)
143 + struct ath12k_wmi_pdev *wmi = ar->wmi;
144 + struct wmi_set_current_country_cmd *cmd;
145 + struct sk_buff *skb;
148 + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
152 + cmd = (struct wmi_set_current_country_cmd *)skb->data;
154 + ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_CURRENT_COUNTRY_CMD,
157 + cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);
158 + memcpy(&cmd->new_alpha2, &arg->alpha2, sizeof(arg->alpha2));
159 + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
161 + ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
162 + "set current country pdev id %d alpha2 %c%c\n",
168 + ath12k_warn(ar->ab,
169 + "failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
170 + dev_kfree_skb(skb);
176 +int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
177 + struct wmi_11d_scan_start_arg *arg)
179 + struct ath12k_wmi_pdev *wmi = ar->wmi;
180 + struct wmi_11d_scan_start_cmd *cmd;
181 + struct sk_buff *skb;
184 + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
188 + cmd = (struct wmi_11d_scan_start_cmd *)skb->data;
190 + ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_START_CMD,
193 + cmd->vdev_id = cpu_to_le32(arg->vdev_id);
194 + cmd->scan_period_msec = cpu_to_le32(arg->scan_period_msec);
195 + cmd->start_interval_msec = cpu_to_le32(arg->start_interval_msec);
196 + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
198 + ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
199 + "send 11d scan start vdev id %d period %d ms internal %d ms\n",
200 + arg->vdev_id, arg->scan_period_msec,
201 + arg->start_interval_msec);
204 + ath12k_warn(ar->ab,
205 + "failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
206 + dev_kfree_skb(skb);
212 +int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id)
214 + struct ath12k_wmi_pdev *wmi = ar->wmi;
215 + struct wmi_11d_scan_stop_cmd *cmd;
216 + struct sk_buff *skb;
219 + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
223 + cmd = (struct wmi_11d_scan_stop_cmd *)skb->data;
225 + ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_STOP_CMD,
228 + cmd->vdev_id = cpu_to_le32(vdev_id);
229 + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
231 + ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
232 + "send 11d scan stop vdev id %d\n",
236 + ath12k_warn(ar->ab,
237 + "failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
238 + dev_kfree_skb(skb);
245 ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id)
247 @@ -5668,6 +5777,50 @@ static void ath12k_wmi_op_ep_tx_credits(
248 wake_up(&ab->wmi_ab.tx_credits_wq);
251 +static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *skb)
253 + const struct wmi_11d_new_cc_event *ev;
255 + struct ath12k_pdev *pdev;
259 + tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
262 + ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
266 + ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
269 + ath12k_warn(ab, "failed to fetch 11d new cc ev");
273 + spin_lock_bh(&ab->base_lock);
274 + memcpy(&ab->new_alpha2, &ev->new_alpha2, REG_ALPHA2_LEN);
275 + spin_unlock_bh(&ab->base_lock);
277 + ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi 11d new cc %c%c\n",
279 + ab->new_alpha2[1]);
283 + for (i = 0; i < ab->num_radios; i++) {
284 + pdev = &ab->pdevs[i];
286 + ar->state_11d = ATH12K_11D_IDLE;
287 + complete(&ar->completed_11d_scan);
290 + queue_work(ab->workqueue, &ab->update_11d_work);
295 static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
298 @@ -7269,6 +7422,9 @@ static void ath12k_wmi_op_rx(struct ath1
299 case WMI_GTK_OFFLOAD_STATUS_EVENTID:
300 ath12k_wmi_gtk_offload_status_event(ab, skb);
302 + case WMI_11D_NEW_COUNTRY_EVENTID:
303 + ath12k_reg_11d_new_cc_event(ab, skb);
305 /* TODO: Add remaining events */
307 ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
308 --- a/drivers/net/wireless/ath/ath12k/wmi.h
309 +++ b/drivers/net/wireless/ath/ath12k/wmi.h
310 @@ -3859,6 +3859,28 @@ struct wmi_init_country_cmd {
314 +struct wmi_11d_scan_start_arg {
316 + u32 scan_period_msec;
317 + u32 start_interval_msec;
320 +struct wmi_11d_scan_start_cmd {
323 + __le32 scan_period_msec;
324 + __le32 start_interval_msec;
327 +struct wmi_11d_scan_stop_cmd {
332 +struct wmi_11d_new_cc_event {
336 struct wmi_delba_send_cmd {
339 @@ -3944,6 +3966,16 @@ struct ath12k_wmi_eht_rate_set_params {
340 #define MAX_6G_REG_RULES 5
341 #define REG_US_5G_NUM_REG_RULES 4
343 +struct wmi_set_current_country_arg {
344 + u8 alpha2[REG_ALPHA2_LEN];
347 +struct wmi_set_current_country_cmd {
353 enum wmi_start_event_param {
354 WMI_VDEV_START_RESP_EVENT = 0,
355 WMI_VDEV_RESTART_RESP_EVENT,
356 @@ -5546,11 +5578,17 @@ int ath12k_wmi_send_bcn_offload_control_
357 u32 vdev_id, u32 bcn_ctrl_op);
358 int ath12k_wmi_send_init_country_cmd(struct ath12k *ar,
359 struct ath12k_wmi_init_country_arg *arg);
361 +ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
362 + struct wmi_set_current_country_arg *arg);
363 int ath12k_wmi_peer_rx_reorder_queue_setup(struct ath12k *ar,
364 int vdev_id, const u8 *addr,
365 dma_addr_t paddr, u8 tid,
366 u8 ba_window_size_valid,
368 +int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
369 + struct wmi_11d_scan_start_arg *arg);
370 +int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id);
372 ath12k_wmi_rx_reord_queue_remove(struct ath12k *ar,
373 struct ath12k_wmi_rx_reorder_queue_remove_arg *arg);
374 --- a/drivers/net/wireless/ath/ath12k/core.c
375 +++ b/drivers/net/wireless/ath/ath12k/core.c
376 @@ -1014,6 +1014,7 @@ void ath12k_core_halt(struct ath12k *ar)
377 cancel_delayed_work_sync(&ar->scan.timeout);
378 cancel_work_sync(&ar->regd_update_work);
379 cancel_work_sync(&ab->rfkill_work);
380 + cancel_work_sync(&ab->update_11d_work);
382 rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
384 @@ -1021,6 +1022,34 @@ void ath12k_core_halt(struct ath12k *ar)
385 idr_init(&ar->txmgmt_idr);
388 +static void ath12k_update_11d(struct work_struct *work)
390 + struct ath12k_base *ab = container_of(work, struct ath12k_base, update_11d_work);
392 + struct ath12k_pdev *pdev;
393 + struct wmi_set_current_country_arg arg = {};
396 + spin_lock_bh(&ab->base_lock);
397 + memcpy(&arg.alpha2, &ab->new_alpha2, 2);
398 + spin_unlock_bh(&ab->base_lock);
400 + ath12k_dbg(ab, ATH12K_DBG_WMI, "update 11d new cc %c%c\n",
401 + arg.alpha2[0], arg.alpha2[1]);
403 + for (i = 0; i < ab->num_radios; i++) {
404 + pdev = &ab->pdevs[i];
407 + memcpy(&ar->alpha2, &arg.alpha2, 2);
408 + ret = ath12k_wmi_send_set_current_country_cmd(ar, &arg);
410 + ath12k_warn(ar->ab,
411 + "pdev id %d failed set current country code: %d\n",
416 static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
419 @@ -1045,8 +1074,10 @@ static void ath12k_core_pre_reconfigure_
422 ath12k_mac_drain_tx(ar);
423 + ar->state_11d = ATH12K_11D_IDLE;
424 + complete(&ar->completed_11d_scan);
425 complete(&ar->scan.started);
426 - complete(&ar->scan.completed);
427 + complete_all(&ar->scan.completed);
428 complete(&ar->scan.on_channel);
429 complete(&ar->peer_assoc_done);
430 complete(&ar->peer_delete_done);
431 @@ -1312,6 +1343,7 @@ struct ath12k_base *ath12k_core_alloc(st
432 INIT_WORK(&ab->restart_work, ath12k_core_restart);
433 INIT_WORK(&ab->reset_work, ath12k_core_reset);
434 INIT_WORK(&ab->rfkill_work, ath12k_rfkill_work);
435 + INIT_WORK(&ab->update_11d_work, ath12k_update_11d);
437 timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
438 init_completion(&ab->htc_suspend);
439 --- a/drivers/net/wireless/ath/ath12k/core.h
440 +++ b/drivers/net/wireless/ath/ath12k/core.h
441 @@ -199,6 +199,12 @@ enum ath12k_scan_state {
442 ATH12K_SCAN_ABORTING,
445 +enum ath12k_11d_state {
447 + ATH12K_11D_PREPARING,
448 + ATH12K_11D_RUNNING,
451 enum ath12k_dev_flags {
453 ATH12K_FLAG_CRASH_FLUSH,
454 @@ -313,6 +319,8 @@ struct ath12k_vif_iter {
455 #define ATH12K_RX_RATE_TABLE_11AX_NUM 576
456 #define ATH12K_RX_RATE_TABLE_NUM 320
458 +#define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
460 struct ath12k_rx_peer_rate_stats {
461 u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
462 u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
463 @@ -648,6 +656,13 @@ struct ath12k {
467 + /* Protected by wiphy::mtx lock. */
468 + u32 vdev_id_11d_scan;
469 + struct completion completed_11d_scan;
470 + enum ath12k_11d_state state_11d;
471 + u8 alpha2[REG_ALPHA2_LEN];
472 + bool regdom_set_by_user;
477 @@ -880,6 +895,8 @@ struct ath12k_base {
478 /* continuous recovery fail count */
479 atomic_t fail_cont_count;
480 unsigned long reset_fail_timeout;
481 + struct work_struct update_11d_work;
484 /* protected by data_lock */
485 u32 fw_crash_counter;
486 --- a/drivers/net/wireless/ath/ath12k/mac.c
487 +++ b/drivers/net/wireless/ath/ath12k/mac.c
488 @@ -2947,6 +2947,11 @@ static void ath12k_bss_assoc(struct ath1
490 ath12k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
491 arvif->vdev_id, ret);
493 + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map) &&
494 + arvif->vdev_type == WMI_VDEV_TYPE_STA &&
495 + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
496 + ath12k_mac_11d_scan_stop_all(ar->ab);
499 static void ath12k_bss_disassoc(struct ath12k *ar,
500 @@ -3522,7 +3527,7 @@ void __ath12k_mac_scan_finish(struct ath
501 ar->scan_channel = NULL;
502 ar->scan.roc_freq = 0;
503 cancel_delayed_work(&ar->scan.timeout);
504 - complete(&ar->scan.completed);
505 + complete_all(&ar->scan.completed);
509 @@ -3783,7 +3788,12 @@ scan:
511 ret = ath12k_start_scan(ar, &arg);
513 - ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
515 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
516 + "scan engine is busy 11d state %d\n", ar->state_11d);
518 + ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
520 spin_lock_bh(&ar->data_lock);
521 ar->scan.state = ATH12K_SCAN_IDLE;
522 spin_unlock_bh(&ar->data_lock);
523 @@ -3802,6 +3812,11 @@ exit:
525 mutex_unlock(&ar->conf_mutex);
527 + if (ar->state_11d == ATH12K_11D_PREPARING &&
528 + arvif->vdev_type == WMI_VDEV_TYPE_STA &&
529 + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
530 + ath12k_mac_11d_scan_start(ar, arvif->vdev_id);
535 @@ -5986,7 +6001,7 @@ static int ath12k_mac_start(struct ath12
537 /* TODO: Do we need to enable ANI? */
539 - ath12k_reg_update_chan_list(ar);
540 + ath12k_reg_update_chan_list(ar, false);
542 ar->num_started_vdevs = 0;
543 ar->num_created_vdevs = 0;
544 @@ -6166,6 +6181,9 @@ static void ath12k_mac_stop(struct ath12
545 cancel_delayed_work_sync(&ar->scan.timeout);
546 cancel_work_sync(&ar->regd_update_work);
547 cancel_work_sync(&ar->ab->rfkill_work);
548 + cancel_work_sync(&ar->ab->update_11d_work);
549 + ar->state_11d = ATH12K_11D_IDLE;
550 + complete(&ar->completed_11d_scan);
552 spin_lock_bh(&ar->data_lock);
553 list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
554 @@ -6412,6 +6430,117 @@ static void ath12k_mac_op_update_vif_off
555 ath12k_mac_update_vif_offload(arvif);
558 +static bool ath12k_mac_vif_ap_active_any(struct ath12k_base *ab)
561 + struct ath12k_pdev *pdev;
562 + struct ath12k_vif *arvif;
565 + for (i = 0; i < ab->num_radios; i++) {
566 + pdev = &ab->pdevs[i];
568 + list_for_each_entry(arvif, &ar->arvifs, list) {
569 + if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_AP)
576 +void ath12k_mac_11d_scan_start(struct ath12k *ar, u32 vdev_id)
578 + struct wmi_11d_scan_start_arg arg;
581 + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
583 + if (ar->regdom_set_by_user)
586 + if (ar->vdev_id_11d_scan != ATH12K_11D_INVALID_VDEV_ID)
589 + if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
592 + if (ath12k_mac_vif_ap_active_any(ar->ab))
595 + arg.vdev_id = vdev_id;
596 + arg.start_interval_msec = 0;
597 + arg.scan_period_msec = ATH12K_SCAN_11D_INTERVAL;
599 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
600 + "mac start 11d scan for vdev %d\n", vdev_id);
602 + ret = ath12k_wmi_send_11d_scan_start_cmd(ar, &arg);
604 + ath12k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n",
607 + ar->vdev_id_11d_scan = vdev_id;
608 + if (ar->state_11d == ATH12K_11D_PREPARING)
609 + ar->state_11d = ATH12K_11D_RUNNING;
613 + if (ar->state_11d == ATH12K_11D_PREPARING) {
614 + ar->state_11d = ATH12K_11D_IDLE;
615 + complete(&ar->completed_11d_scan);
619 +void ath12k_mac_11d_scan_stop(struct ath12k *ar)
624 + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
626 + if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
629 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac stop 11d for vdev %d\n",
630 + ar->vdev_id_11d_scan);
632 + if (ar->state_11d == ATH12K_11D_PREPARING) {
633 + ar->state_11d = ATH12K_11D_IDLE;
634 + complete(&ar->completed_11d_scan);
637 + if (ar->vdev_id_11d_scan != ATH12K_11D_INVALID_VDEV_ID) {
638 + vdev_id = ar->vdev_id_11d_scan;
640 + ret = ath12k_wmi_send_11d_scan_stop_cmd(ar, vdev_id);
642 + ath12k_warn(ar->ab,
643 + "failed to stopt 11d scan vdev %d ret: %d\n",
646 + ar->vdev_id_11d_scan = ATH12K_11D_INVALID_VDEV_ID;
647 + ar->state_11d = ATH12K_11D_IDLE;
648 + complete(&ar->completed_11d_scan);
653 +void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab)
656 + struct ath12k_pdev *pdev;
659 + ath12k_dbg(ab, ATH12K_DBG_MAC, "mac stop soc 11d scan\n");
661 + for (i = 0; i < ab->num_radios; i++) {
662 + pdev = &ab->pdevs[i];
665 + ath12k_mac_11d_scan_stop(ar);
669 static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
671 struct ath12k_hw *ah = ar->ah;
672 @@ -6526,6 +6655,7 @@ static int ath12k_mac_vdev_create(struct
673 arvif->vdev_id, ret);
676 + ath12k_mac_11d_scan_stop_all(ar->ab);
678 case WMI_VDEV_TYPE_STA:
679 param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
680 @@ -6564,6 +6694,13 @@ static int ath12k_mac_vdev_create(struct
681 arvif->vdev_id, ret);
685 + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
686 + arvif->vdev_type == WMI_VDEV_TYPE_STA &&
687 + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
688 + reinit_completion(&ar->completed_11d_scan);
689 + ar->state_11d = ATH12K_11D_PREPARING;
694 @@ -6904,6 +7041,11 @@ static void ath12k_mac_op_remove_interfa
695 ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
698 + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
699 + arvif->vdev_type == WMI_VDEV_TYPE_STA &&
700 + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
701 + ath12k_mac_11d_scan_stop(ar);
703 if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
704 ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
706 @@ -7744,6 +7886,14 @@ ath12k_mac_op_unassign_vif_chanctx(struc
707 ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
708 ath12k_mac_monitor_stop(ar);
710 + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
711 + arvif->vdev_type == WMI_VDEV_TYPE_STA &&
712 + arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE &&
713 + ar->state_11d != ATH12K_11D_PREPARING) {
714 + reinit_completion(&ar->completed_11d_scan);
715 + ar->state_11d = ATH12K_11D_PREPARING;
718 mutex_unlock(&ar->conf_mutex);
721 @@ -8282,6 +8432,14 @@ ath12k_mac_op_reconfig_complete(struct i
722 ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
725 + if (ar->ab->hw_params->current_cc_support &&
726 + ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
727 + struct wmi_set_current_country_arg arg = {};
729 + memcpy(&arg.alpha2, ar->alpha2, 2);
730 + ath12k_wmi_send_set_current_country_cmd(ar, &arg);
734 recovery_count = atomic_inc_return(&ab->recovery_count);
736 @@ -9331,6 +9489,9 @@ static void ath12k_mac_setup(struct ath1
738 INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
739 skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
741 + ar->vdev_id_11d_scan = ATH12K_11D_INVALID_VDEV_ID;
742 + init_completion(&ar->completed_11d_scan);
745 int ath12k_mac_register(struct ath12k_base *ab)
746 --- a/drivers/net/wireless/ath/ath12k/mac.h
747 +++ b/drivers/net/wireless/ath/ath12k/mac.h
748 @@ -51,6 +51,13 @@ enum ath12k_supported_bw {
750 extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
752 +#define ATH12K_SCAN_11D_INTERVAL 600000
753 +#define ATH12K_11D_INVALID_VDEV_ID 0xFFFF
755 +void ath12k_mac_11d_scan_start(struct ath12k *ar, u32 vdev_id);
756 +void ath12k_mac_11d_scan_stop(struct ath12k *ar);
757 +void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab);
759 void ath12k_mac_destroy(struct ath12k_base *ab);
760 void ath12k_mac_unregister(struct ath12k_base *ab);
761 int ath12k_mac_register(struct ath12k_base *ab);
762 --- a/drivers/net/wireless/ath/ath12k/reg.c
763 +++ b/drivers/net/wireless/ath/ath12k/reg.c
764 @@ -48,6 +48,7 @@ ath12k_reg_notifier(struct wiphy *wiphy,
766 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
767 struct ath12k_wmi_init_country_arg arg;
768 + struct wmi_set_current_country_arg current_arg = {};
769 struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
770 struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
772 @@ -77,27 +78,38 @@ ath12k_reg_notifier(struct wiphy *wiphy,
776 - /* Set the country code to the firmware and wait for
777 - * the WMI_REG_CHAN_LIST_CC EVENT for updating the
780 - arg.flags = ALPHA_IS_SET;
781 - memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
782 - arg.cc_info.alpha2[2] = 0;
784 /* Allow fresh updates to wiphy regd */
785 ah->regd_updated = false;
787 /* Send the reg change request to all the radios */
788 for_each_ar(ah, ar, i) {
789 - ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
791 - ath12k_warn(ar->ab,
792 - "INIT Country code set to fw failed : %d\n", ret);
793 + if (ar->ab->hw_params->current_cc_support) {
794 + memcpy(¤t_arg.alpha2, request->alpha2, 2);
795 + memcpy(&ar->alpha2, ¤t_arg.alpha2, 2);
796 + ret = ath12k_wmi_send_set_current_country_cmd(ar, ¤t_arg);
798 + ath12k_warn(ar->ab,
799 + "failed set current country code: %d\n", ret);
801 + arg.flags = ALPHA_IS_SET;
802 + memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
803 + arg.cc_info.alpha2[2] = 0;
805 + ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
807 + ath12k_warn(ar->ab,
808 + "failed set INIT Country code: %d\n", ret);
812 + ath12k_mac_11d_scan_stop(ar);
813 + wiphy_unlock(wiphy);
815 + ar->regdom_set_by_user = true;
819 -int ath12k_reg_update_chan_list(struct ath12k *ar)
820 +int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
822 struct ieee80211_supported_band **bands;
823 struct ath12k_wmi_scan_chan_list_arg *arg;
824 @@ -106,7 +118,35 @@ int ath12k_reg_update_chan_list(struct a
825 struct ath12k_wmi_channel_arg *ch;
826 enum nl80211_band band;
827 int num_channels = 0;
831 + if (wait && ar->state_11d != ATH12K_11D_IDLE) {
832 + left = wait_for_completion_timeout(&ar->completed_11d_scan,
833 + ATH12K_SCAN_TIMEOUT_HZ);
835 + ath12k_dbg(ar->ab, ATH12K_DBG_REG,
836 + "failed to receive 11d scan complete: timed out\n");
837 + ar->state_11d = ATH12K_11D_IDLE;
839 + ath12k_dbg(ar->ab, ATH12K_DBG_REG,
840 + "reg 11d scan wait left time %d\n", left);
844 + (ar->scan.state == ATH12K_SCAN_STARTING ||
845 + ar->scan.state == ATH12K_SCAN_RUNNING)) {
846 + left = wait_for_completion_timeout(&ar->scan.completed,
847 + ATH12K_SCAN_TIMEOUT_HZ);
849 + ath12k_dbg(ar->ab, ATH12K_DBG_REG,
850 + "failed to receive hw scan complete: timed out\n");
852 + ath12k_dbg(ar->ab, ATH12K_DBG_REG,
853 + "reg hw scan wait left time %d\n", left);
856 + if (ar->ah->state == ATH12K_HW_STATE_RESTARTING)
859 bands = hw->wiphy->bands;
860 for (band = 0; band < NUM_NL80211_BANDS; band++) {
861 @@ -295,7 +335,7 @@ int ath12k_regd_update(struct ath12k *ar
863 for_each_ar(ah, ar, i) {
865 - ret = ath12k_reg_update_chan_list(ar);
866 + ret = ath12k_reg_update_chan_list(ar, true);
870 --- a/drivers/net/wireless/ath/ath12k/reg.h
871 +++ b/drivers/net/wireless/ath/ath12k/reg.h
873 /* SPDX-License-Identifier: BSD-3-Clause-Clear */
875 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
876 - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
877 + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
881 @@ -96,6 +96,6 @@ struct ieee80211_regdomain *ath12k_reg_b
882 struct ath12k_reg_info *reg_info,
884 int ath12k_regd_update(struct ath12k *ar, bool init);
885 -int ath12k_reg_update_chan_list(struct ath12k *ar);
886 +int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait);
889 --- a/drivers/net/wireless/ath/ath12k/hw.c
890 +++ b/drivers/net/wireless/ath/ath12k/hw.c
891 @@ -926,6 +926,7 @@ static const struct ath12k_hw_params ath
892 .supports_dynamic_smps_6ghz = true,
895 + .current_cc_support = false,
898 .name = "wcn7850 hw2.0",
899 @@ -1004,6 +1005,7 @@ static const struct ath12k_hw_params ath
900 .supports_dynamic_smps_6ghz = false,
902 .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
903 + .current_cc_support = true,
906 .name = "qcn9274 hw2.0",
907 @@ -1078,6 +1080,7 @@ static const struct ath12k_hw_params ath
908 .supports_dynamic_smps_6ghz = true,
911 + .current_cc_support = false,
915 --- a/drivers/net/wireless/ath/ath12k/hw.h
916 +++ b/drivers/net/wireless/ath/ath12k/hw.h
917 @@ -189,6 +189,7 @@ struct ath12k_hw_params {
918 bool tcl_ring_retry:1;
919 bool reoq_lut_support:1;
920 bool supports_shadow_regs:1;
921 + bool current_cc_support:1;