1 /*
2  * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: Implements public API for PMO NS offload feature to interact
21  * with target/wmi.
22  */
23 
24 #include "wlan_pmo_tgt_api.h"
25 #include "wlan_pmo_arp_public_struct.h"
26 #include "wlan_pmo_ns_public_struct.h"
27 #include "wlan_pmo_obj_mgmt_public_struct.h"
28 #include "wlan_pmo_main.h"
29 
pmo_tgt_enable_ns_offload_req(struct wlan_objmgr_vdev * vdev,uint8_t vdev_id)30 QDF_STATUS pmo_tgt_enable_ns_offload_req(struct wlan_objmgr_vdev *vdev,
31 		uint8_t vdev_id)
32 {
33 	struct pmo_arp_offload_params *arp_offload_req = NULL;
34 	struct pmo_ns_offload_params *ns_offload_req = NULL;
35 	struct pmo_vdev_priv_obj *vdev_ctx;
36 	struct wlan_objmgr_psoc *psoc;
37 	QDF_STATUS status;
38 	struct wlan_pmo_tx_ops pmo_tx_ops;
39 
40 	vdev_ctx = pmo_vdev_get_priv(vdev);
41 
42 	psoc = pmo_vdev_get_psoc(vdev);
43 
44 	arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req));
45 	if (!arp_offload_req) {
46 		status = QDF_STATUS_E_NOMEM;
47 		goto out;
48 	}
49 
50 	ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req));
51 	if (!ns_offload_req) {
52 		status = QDF_STATUS_E_NOMEM;
53 		goto out;
54 	}
55 
56 	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
57 	qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req,
58 		sizeof(*arp_offload_req));
59 	qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req,
60 		sizeof(*ns_offload_req));
61 	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
62 
63 	pmo_debug("vdev_id: %d: ARP offload %d NS offload  %d ns_count %u",
64 		  vdev_id,
65 		  arp_offload_req->enable, ns_offload_req->enable,
66 		  ns_offload_req->num_ns_offload_count);
67 
68 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
69 	if (!pmo_tx_ops.send_ns_offload_req) {
70 		pmo_err("send_ns_offload_req is null");
71 		status = QDF_STATUS_E_NULL_VALUE;
72 		goto out;
73 	}
74 	status = pmo_tx_ops.send_ns_offload_req(
75 			vdev, arp_offload_req, ns_offload_req);
76 	if (status != QDF_STATUS_SUCCESS) {
77 		pmo_err("Failed to send NS offload");
78 		goto out;
79 	}
80 
81 	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
82 	if (vdev_ctx->vdev_arp_req.enable)
83 		vdev_ctx->vdev_arp_req.is_offload_applied = true;
84 	if (vdev_ctx->vdev_ns_req.enable)
85 		vdev_ctx->vdev_ns_req.is_offload_applied = true;
86 	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
87 
88 out:
89 	if (arp_offload_req)
90 		qdf_mem_free(arp_offload_req);
91 	if (ns_offload_req)
92 		qdf_mem_free(ns_offload_req);
93 
94 	return status;
95 }
96 
pmo_tgt_disable_ns_offload_req(struct wlan_objmgr_vdev * vdev,uint8_t vdev_id)97 QDF_STATUS pmo_tgt_disable_ns_offload_req(struct wlan_objmgr_vdev *vdev,
98 		uint8_t vdev_id)
99 {
100 	struct pmo_arp_offload_params *arp_offload_req = NULL;
101 	struct pmo_ns_offload_params *ns_offload_req = NULL;
102 	struct pmo_vdev_priv_obj *vdev_ctx;
103 	struct wlan_objmgr_psoc *psoc;
104 	QDF_STATUS status;
105 	struct wlan_pmo_tx_ops pmo_tx_ops;
106 
107 	pmo_enter();
108 
109 	vdev_ctx = pmo_vdev_get_priv(vdev);
110 
111 	psoc = pmo_vdev_get_psoc(vdev);
112 
113 	arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req));
114 	if (!arp_offload_req) {
115 		status = QDF_STATUS_E_NOMEM;
116 		goto out;
117 	}
118 
119 	ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req));
120 	if (!ns_offload_req) {
121 		status = QDF_STATUS_E_NOMEM;
122 		goto out;
123 	}
124 
125 	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
126 	qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req,
127 		sizeof(*arp_offload_req));
128 	qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req,
129 		sizeof(*ns_offload_req));
130 	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
131 
132 	pmo_debug("ARP Offload vdev_id: %d enable: %d",
133 		vdev_id,
134 		arp_offload_req->enable);
135 	pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u",
136 		vdev_id,
137 		ns_offload_req->enable,
138 		ns_offload_req->num_ns_offload_count);
139 
140 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
141 	if (!pmo_tx_ops.send_ns_offload_req) {
142 		pmo_err("send_ns_offload_req is null");
143 		status = QDF_STATUS_E_NULL_VALUE;
144 		goto out;
145 	}
146 	status = pmo_tx_ops.send_ns_offload_req(
147 			vdev, arp_offload_req, ns_offload_req);
148 	if (status != QDF_STATUS_SUCCESS)
149 		pmo_err("Failed to send NS offload");
150 
151 	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
152 	vdev_ctx->vdev_arp_req.is_offload_applied = false;
153 	vdev_ctx->vdev_ns_req.is_offload_applied = false;
154 	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
155 
156 out:
157 	if (arp_offload_req)
158 		qdf_mem_free(arp_offload_req);
159 	if (ns_offload_req)
160 		qdf_mem_free(ns_offload_req);
161 	pmo_exit();
162 
163 	return status;
164 }
165 
166