xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_ipa.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: wlan_hdd_ipa.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * WLAN HDD and ipa interface implementation
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name /* Include Files */
27*5113495bSYour Name #include <wlan_hdd_includes.h>
28*5113495bSYour Name #include <wlan_hdd_ipa.h>
29*5113495bSYour Name #include "wlan_policy_mgr_ucfg.h"
30*5113495bSYour Name #include "wlan_ipa_ucfg_api.h"
31*5113495bSYour Name #include <wlan_hdd_softap_tx_rx.h>
32*5113495bSYour Name #include <linux/inetdevice.h>
33*5113495bSYour Name #include <qdf_trace.h>
34*5113495bSYour Name /* Test against msm kernel version */
35*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && \
36*5113495bSYour Name 	IS_ENABLED(CONFIG_SCHED_WALT)
37*5113495bSYour Name #include <linux/sched/walt.h>
38*5113495bSYour Name #endif
39*5113495bSYour Name #include "wlan_hdd_object_manager.h"
40*5113495bSYour Name #include "wlan_dp_ucfg_api.h"
41*5113495bSYour Name 
42*5113495bSYour Name #ifdef IPA_OFFLOAD
43*5113495bSYour Name 
44*5113495bSYour Name /**
45*5113495bSYour Name  * struct hdd_ipa_connection_info - connectio info for IPA component
46*5113495bSYour Name  * @vdev_id: vdev id
47*5113495bSYour Name  * @ch_freq: channel frequency
48*5113495bSYour Name  * @ch_width: channel width
49*5113495bSYour Name  * @wlan_80211_mode: enum qca_wlan_802_11_mode
50*5113495bSYour Name  */
51*5113495bSYour Name struct hdd_ipa_connection_info {
52*5113495bSYour Name 	uint8_t vdev_id;
53*5113495bSYour Name 	qdf_freq_t ch_freq;
54*5113495bSYour Name 	enum phy_ch_width ch_width;
55*5113495bSYour Name 	enum qca_wlan_802_11_mode wlan_80211_mode;
56*5113495bSYour Name };
57*5113495bSYour Name 
58*5113495bSYour Name #if (defined(QCA_CONFIG_SMP) && defined(PF_WAKE_UP_IDLE)) ||\
59*5113495bSYour Name 	IS_ENABLED(CONFIG_SCHED_WALT)
60*5113495bSYour Name /**
61*5113495bSYour Name  * hdd_ipa_get_wake_up_idle() - Get PF_WAKE_UP_IDLE flag in the task structure
62*5113495bSYour Name  *
63*5113495bSYour Name  * Get PF_WAKE_UP_IDLE flag in the task structure
64*5113495bSYour Name  *
65*5113495bSYour Name  * Return: 1 if PF_WAKE_UP_IDLE flag is set, 0 otherwise
66*5113495bSYour Name  */
hdd_ipa_get_wake_up_idle(void)67*5113495bSYour Name static uint32_t hdd_ipa_get_wake_up_idle(void)
68*5113495bSYour Name {
69*5113495bSYour Name 	return sched_get_wake_up_idle(current);
70*5113495bSYour Name }
71*5113495bSYour Name 
72*5113495bSYour Name /**
73*5113495bSYour Name  * hdd_ipa_set_wake_up_idle() - Set PF_WAKE_UP_IDLE flag in the task structure
74*5113495bSYour Name  * @wake_up_idle: Value to set PF_WAKE_UP_IDLE flag
75*5113495bSYour Name  *
76*5113495bSYour Name  * Set PF_WAKE_UP_IDLE flag in the task structure
77*5113495bSYour Name  * This task and any task woken by this will be waken to idle CPU
78*5113495bSYour Name  *
79*5113495bSYour Name  * Return: None
80*5113495bSYour Name  */
hdd_ipa_set_wake_up_idle(bool wake_up_idle)81*5113495bSYour Name static void hdd_ipa_set_wake_up_idle(bool wake_up_idle)
82*5113495bSYour Name {
83*5113495bSYour Name 	sched_set_wake_up_idle(current, wake_up_idle);
84*5113495bSYour Name }
85*5113495bSYour Name #else
hdd_ipa_get_wake_up_idle(void)86*5113495bSYour Name static uint32_t hdd_ipa_get_wake_up_idle(void)
87*5113495bSYour Name {
88*5113495bSYour Name 	return 0;
89*5113495bSYour Name }
90*5113495bSYour Name 
hdd_ipa_set_wake_up_idle(bool wake_up_idle)91*5113495bSYour Name static void hdd_ipa_set_wake_up_idle(bool wake_up_idle)
92*5113495bSYour Name {
93*5113495bSYour Name }
94*5113495bSYour Name #endif
95*5113495bSYour Name 
96*5113495bSYour Name #ifdef QCA_CONFIG_SMP
97*5113495bSYour Name /**
98*5113495bSYour Name  * hdd_ipa_send_to_nw_stack() - Check if IPA supports NAPI
99*5113495bSYour Name  * polling during RX
100*5113495bSYour Name  * @skb : data buffer sent to network stack
101*5113495bSYour Name  *
102*5113495bSYour Name  * If IPA LAN RX supports NAPI polling mechanism use
103*5113495bSYour Name  * netif_receive_skb instead of netif_rx_ni to forward the skb
104*5113495bSYour Name  * to network stack.
105*5113495bSYour Name  *
106*5113495bSYour Name  * Return: Return value from netif_rx_ni/netif_receive_skb
107*5113495bSYour Name  */
hdd_ipa_send_to_nw_stack(qdf_nbuf_t skb)108*5113495bSYour Name static int hdd_ipa_send_to_nw_stack(qdf_nbuf_t skb)
109*5113495bSYour Name {
110*5113495bSYour Name 	int result;
111*5113495bSYour Name 
112*5113495bSYour Name 	if (qdf_ipa_get_lan_rx_napi())
113*5113495bSYour Name 		result = netif_receive_skb(skb);
114*5113495bSYour Name 	else
115*5113495bSYour Name 		result = netif_rx_ni(skb);
116*5113495bSYour Name 	return result;
117*5113495bSYour Name }
118*5113495bSYour Name #else
hdd_ipa_send_to_nw_stack(qdf_nbuf_t skb)119*5113495bSYour Name static int hdd_ipa_send_to_nw_stack(qdf_nbuf_t skb)
120*5113495bSYour Name {
121*5113495bSYour Name 	int result;
122*5113495bSYour Name 
123*5113495bSYour Name 	result = netif_rx_ni(skb);
124*5113495bSYour Name 	return result;
125*5113495bSYour Name }
126*5113495bSYour Name #endif
127*5113495bSYour Name 
128*5113495bSYour Name #ifdef QCA_CONFIG_SMP
129*5113495bSYour Name 
130*5113495bSYour Name /**
131*5113495bSYour Name  * hdd_ipa_aggregated_rx_ind() - Submit aggregated packets to the stack
132*5113495bSYour Name  * @skb: skb to be submitted to the stack
133*5113495bSYour Name  *
134*5113495bSYour Name  * For CONFIG_SMP systems, simply call netif_rx_ni.
135*5113495bSYour Name  * For non CONFIG_SMP systems call netif_rx till
136*5113495bSYour Name  * IPA_WLAN_RX_SOFTIRQ_THRESH. When threshold is reached call netif_rx_ni.
137*5113495bSYour Name  * In this manner, UDP/TCP packets are sent in an aggregated way to the stack.
138*5113495bSYour Name  * For IP/ICMP packets, simply call netif_rx_ni.
139*5113495bSYour Name  *
140*5113495bSYour Name  * Check if IPA supports NAPI polling then use netif_receive_skb
141*5113495bSYour Name  * instead of netif_rx_ni.
142*5113495bSYour Name  *
143*5113495bSYour Name  * Return: return value from the netif_rx_ni/netif_rx api.
144*5113495bSYour Name  */
hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)145*5113495bSYour Name static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
146*5113495bSYour Name {
147*5113495bSYour Name 	int ret;
148*5113495bSYour Name 
149*5113495bSYour Name 	ret =  hdd_ipa_send_to_nw_stack(skb);
150*5113495bSYour Name 	return ret;
151*5113495bSYour Name }
152*5113495bSYour Name #else
hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)153*5113495bSYour Name static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
154*5113495bSYour Name {
155*5113495bSYour Name 	struct iphdr *ip_h;
156*5113495bSYour Name 	static atomic_t softirq_mitigation_cntr =
157*5113495bSYour Name 		ATOMIC_INIT(IPA_WLAN_RX_SOFTIRQ_THRESH);
158*5113495bSYour Name 	int result;
159*5113495bSYour Name 
160*5113495bSYour Name 	ip_h = (struct iphdr *)(skb->data);
161*5113495bSYour Name 	if ((skb->protocol == htons(ETH_P_IP)) &&
162*5113495bSYour Name 		(ip_h->protocol == IPPROTO_ICMP)) {
163*5113495bSYour Name 		result = hdd_ipa_send_to_nw_stack(skb);
164*5113495bSYour Name 	} else {
165*5113495bSYour Name 		/* Call netif_rx_ni for every IPA_WLAN_RX_SOFTIRQ_THRESH packets
166*5113495bSYour Name 		 * to avoid excessive softirq's.
167*5113495bSYour Name 		 */
168*5113495bSYour Name 		if (atomic_dec_and_test(&softirq_mitigation_cntr)) {
169*5113495bSYour Name 			result = hdd_ipa_send_to_nw_stack(skb);
170*5113495bSYour Name 			atomic_set(&softirq_mitigation_cntr,
171*5113495bSYour Name 					IPA_WLAN_RX_SOFTIRQ_THRESH);
172*5113495bSYour Name 		} else {
173*5113495bSYour Name 			result = netif_rx(skb);
174*5113495bSYour Name 		}
175*5113495bSYour Name 	}
176*5113495bSYour Name 
177*5113495bSYour Name 	return result;
178*5113495bSYour Name }
179*5113495bSYour Name #endif
180*5113495bSYour Name 
hdd_ipa_send_nbuf_to_network(qdf_nbuf_t nbuf,qdf_netdev_t dev)181*5113495bSYour Name void hdd_ipa_send_nbuf_to_network(qdf_nbuf_t nbuf, qdf_netdev_t dev)
182*5113495bSYour Name {
183*5113495bSYour Name 	struct hdd_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev);
184*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
185*5113495bSYour Name 	int result;
186*5113495bSYour Name 	bool delivered = false;
187*5113495bSYour Name 	uint32_t enabled, len = 0;
188*5113495bSYour Name 	struct hdd_tx_rx_stats *stats;
189*5113495bSYour Name 	struct hdd_station_ctx *sta_ctx;
190*5113495bSYour Name 	bool is_eapol;
191*5113495bSYour Name 	u8 *ta_addr = NULL;
192*5113495bSYour Name 
193*5113495bSYour Name 	if (hdd_validate_adapter(adapter)) {
194*5113495bSYour Name 		kfree_skb(nbuf);
195*5113495bSYour Name 		return;
196*5113495bSYour Name 	}
197*5113495bSYour Name 
198*5113495bSYour Name 	if (cds_is_driver_unloading()) {
199*5113495bSYour Name 		kfree_skb(nbuf);
200*5113495bSYour Name 		return;
201*5113495bSYour Name 	}
202*5113495bSYour Name 
203*5113495bSYour Name 	stats = &adapter->deflink->hdd_stats.tx_rx_stats;
204*5113495bSYour Name 	hdd_ipa_update_rx_mcbc_stats(adapter, nbuf);
205*5113495bSYour Name 
206*5113495bSYour Name 	if ((adapter->device_mode == QDF_SAP_MODE) &&
207*5113495bSYour Name 	    (qdf_nbuf_is_ipv4_dhcp_pkt(nbuf) == true)) {
208*5113495bSYour Name 		/* Send DHCP Indication to FW */
209*5113495bSYour Name 		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
210*5113495bSYour Name 						   WLAN_DP_ID);
211*5113495bSYour Name 		if (vdev) {
212*5113495bSYour Name 			ucfg_dp_softap_inspect_dhcp_packet(vdev, nbuf, QDF_RX);
213*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
214*5113495bSYour Name 		}
215*5113495bSYour Name 	}
216*5113495bSYour Name 
217*5113495bSYour Name 	is_eapol = qdf_nbuf_is_ipv4_eapol_pkt(nbuf);
218*5113495bSYour Name 
219*5113495bSYour Name 	qdf_dp_trace_set_track(nbuf, QDF_RX);
220*5113495bSYour Name 
221*5113495bSYour Name 	ucfg_dp_event_eapol_log(nbuf, QDF_RX);
222*5113495bSYour Name 	qdf_dp_trace_log_pkt(adapter->deflink->vdev_id,
223*5113495bSYour Name 			     nbuf, QDF_RX, QDF_TRACE_DEFAULT_PDEV_ID,
224*5113495bSYour Name 			     adapter->device_mode);
225*5113495bSYour Name 	DPTRACE(qdf_dp_trace(nbuf,
226*5113495bSYour Name 			     QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
227*5113495bSYour Name 			     QDF_TRACE_DEFAULT_PDEV_ID,
228*5113495bSYour Name 			     qdf_nbuf_data_addr(nbuf),
229*5113495bSYour Name 			     sizeof(qdf_nbuf_data(nbuf)), QDF_RX));
230*5113495bSYour Name 	DPTRACE(qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
231*5113495bSYour Name 				      QDF_DP_TRACE_RX_PACKET_RECORD, 0,
232*5113495bSYour Name 				      QDF_RX));
233*5113495bSYour Name 
234*5113495bSYour Name 	/*
235*5113495bSYour Name 	 * Set PF_WAKE_UP_IDLE flag in the task structure
236*5113495bSYour Name 	 * This task and any task woken by this will be waken to idle CPU
237*5113495bSYour Name 	 */
238*5113495bSYour Name 	enabled = hdd_ipa_get_wake_up_idle();
239*5113495bSYour Name 	if (!enabled)
240*5113495bSYour Name 		hdd_ipa_set_wake_up_idle(true);
241*5113495bSYour Name 
242*5113495bSYour Name 	nbuf->dev = adapter->dev;
243*5113495bSYour Name 	nbuf->protocol = eth_type_trans(nbuf, nbuf->dev);
244*5113495bSYour Name 	nbuf->ip_summed = CHECKSUM_NONE;
245*5113495bSYour Name 	len = nbuf->len;
246*5113495bSYour Name 
247*5113495bSYour Name 	/*
248*5113495bSYour Name 	 * Update STA RX exception packet stats.
249*5113495bSYour Name 	 * For SAP as part of IPA HW stats are updated.
250*5113495bSYour Name 	 */
251*5113495bSYour Name 
252*5113495bSYour Name 	if (is_eapol && SEND_EAPOL_OVER_NL) {
253*5113495bSYour Name 		if (adapter->device_mode == QDF_SAP_MODE) {
254*5113495bSYour Name 			ta_addr = adapter->mac_addr.bytes;
255*5113495bSYour Name 		} else if (adapter->device_mode == QDF_STA_MODE) {
256*5113495bSYour Name 			sta_ctx =
257*5113495bSYour Name 				WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
258*5113495bSYour Name 			ta_addr = (u8 *)&sta_ctx->conn_info.peer_macaddr;
259*5113495bSYour Name 		}
260*5113495bSYour Name 
261*5113495bSYour Name 		if (ta_addr) {
262*5113495bSYour Name 			if (wlan_hdd_cfg80211_rx_control_port(adapter->dev,
263*5113495bSYour Name 							      ta_addr, nbuf,
264*5113495bSYour Name 							      false))
265*5113495bSYour Name 				result = NET_RX_SUCCESS;
266*5113495bSYour Name 			else
267*5113495bSYour Name 				result = NET_RX_DROP;
268*5113495bSYour Name 		} else {
269*5113495bSYour Name 			result = NET_RX_DROP;
270*5113495bSYour Name 		}
271*5113495bSYour Name 
272*5113495bSYour Name 		dev_kfree_skb(nbuf);
273*5113495bSYour Name 	} else {
274*5113495bSYour Name 		result = hdd_ipa_aggregated_rx_ind(nbuf);
275*5113495bSYour Name 	}
276*5113495bSYour Name 
277*5113495bSYour Name 	if (result == NET_RX_SUCCESS)
278*5113495bSYour Name 		delivered = true;
279*5113495bSYour Name 	/*
280*5113495bSYour Name 	 * adapter->vdev is directly dereferenced because this is per packet
281*5113495bSYour Name 	 * path, hdd_get_vdev_by_user() usage will be very costly as it involves
282*5113495bSYour Name 	 * lock access.
283*5113495bSYour Name 	 * Expectation here is vdev will be present during TX/RX processing
284*5113495bSYour Name 	 * and also DP internally maintaining vdev ref count
285*5113495bSYour Name 	 */
286*5113495bSYour Name 	ucfg_dp_inc_rx_pkt_stats(adapter->deflink->vdev,
287*5113495bSYour Name 				 len, delivered);
288*5113495bSYour Name 	/*
289*5113495bSYour Name 	 * Restore PF_WAKE_UP_IDLE flag in the task structure
290*5113495bSYour Name 	 */
291*5113495bSYour Name 	if (!enabled)
292*5113495bSYour Name 		hdd_ipa_set_wake_up_idle(false);
293*5113495bSYour Name }
294*5113495bSYour Name 
hdd_ipa_set_mcc_mode(bool mcc_mode)295*5113495bSYour Name void hdd_ipa_set_mcc_mode(bool mcc_mode)
296*5113495bSYour Name {
297*5113495bSYour Name 	struct hdd_context *hdd_ctx;
298*5113495bSYour Name 
299*5113495bSYour Name 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
300*5113495bSYour Name 	if (!hdd_ctx)
301*5113495bSYour Name 		return;
302*5113495bSYour Name 
303*5113495bSYour Name 	ucfg_ipa_set_mcc_mode(hdd_ctx->pdev, mcc_mode);
304*5113495bSYour Name }
305*5113495bSYour Name 
306*5113495bSYour Name #ifdef IPA_WDI3_TX_TWO_PIPES
307*5113495bSYour Name static void
hdd_ipa_fill_sta_connection_info(struct wlan_hdd_link_info * link,struct hdd_ipa_connection_info * conn)308*5113495bSYour Name hdd_ipa_fill_sta_connection_info(struct wlan_hdd_link_info *link,
309*5113495bSYour Name 				 struct hdd_ipa_connection_info *conn)
310*5113495bSYour Name {
311*5113495bSYour Name 	struct hdd_station_ctx *ctx = WLAN_HDD_GET_STATION_CTX_PTR(link);
312*5113495bSYour Name 
313*5113495bSYour Name 	conn->ch_freq = ctx->conn_info.chan_freq;
314*5113495bSYour Name 	conn->ch_width = ctx->conn_info.ch_width;
315*5113495bSYour Name 	conn->wlan_80211_mode = hdd_convert_cfgdot11mode_to_80211mode(
316*5113495bSYour Name 			ctx->conn_info.dot11mode);
317*5113495bSYour Name }
318*5113495bSYour Name 
319*5113495bSYour Name static void
hdd_ipa_fill_sap_connection_info(struct wlan_hdd_link_info * link,struct hdd_ipa_connection_info * conn)320*5113495bSYour Name hdd_ipa_fill_sap_connection_info(struct wlan_hdd_link_info *link,
321*5113495bSYour Name 				 struct hdd_ipa_connection_info *conn)
322*5113495bSYour Name {
323*5113495bSYour Name 	struct hdd_ap_ctx *ctx = WLAN_HDD_GET_AP_CTX_PTR(link);
324*5113495bSYour Name 
325*5113495bSYour Name 	conn->ch_freq = ctx->operating_chan_freq;
326*5113495bSYour Name 	conn->ch_width = ctx->sap_config.ch_params.ch_width;
327*5113495bSYour Name 	conn->wlan_80211_mode = hdd_convert_phymode_to_80211mode(
328*5113495bSYour Name 			ctx->sap_config.SapHw_mode);
329*5113495bSYour Name }
330*5113495bSYour Name 
hdd_ipa_fill_connection_info(struct wlan_hdd_link_info * link,struct hdd_ipa_connection_info * conn)331*5113495bSYour Name static void hdd_ipa_fill_connection_info(struct wlan_hdd_link_info *link,
332*5113495bSYour Name 					 struct hdd_ipa_connection_info *conn)
333*5113495bSYour Name {
334*5113495bSYour Name 	struct hdd_adapter *adapter = link->adapter;
335*5113495bSYour Name 
336*5113495bSYour Name 	conn->vdev_id = link->vdev_id;
337*5113495bSYour Name 
338*5113495bSYour Name 	if (adapter->device_mode == QDF_STA_MODE)
339*5113495bSYour Name 		hdd_ipa_fill_sta_connection_info(link, conn);
340*5113495bSYour Name 	else if (adapter->device_mode == QDF_SAP_MODE)
341*5113495bSYour Name 		hdd_ipa_fill_sap_connection_info(link, conn);
342*5113495bSYour Name }
343*5113495bSYour Name 
344*5113495bSYour Name static QDF_STATUS
hdd_ipa_get_tx_pipe_multi_conn(struct hdd_context * hdd_ctx,struct hdd_ipa_connection_info * conn,bool * tx_pipe)345*5113495bSYour Name hdd_ipa_get_tx_pipe_multi_conn(struct hdd_context *hdd_ctx,
346*5113495bSYour Name 			       struct hdd_ipa_connection_info *conn,
347*5113495bSYour Name 			       bool *tx_pipe)
348*5113495bSYour Name {
349*5113495bSYour Name 	uint32_t new_freq = conn->ch_freq;
350*5113495bSYour Name 	QDF_STATUS status;
351*5113495bSYour Name 	uint8_t vdev_id;
352*5113495bSYour Name 	bool pipe;
353*5113495bSYour Name 
354*5113495bSYour Name 	if (ucfg_policy_mgr_get_vdev_same_freq_new_conn(hdd_ctx->psoc,
355*5113495bSYour Name 							new_freq,
356*5113495bSYour Name 							&vdev_id)) {
357*5113495bSYour Name 		/* Inherit the pipe selection of the connection that has
358*5113495bSYour Name 		 * same freq.
359*5113495bSYour Name 		 */
360*5113495bSYour Name 		return ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id, tx_pipe);
361*5113495bSYour Name 	} else {
362*5113495bSYour Name 		if (ucfg_policy_mgr_get_vdev_diff_freq_new_conn(hdd_ctx->psoc,
363*5113495bSYour Name 								new_freq,
364*5113495bSYour Name 								&vdev_id)) {
365*5113495bSYour Name 			status = ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id,
366*5113495bSYour Name 						       &pipe);
367*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
368*5113495bSYour Name 				return QDF_STATUS_E_INVAL;
369*5113495bSYour Name 
370*5113495bSYour Name 			/* Inverse the pipe selection of the connection that
371*5113495bSYour Name 			 * has different channel frequency.
372*5113495bSYour Name 			 */
373*5113495bSYour Name 			*tx_pipe = !pipe;
374*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
375*5113495bSYour Name 		} else {
376*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
377*5113495bSYour Name 		}
378*5113495bSYour Name 	}
379*5113495bSYour Name }
380*5113495bSYour Name 
hdd_ipa_get_tx_pipe(struct hdd_context * hdd_ctx,struct wlan_hdd_link_info * link,bool * tx_pipe)381*5113495bSYour Name QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
382*5113495bSYour Name 			       struct wlan_hdd_link_info *link,
383*5113495bSYour Name 			       bool *tx_pipe)
384*5113495bSYour Name {
385*5113495bSYour Name 	struct hdd_ipa_connection_info conn;
386*5113495bSYour Name 	uint32_t count;
387*5113495bSYour Name 
388*5113495bSYour Name 	if (qdf_unlikely(!hdd_ctx || !link || !tx_pipe)) {
389*5113495bSYour Name 		hdd_debug("Invalid parameters");
390*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
391*5113495bSYour Name 	}
392*5113495bSYour Name 
393*5113495bSYour Name 	/* If SBS not capable, use legacy DBS selection */
394*5113495bSYour Name 	if (!ucfg_policy_mgr_is_hw_sbs_capable(hdd_ctx->psoc)) {
395*5113495bSYour Name 		hdd_debug("firmware is not sbs capable");
396*5113495bSYour Name 		*tx_pipe = WLAN_REG_IS_24GHZ_CH_FREQ(conn.ch_freq);
397*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
398*5113495bSYour Name 	}
399*5113495bSYour Name 
400*5113495bSYour Name 	hdd_ipa_fill_connection_info(link, &conn);
401*5113495bSYour Name 
402*5113495bSYour Name 	/* Always select the primary pipe for connection that is EHT160 or
403*5113495bSYour Name 	 * EHT320 due to higher tput requiements.
404*5113495bSYour Name 	 */
405*5113495bSYour Name 	if (conn.wlan_80211_mode == QCA_WLAN_802_11_MODE_11BE &&
406*5113495bSYour Name 	    (conn.ch_width == CH_WIDTH_160MHZ ||
407*5113495bSYour Name 	     conn.ch_width == CH_WIDTH_320MHZ)) {
408*5113495bSYour Name 		*tx_pipe = false;
409*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
410*5113495bSYour Name 	}
411*5113495bSYour Name 
412*5113495bSYour Name 	count = ucfg_policy_mgr_get_connection_count(hdd_ctx->psoc);
413*5113495bSYour Name 	if (!count) {
414*5113495bSYour Name 		/* For first connection that is below EHT160, select the
415*5113495bSYour Name 		 * alternate pipe so as to reserve the primary pipe for
416*5113495bSYour Name 		 * potential connections that are above EHT160.
417*5113495bSYour Name 		 */
418*5113495bSYour Name 		*tx_pipe = true;
419*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
420*5113495bSYour Name 	}
421*5113495bSYour Name 
422*5113495bSYour Name 	return hdd_ipa_get_tx_pipe_multi_conn(hdd_ctx, &conn, tx_pipe);
423*5113495bSYour Name }
424*5113495bSYour Name #else /* !IPA_WDI3_TX_TWO_PIPES */
hdd_ipa_get_tx_pipe(struct hdd_context * hdd_ctx,struct wlan_hdd_link_info * link,bool * tx_pipe)425*5113495bSYour Name QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
426*5113495bSYour Name 			       struct wlan_hdd_link_info *link,
427*5113495bSYour Name 			       bool *tx_pipe)
428*5113495bSYour Name {
429*5113495bSYour Name 	if (qdf_unlikely(!tx_pipe))
430*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
431*5113495bSYour Name 
432*5113495bSYour Name 	/* For IPA_WDI3_TX_TWO_PIPES=n, only one tx pipe is available */
433*5113495bSYour Name 	*tx_pipe = false;
434*5113495bSYour Name 
435*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
436*5113495bSYour Name }
437*5113495bSYour Name #endif /* IPA_WDI3_TX_TWO_PIPES */
438*5113495bSYour Name 
hdd_ipa_set_perf_level_bw(enum hw_mode_bandwidth bw)439*5113495bSYour Name void hdd_ipa_set_perf_level_bw(enum hw_mode_bandwidth bw)
440*5113495bSYour Name {
441*5113495bSYour Name 	struct hdd_context *hdd_ctx;
442*5113495bSYour Name 	enum wlan_ipa_bw_level lvl;
443*5113495bSYour Name 
444*5113495bSYour Name 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
445*5113495bSYour Name 	if (!hdd_ctx)
446*5113495bSYour Name 		return;
447*5113495bSYour Name 
448*5113495bSYour Name 	if (bw == HW_MODE_320_MHZ)
449*5113495bSYour Name 		lvl = WLAN_IPA_BW_LEVEL_HIGH;
450*5113495bSYour Name 	else if (bw == HW_MODE_160_MHZ)
451*5113495bSYour Name 		lvl = WLAN_IPA_BW_LEVEL_MEDIUM;
452*5113495bSYour Name 	else
453*5113495bSYour Name 		lvl = WLAN_IPA_BW_LEVEL_LOW;
454*5113495bSYour Name 
455*5113495bSYour Name 	hdd_debug("Vote IPA perf level to %d", lvl);
456*5113495bSYour Name 	ucfg_ipa_set_perf_level_bw(hdd_ctx->pdev, lvl);
457*5113495bSYour Name }
458*5113495bSYour Name 
459*5113495bSYour Name #endif
460