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