1 /*
2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 *
6 * Permission to use, copy, modify, and/or distribute this software for
7 * any purpose with or without fee is hereby granted, provided that the
8 * above copyright notice and this permission notice appear in all
9 * copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18 * PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 /**
22 * DOC: target_if_dfs_partial_offload.c
23 * This file contains dfs target interface for partial offload
24 */
25
26 #include <target_if.h>
27 #include "target_type.h"
28 #include "target_if_dfs_partial_offload.h"
29 #include "target_if_dfs.h"
30
target_if_dfs_reg_phyerr_events(struct wlan_objmgr_psoc * psoc)31 QDF_STATUS target_if_dfs_reg_phyerr_events(struct wlan_objmgr_psoc *psoc)
32 {
33 /* TODO: dfs non-offload case */
34 return QDF_STATUS_SUCCESS;
35 }
36
target_if_dfs_get_caps(struct wlan_objmgr_pdev * pdev,struct wlan_dfs_caps * dfs_caps)37 QDF_STATUS target_if_dfs_get_caps(struct wlan_objmgr_pdev *pdev,
38 struct wlan_dfs_caps *dfs_caps)
39 {
40 struct wlan_objmgr_psoc *psoc = NULL;
41 struct target_psoc_info *tgt_psoc_info;
42
43 if (!dfs_caps) {
44 target_if_err("null dfs_caps");
45 return QDF_STATUS_E_FAILURE;
46 }
47
48 dfs_caps->wlan_dfs_combined_rssi_ok = 0;
49 dfs_caps->wlan_dfs_ext_chan_ok = 0;
50 dfs_caps->wlan_dfs_use_enhancement = 0;
51 dfs_caps->wlan_strong_signal_diversiry = 0;
52 dfs_caps->wlan_fastdiv_val = 0;
53 dfs_caps->wlan_chip_is_bb_tlv = 1;
54 dfs_caps->wlan_chip_is_over_sampled = 0;
55 dfs_caps->wlan_chip_is_ht160 = 0;
56 dfs_caps->wlan_chip_is_false_detect = 0;
57
58 psoc = wlan_pdev_get_psoc(pdev);
59 if (!psoc) {
60 target_if_err("null psoc");
61 return QDF_STATUS_E_FAILURE;
62 }
63
64 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
65 if (!tgt_psoc_info) {
66 target_if_err("null tgt_psoc_info");
67 return QDF_STATUS_E_FAILURE;
68 }
69
70 switch (target_psoc_get_target_type(tgt_psoc_info)) {
71 case TARGET_TYPE_AR900B:
72 break;
73
74 case TARGET_TYPE_AR9888:
75 dfs_caps->wlan_chip_is_over_sampled = 1;
76 break;
77
78 case TARGET_TYPE_QCA9984:
79 case TARGET_TYPE_QCA9888:
80 dfs_caps->wlan_chip_is_ht160 = 1;
81 break;
82 default:
83 break;
84 }
85
86 return QDF_STATUS_SUCCESS;
87 }
88
89 #if defined(HOST_DFS_SPOOF_TEST)
target_if_dfs_send_avg_params_to_fw(struct wlan_objmgr_pdev * pdev,struct dfs_radar_found_params * params)90 QDF_STATUS target_if_dfs_send_avg_params_to_fw(
91 struct wlan_objmgr_pdev *pdev,
92 struct dfs_radar_found_params *params)
93 {
94 QDF_STATUS status;
95 wmi_unified_t wmi_handle;
96
97 if (!pdev) {
98 target_if_err("null pdev");
99 return QDF_STATUS_E_FAILURE;
100 }
101
102 wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
103 if (!wmi_handle) {
104 target_if_err("null wmi_handle");
105 return QDF_STATUS_E_FAILURE;
106 }
107
108 status = wmi_unified_dfs_send_avg_params_cmd(wmi_handle,
109 params);
110 if (QDF_IS_STATUS_ERROR(status))
111 target_if_err("dfs radar found average parameters send failed: %d",
112 status);
113
114 return status;
115 }
116
target_if_dfs_status_check_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)117 int target_if_dfs_status_check_event_handler(ol_scn_t scn,
118 uint8_t *data,
119 uint32_t datalen)
120 {
121 struct wlan_objmgr_psoc *psoc;
122 struct wlan_objmgr_pdev *pdev;
123 struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
124 u_int32_t dfs_status_check;
125 wmi_unified_t wmi_hdl;
126
127 if (!scn || !data) {
128 target_if_err("scn: %pK, data: %pK", scn, data);
129 return -EINVAL;
130 }
131
132 psoc = target_if_get_psoc_from_scn_hdl(scn);
133 if (!psoc) {
134 target_if_err("null psoc");
135 return -EINVAL;
136 }
137
138 /* Since Partial Offload chipsets have only one pdev per psoc, the first
139 * pdev from the pdev list is used.
140 */
141 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_DFS_ID);
142 if (!pdev) {
143 target_if_err("null pdev");
144 return -EINVAL;
145 }
146
147 dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
148 if (!dfs_rx_ops) {
149 target_if_err("null dfs_rx_ops");
150 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
151 return -EINVAL;
152 }
153
154 if (!dfs_rx_ops->dfs_action_on_status) {
155 target_if_err("dfs_rx_ops->dfs_action_on_status is NULL");
156 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
157 return -EINVAL;
158 }
159
160 wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev);
161 if (!wmi_hdl) {
162 target_if_err("wmi_hdl is NULL");
163 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
164 return -EINVAL;
165 }
166
167 if (wmi_extract_dfs_status_from_fw(wmi_hdl, data, &dfs_status_check) !=
168 QDF_STATUS_SUCCESS) {
169 target_if_err("failed to extract status response from FW");
170 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
171 return -EINVAL;
172 }
173
174 if (dfs_rx_ops->dfs_action_on_status(pdev, &dfs_status_check) !=
175 QDF_STATUS_SUCCESS) {
176 target_if_err("dfs action on host dfs status from FW failed");
177 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
178 return -EINVAL;
179 }
180
181 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
182
183 return 0;
184 }
185 #endif
186