xref: /wlan-dirver/qca-wifi-host-cmn/target_if/dcs/src/target_if_dcs.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: target_if_dcs.c
19  *
20  * This file provide definition for APIs registered through lmac Tx Ops
21  */
22 
23 #include <wmi_unified_api.h>
24 #include <wmi_unified_priv.h>
25 #include <wmi_unified_dcs_api.h>
26 #include <init_deinit_lmac.h>
27 #include "wlan_dcs_tgt_api.h"
28 #include "target_if_dcs.h"
29 
30 /**
31  * target_if_dcs_interference_event_handler() - function to handle dcs event
32  * from firmware.
33  * @scn: scn handle
34  * @data: data buffer for event
35  * @datalen: data length
36  *
37  * Return: status of operation.
38  */
39 static int target_if_dcs_interference_event_handler(ol_scn_t scn,
40 						    uint8_t *data,
41 						    uint32_t datalen)
42 {
43 	QDF_STATUS status;
44 	struct dcs_stats_event ev;
45 	struct wlan_objmgr_psoc *psoc;
46 	struct wmi_unified *wmi_handle;
47 	struct wlan_target_if_dcs_rx_ops *rx_ops;
48 
49 	if (!scn || !data) {
50 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
51 		return -EINVAL;
52 	}
53 	psoc = target_if_get_psoc_from_scn_hdl(scn);
54 	if (!psoc) {
55 		target_if_err("null psoc");
56 		return -EINVAL;
57 	}
58 
59 	rx_ops = target_if_dcs_get_rx_ops(psoc);
60 	if (!rx_ops || !rx_ops->process_dcs_event) {
61 		target_if_err("callback not registered");
62 		return -EINVAL;
63 	}
64 
65 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
66 	if (!wmi_handle) {
67 		target_if_err("wmi_handle is null");
68 		return -EINVAL;
69 	}
70 
71 	if (wmi_extract_dcs_interference_type(wmi_handle, data,
72 					      &ev.dcs_param) !=
73 						QDF_STATUS_SUCCESS) {
74 		target_if_err("Unable to extract dcs interference type");
75 		return -EINVAL;
76 	}
77 
78 	if (wmi_extract_dcs_im_tgt_stats(wmi_handle, data, &ev.wlan_stat) !=
79 							QDF_STATUS_SUCCESS) {
80 		target_if_err("Unable to extract WLAN IM stats");
81 		return -EINVAL;
82 	}
83 
84 	status = rx_ops->process_dcs_event(psoc, &ev);
85 
86 	return qdf_status_to_os_return(status);
87 }
88 
89 static QDF_STATUS
90 target_if_dcs_register_event_handler(struct wlan_objmgr_psoc *psoc)
91 {
92 	QDF_STATUS ret_val;
93 	struct wmi_unified *wmi_handle;
94 
95 	if (!psoc) {
96 		target_if_err("PSOC is NULL!");
97 		return QDF_STATUS_E_NULL_VALUE;
98 	}
99 
100 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
101 	if (!wmi_handle) {
102 		target_if_err("wmi_handle is null");
103 		return QDF_STATUS_E_INVAL;
104 	}
105 
106 	ret_val = wmi_unified_register_event_handler(
107 			wmi_handle,
108 			wmi_dcs_interference_event_id,
109 			target_if_dcs_interference_event_handler,
110 			WMI_RX_WORK_CTX);
111 	if (QDF_IS_STATUS_ERROR(ret_val))
112 		target_if_err("Failed to register dcs interference event cb");
113 
114 	return ret_val;
115 }
116 
117 static QDF_STATUS
118 target_if_dcs_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
119 {
120 	struct wmi_unified *wmi_handle;
121 
122 	if (!psoc) {
123 		target_if_err("PSOC is NULL!");
124 		return QDF_STATUS_E_INVAL;
125 	}
126 
127 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
128 	if (!wmi_handle) {
129 		target_if_err("wmi_handle is null");
130 		return QDF_STATUS_E_INVAL;
131 	}
132 	wmi_unified_unregister_event_handler(wmi_handle,
133 					     wmi_dcs_interference_event_id);
134 
135 	return QDF_STATUS_SUCCESS;
136 }
137 
138 /**
139  * target_if_dcs_cmd_send() - Send WMI command for dcs requests
140  * @psoc: psoc pointer
141  * @pdev_id: pdev_id
142  * @is_host_pdev_id: pdev_id is host pdev_id or not
143  * @dcs_enable: dcs enable or not
144  *
145  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
146  */
147 static QDF_STATUS
148 target_if_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id,
149 		       bool is_host_pdev_id, uint32_t dcs_enable)
150 {
151 	QDF_STATUS ret;
152 	struct wmi_unified *wmi_handle;
153 
154 	if (!psoc) {
155 		target_if_err("null psoc");
156 		return QDF_STATUS_E_FAILURE;
157 	}
158 
159 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
160 	if (!wmi_handle) {
161 		target_if_err("null handle");
162 		return QDF_STATUS_E_FAILURE;
163 	}
164 
165 	ret = wmi_send_dcs_pdev_param(wmi_handle, pdev_id,
166 				      is_host_pdev_id, dcs_enable);
167 	if (QDF_IS_STATUS_ERROR(ret))
168 		target_if_err("wmi dcs cmd send failed, ret: %d", ret);
169 
170 	return ret;
171 }
172 
173 QDF_STATUS
174 target_if_dcs_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
175 {
176 	struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
177 
178 	if (!tx_ops) {
179 		target_if_err("lmac tx ops is NULL!");
180 		return QDF_STATUS_E_INVAL;
181 	}
182 
183 	dcs_tx_ops = &tx_ops->dcs_tx_ops;
184 	if (!dcs_tx_ops) {
185 		target_if_err("lmac tx ops is NULL!");
186 		return QDF_STATUS_E_FAILURE;
187 	}
188 
189 	dcs_tx_ops->dcs_attach =
190 		target_if_dcs_register_event_handler;
191 	dcs_tx_ops->dcs_detach =
192 		target_if_dcs_unregister_event_handler;
193 	dcs_tx_ops->dcs_cmd_send = target_if_dcs_cmd_send;
194 
195 	return QDF_STATUS_SUCCESS;
196 }
197 
198