blob: 15d372d393c3898cb34d197ea238f3f5928a8026 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Komal Seelamc12e6752016-02-02 18:17:13 +05302 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_napi.c
30 *
31 * WLAN HDD NAPI interface implementation
32 */
33#include <smp.h> /* get_cpu */
34
35#include "wlan_hdd_napi.h"
36#include "cds_api.h" /* cds_get_context */
37#include "hif.h" /* hif_map_service...*/
38#include "wlan_hdd_main.h" /* hdd_err/warn... */
39#include "cdf_types.h" /* CDF_MODULE_ID_... */
40#include "ce_api.h"
41
42/* guaranteed to be initialized to zero/NULL by the standard */
43static struct qca_napi_data *hdd_napi_ctx;
44
45/**
46 * hdd_napi_get_all() - return the whole NAPI structure from HIF
47 *
48 * Gets to the data structure common to all NAPI instances.
49 *
50 * Return:
51 * NULL : probably NAPI not initialized yet.
52 * <addr>: the address of the whole NAPI structure
53 */
54struct qca_napi_data *hdd_napi_get_all(void)
55{
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080056 struct qca_napi_data *rp = NULL;
Komal Seelam3d202862016-02-24 18:43:24 +053057 struct hif_opaque_softc *hif;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080058
Houston Hoffman43d47fa2016-02-24 16:34:30 -080059 NAPI_DEBUG("-->");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080060
61 hif = cds_get_context(CDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080062 if (unlikely(NULL == hif))
63 CDF_ASSERT(NULL != hif); /* WARN */
64 else
65 rp = hif_napi_get_all(hif);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066
Houston Hoffman43d47fa2016-02-24 16:34:30 -080067 NAPI_DEBUG("<-- [addr=%p]", rp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068 return rp;
69}
70
71/**
72 * hdd_napi_get_map() - get a copy of napi pipe map
73 *
74 * Return:
75 * uint32_t : copy of pipe map
76 */
77static uint32_t hdd_napi_get_map(void)
78{
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080079 uint32_t map = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080
Houston Hoffman43d47fa2016-02-24 16:34:30 -080081 NAPI_DEBUG("-->");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082 /* cache once, use forever */
83 if (hdd_napi_ctx == NULL)
84 hdd_napi_ctx = hdd_napi_get_all();
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080085 if (hdd_napi_ctx != NULL)
86 map = hdd_napi_ctx->ce_map;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080087
Houston Hoffman43d47fa2016-02-24 16:34:30 -080088 NAPI_DEBUG("<-- [map=0x%08x]", map);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089 return map;
90}
91
92/**
93 * hdd_napi_create() - creates the NAPI structures for a given netdev
94 *
95 * Creates NAPI instances. This function is called
96 * unconditionally during initialization. It creates
97 * napi structures through the proper HTC/HIF calls.
98 * The structures are disabled on creation.
99 *
100 * Return:
101 * single-queue: <0: err, >0=id, 0 (should not happen)
102 * multi-queue: bitmap of created instances (0: none)
103 */
104int hdd_napi_create(void)
105{
Komal Seelam3d202862016-02-24 18:43:24 +0530106 struct hif_opaque_softc *hif_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107 uint8_t ul, dl;
108 int ul_polled, dl_polled;
109 int rc = 0;
110
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800111 NAPI_DEBUG("-->");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800113 hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
114 if (unlikely(NULL == hif_ctx)) {
115 CDF_ASSERT(NULL != hif_ctx);
116 rc = -EFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117 } else {
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800118 /*
119 * Note: hif_service_to_pipe returns one pipe id per service.
120 * For multi-queue NAPI for Adrastea, we will use multiple
121 * services/calls.
122 * For Rome, there is only one service, hence a single call
123 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530124 if (QDF_STATUS_SUCCESS !=
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800125 hif_map_service_to_pipe(hif_ctx, HTT_DATA_MSG_SVC,
126 &ul, &dl, &ul_polled, &dl_polled)) {
127 hdd_err("cannot map service to pipe");
128 rc = -EINVAL;
129 } else {
130 rc = hif_napi_create(hif_ctx, dl, hdd_napi_poll,
131 QCA_NAPI_BUDGET,
132 QCA_NAPI_DEF_SCALE);
133 if (rc < 0)
134 hdd_err("ERR(%d) creating NAPI on pipe %d",
135 rc, dl);
136 else {
137 hdd_info("napi instance %d created on pipe %d",
138 rc, dl);
139 /* rc = (0x01 << rc); -- phase 2 */
140 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 }
142 }
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800143 NAPI_DEBUG("<-- [rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144
145 return rc;
146}
147
148/**
149 * hdd_napi_destroy() - destroys the NAPI structures for a given netdev
150 * @force: if set, will force-disable the instance before _del'ing
151 *
152 * Destroy NAPI instances. This function is called
153 * unconditionally during module removal. It destroy
154 * napi structures through the proper HTC/HIF calls.
155 *
156 * Return:
157 * number of NAPI instances destroyed
158 */
159int hdd_napi_destroy(int force)
160{
161 int rc = 0;
162 int i;
163 uint32_t hdd_napi_map = hdd_napi_get_map();
164
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800165 NAPI_DEBUG("--> (force=%d)", force);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166 if (hdd_napi_map) {
Komal Seelam3d202862016-02-24 18:43:24 +0530167 struct hif_opaque_softc *hif_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168
169 hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800170 if (unlikely(NULL == hif_ctx))
171 CDF_ASSERT(NULL != hif_ctx);
172 else
173 for (i = 0; i < CE_COUNT_MAX; i++)
174 if (hdd_napi_map & (0x01 << i)) {
175 if (0 <= hif_napi_destroy(
176 hif_ctx,
177 NAPI_PIPE2ID(i), force)) {
178 rc++;
179 hdd_napi_map &= ~(0x01 << i);
180 } else
181 hdd_err("cannot destroy napi %d: (pipe:%d), f=%d\n",
182 i,
183 NAPI_PIPE2ID(i), force);
184 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 }
186
187 /* if all instances are removed, it is likely that hif_context has been
188 * removed as well, so the cached value of the napi context also needs
189 * to be removed
190 */
191 if (force)
192 CDF_ASSERT(hdd_napi_map == 0);
193 if (0 == hdd_napi_map)
194 hdd_napi_ctx = NULL;
195
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800196 NAPI_DEBUG("<-- [rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 return rc;
198}
199
200/**
201 * hdd_napi_enabled() - checks if NAPI is enabled (for a given id)
202 * @id: the id of the NAPI to check (any= -1)
203 *
204 * Return:
205 * int: 0 = false (NOT enabled)
206 * !0 = true (enabbled)
207 */
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800208int hdd_napi_enabled(int id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209{
Komal Seelam3d202862016-02-24 18:43:24 +0530210 struct hif_opaque_softc *hif;
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800211 int rc = 0; /* NOT enabled */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212
213 hif = cds_get_context(CDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800214 if (unlikely(NULL == hif))
215 CDF_ASSERT(hif != NULL); /* WARN_ON; rc = 0 */
216 else if (-1 == id)
217 rc = hif_napi_enabled(hif, id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800218 else
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800219 rc = hif_napi_enabled(hif, NAPI_ID2PIPE(id));
220 return rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221}
222
223/**
224 * hdd_napi_event() - relay the event detected by HDD to HIF NAPI decision maker
225 * @event: event code
226 * @data : event-specific auxiliary data
227 *
228 * Return code does not indicate a change, but whether or not NAPI is
229 * enabled at the time of the return of the function. That is, if NAPI
230 * was disabled before the call, and the event does not cause NAPI to be
231 * enabled, a value of 0 will be returned indicating that it is (still)
232 * disabled.
233 *
234 * Return:
235 * < 0: error code
236 * = 0: NAPI state = disabled (after processing the event)
237 * = 1: NAPI state = enabled (after processing the event)
238 */
239int hdd_napi_event(enum qca_napi_event event, void *data)
240{
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800241 int rc = -EFAULT; /* assume err */
Komal Seelam3d202862016-02-24 18:43:24 +0530242 struct hif_opaque_softc *hif;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800244 NAPI_DEBUG("-->(event=%d, aux=%p)", event, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245
246 hif = cds_get_context(CDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800247 if (unlikely(NULL == hif))
248 CDF_ASSERT(hif != NULL);
249 else
250 rc = hif_napi_event(hif, event, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800252 NAPI_DEBUG("<--[rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 return rc;
254}
255
256/**
257 * hdd_napi_poll() - NAPI poll function
258 * @napi : pointer to NAPI struct
259 * @budget: the pre-declared budget
260 *
261 * Implementation of poll function. This function is called
262 * by kernel during softirq processing.
263 *
264 * NOTE FOR THE MAINTAINER:
265 * Make sure this is very close to the ce_tasklet code.
266 *
267 * Return:
268 * int: the amount of work done ( <= budget )
269 */
270int hdd_napi_poll(struct napi_struct *napi, int budget)
271{
Komal Seelamc12e6752016-02-02 18:17:13 +0530272 return hif_napi_poll(cds_get_context(CDF_MODULE_ID_HIF), napi, budget);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273}