1 /*
2  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 #include <target_if_spatial_reuse.h>
20 #include <wlan_lmac_if_def.h>
21 #include <wmi_unified_api.h>
22 #include <wmi_unified_vdev_api.h>
23 #include <target_if_vdev_mgr_tx_ops.h>
24 #include <init_deinit_lmac.h>
25 #include <wlan_vdev_mlme_api.h>
26 
spatial_reuse_send_cfg(struct wlan_objmgr_vdev * vdev,uint8_t sr_ctrl,uint8_t non_srg_max_pd_offset)27 static QDF_STATUS spatial_reuse_send_cfg(struct wlan_objmgr_vdev *vdev,
28 					 uint8_t sr_ctrl,
29 					 uint8_t non_srg_max_pd_offset)
30 {
31 	struct pdev_params pparam;
32 	wmi_unified_t wmi_handle;
33 
34 	wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev);
35 	if (!wmi_handle) {
36 		mlme_err("Failed to get WMI handle!");
37 		return QDF_STATUS_E_INVAL;
38 	}
39 
40 	qdf_mem_zero(&pparam, sizeof(pparam));
41 	pparam.param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD;
42 	if (!(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
43 	    (sr_ctrl & NON_SRG_OFFSET_PRESENT)) {
44 		QDF_SET_BITS(pparam.param_value, NON_SRG_SPR_ENABLE_POS,
45 			     NON_SRG_SPR_ENABLE_SIZE, NON_SRG_SPR_ENABLE);
46 		QDF_SET_BITS(pparam.param_value, SR_PARAM_VAL_DBM_POS,
47 			     NON_SRG_PARAM_VAL_DBM_SIZE,
48 			     SR_PARAM_VAL_DBM_UNIT);
49 		QDF_SET_BITS(pparam.param_value, NON_SRG_MAX_PD_OFFSET_POS,
50 			     NON_SRG_MAX_PD_OFFSET_SIZE,
51 			     non_srg_max_pd_offset);
52 	}
53 
54 	return wmi_unified_pdev_param_send(wmi_handle, &pparam,
55 					   WILDCARD_PDEV_ID);
56 }
57 
58 static QDF_STATUS
spatial_reuse_send_sr_prohibit_cfg(struct wlan_objmgr_vdev * vdev,bool he_siga_va15_allowed)59 spatial_reuse_send_sr_prohibit_cfg(struct wlan_objmgr_vdev *vdev,
60 				   bool he_siga_va15_allowed)
61 {
62 	struct sr_prohibit_param srp_param;
63 	wmi_unified_t wmi_handle;
64 
65 	wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev);
66 	if (!wmi_handle) {
67 		mlme_err("Failed to get WMI handle!");
68 		return QDF_STATUS_E_INVAL;
69 	}
70 
71 	srp_param.vdev_id = wlan_vdev_get_id(vdev);
72 	srp_param.sr_he_siga_val15_allowed = he_siga_va15_allowed;
73 
74 	return wmi_unified_vdev_param_sr_prohibit_send(wmi_handle, &srp_param);
75 }
76 
77 #ifdef OBSS_PD
78 static QDF_STATUS
spatial_reuse_send_bss_color_bit_map(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_pdev * pdev)79 spatial_reuse_send_bss_color_bit_map(struct wlan_objmgr_vdev *vdev,
80 				     struct wlan_objmgr_pdev *pdev)
81 {
82 	uint64_t srg_color_bit_map = 0;
83 	uint32_t bit_map_0 = 0;
84 	uint32_t bit_map_1 = 0;
85 	struct wmi_unified *wmi_handle;
86 	QDF_STATUS status = QDF_STATUS_SUCCESS;
87 
88 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
89 	if (!wmi_handle)
90 		return QDF_STATUS_E_INVAL;
91 
92 	wlan_vdev_obj_lock(vdev);
93 	wlan_vdev_mlme_get_srg_bss_color_bit_map(vdev, &srg_color_bit_map);
94 	wlan_vdev_obj_unlock(vdev);
95 	bit_map_0 = (uint32_t) srg_color_bit_map;
96 	bit_map_1 = (uint32_t) (srg_color_bit_map >> 32);
97 
98 	status = wmi_unified_send_self_srg_bss_color_bitmap_set_cmd(
99 					wmi_handle, bit_map_0, bit_map_1,
100 					pdev->pdev_objmgr.wlan_pdev_id);
101 	return status;
102 }
103 
104 static QDF_STATUS
spatial_reuse_send_partial_bssid_bit_map(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_pdev * pdev)105 spatial_reuse_send_partial_bssid_bit_map(struct wlan_objmgr_vdev *vdev,
106 					 struct wlan_objmgr_pdev *pdev)
107 {
108 	uint64_t partial_bssid_bit_map = 0;
109 	uint32_t bit_map_0 = 0;
110 	uint32_t bit_map_1 = 0;
111 	struct wmi_unified *wmi_handle;
112 	QDF_STATUS status = QDF_STATUS_SUCCESS;
113 
114 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
115 	if (!wmi_handle)
116 		return QDF_STATUS_E_INVAL;
117 
118 	wlan_vdev_obj_lock(vdev);
119 	wlan_vdev_mlme_get_srg_partial_bssid_bit_map(vdev,
120 						     &partial_bssid_bit_map);
121 	wlan_vdev_obj_unlock(vdev);
122 	bit_map_0 = (uint32_t) partial_bssid_bit_map;
123 	bit_map_1 = (uint32_t) (partial_bssid_bit_map >> 32);
124 
125 	status = wmi_unified_send_self_srg_partial_bssid_bitmap_set_cmd(
126 					wmi_handle, bit_map_0, bit_map_1,
127 					pdev->pdev_objmgr.wlan_pdev_id);
128 	return status;
129 }
130 #else
131 static QDF_STATUS
spatial_reuse_send_bss_color_bit_map(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_pdev * pdev)132 spatial_reuse_send_bss_color_bit_map(struct wlan_objmgr_vdev *vdev,
133 				     struct wlan_objmgr_pdev *pdev)
134 {
135 	return QDF_STATUS_SUCCESS;
136 }
137 
138 static QDF_STATUS
spatial_reuse_send_partial_bssid_bit_map(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_pdev * pdev)139 spatial_reuse_send_partial_bssid_bit_map(struct wlan_objmgr_vdev *vdev,
140 					 struct wlan_objmgr_pdev *pdev)
141 {
142 	return QDF_STATUS_SUCCESS;
143 }
144 #endif
145 
146 static QDF_STATUS
spatial_reuse_send_pd_threshold(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,uint32_t val)147 spatial_reuse_send_pd_threshold(struct wlan_objmgr_pdev *pdev,
148 				uint8_t vdev_id,
149 				uint32_t val)
150 {
151 	struct vdev_set_params vdev_param;
152 	struct wmi_unified *wmi_handle;
153 	bool sr_supported;
154 
155 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
156 	if (!wmi_handle)
157 		return QDF_STATUS_E_INVAL;
158 
159 	sr_supported =
160 		wmi_service_enabled(wmi_handle,
161 				    wmi_service_srg_srp_spatial_reuse_support);
162 
163 	if (sr_supported) {
164 		qdf_mem_zero(&vdev_param, sizeof(vdev_param));
165 		vdev_param.vdev_id = vdev_id;
166 		vdev_param.param_id = wmi_vdev_param_set_cmd_obss_pd_threshold;
167 		vdev_param.param_value = val;
168 		return wmi_unified_vdev_set_param_send(wmi_handle, &vdev_param);
169 	} else {
170 		mlme_debug("Target doesn't support SR operations");
171 	}
172 	return QDF_STATUS_SUCCESS;
173 }
174 
175 /**
176  * spatial_reuse_set_sr_enable_disable: To send wmi command to enable/disable SR
177  * @vdev: object manager vdev
178  * @pdev: object manager pdev
179  * @is_sr_enable: sr enable/disable
180  * @srg_pd_threshold: SRG pd threshold
181  * @non_srg_pd_threshold: NON-SRG pd threshold
182  *
183  * Return: Success/Failure
184  */
185 static QDF_STATUS
spatial_reuse_set_sr_enable_disable(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_pdev * pdev,bool is_sr_enable,int32_t srg_pd_threshold,int32_t non_srg_pd_threshold)186 spatial_reuse_set_sr_enable_disable(struct wlan_objmgr_vdev *vdev,
187 				    struct wlan_objmgr_pdev *pdev,
188 				    bool is_sr_enable, int32_t srg_pd_threshold,
189 				    int32_t non_srg_pd_threshold)
190 {
191 	uint32_t val = 0;
192 	struct wlan_objmgr_psoc *psoc;
193 	QDF_STATUS status = QDF_STATUS_SUCCESS;
194 
195 	psoc = wlan_pdev_get_psoc(pdev);
196 	if (!psoc)
197 		return QDF_STATUS_E_NOENT;
198 
199 	if (is_sr_enable) {
200 		wlan_mlme_update_sr_data(vdev, &val, srg_pd_threshold,
201 					 non_srg_pd_threshold,
202 					 is_sr_enable);
203 		wlan_vdev_obj_lock(vdev);
204 		wlan_vdev_mlme_set_he_spr_enabled(vdev, true);
205 		wlan_vdev_obj_unlock(vdev);
206 	} else {
207 		wlan_vdev_obj_lock(vdev);
208 		wlan_vdev_mlme_set_he_spr_enabled(vdev, false);
209 		wlan_vdev_obj_unlock(vdev);
210 	}
211 
212 	mlme_debug("srp param val: %x, enable: %d",
213 		   val, is_sr_enable);
214 	if (is_sr_enable) {
215 		status = spatial_reuse_send_bss_color_bit_map(vdev, pdev);
216 		if (status != QDF_STATUS_SUCCESS)
217 			return status;
218 		status = spatial_reuse_send_partial_bssid_bit_map(vdev, pdev);
219 		if (status != QDF_STATUS_SUCCESS)
220 			return status;
221 	}
222 	status = spatial_reuse_send_pd_threshold(pdev,
223 						 vdev->vdev_objmgr.vdev_id,
224 						 val);
225 	if (status != QDF_STATUS_SUCCESS)
226 		return status;
227 
228 	return status;
229 }
230 
target_if_spatial_reuse_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)231 void target_if_spatial_reuse_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
232 {
233 	tx_ops->spatial_reuse_tx_ops.send_cfg = spatial_reuse_send_cfg;
234 	tx_ops->spatial_reuse_tx_ops.send_sr_prohibit_cfg =
235 					spatial_reuse_send_sr_prohibit_cfg;
236 	tx_ops->spatial_reuse_tx_ops.target_if_set_sr_enable_disable =
237 					spatial_reuse_set_sr_enable_disable;
238 	tx_ops->spatial_reuse_tx_ops.target_if_sr_update =
239 					spatial_reuse_send_pd_threshold;
240 }
241