blob: 2706b71037e103fafa24bf42edfc720d6f354b64 [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... */
Anurag Chouhan6d760662016-02-20 16:05:43 +053039#include "qdf_types.h" /* QDF_MODULE_ID_... */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#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
Anurag Chouhan6d760662016-02-20 16:05:43 +053061 hif = cds_get_context(QDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080062 if (unlikely(NULL == hif))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053063 QDF_ASSERT(NULL != hif); /* WARN */
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -080064 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{
Houston Hoffmanc1f962e2016-04-13 16:35:44 -0700106 struct hif_opaque_softc *hif_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107 int rc = 0;
108
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800109 NAPI_DEBUG("-->");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110
Anurag Chouhan6d760662016-02-20 16:05:43 +0530111 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800112 if (unlikely(NULL == hif_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530113 QDF_ASSERT(NULL != hif_ctx);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800114 rc = -EFAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115 } else {
Houston Hoffmanc1f962e2016-04-13 16:35:44 -0700116 rc = hif_napi_create(hif_ctx, hdd_napi_poll,
117 QCA_NAPI_BUDGET,
118 QCA_NAPI_DEF_SCALE);
119 if (rc < 0)
120 hdd_err("ERR(%d) creating NAPI instances",
121 rc);
122 else
123 hdd_info("napi instances were created. Map=0x%x", rc);
124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125 }
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800126 NAPI_DEBUG("<-- [rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127
128 return rc;
129}
130
131/**
132 * hdd_napi_destroy() - destroys the NAPI structures for a given netdev
133 * @force: if set, will force-disable the instance before _del'ing
134 *
135 * Destroy NAPI instances. This function is called
136 * unconditionally during module removal. It destroy
137 * napi structures through the proper HTC/HIF calls.
138 *
139 * Return:
140 * number of NAPI instances destroyed
141 */
142int hdd_napi_destroy(int force)
143{
144 int rc = 0;
145 int i;
146 uint32_t hdd_napi_map = hdd_napi_get_map();
147
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800148 NAPI_DEBUG("--> (force=%d)", force);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149 if (hdd_napi_map) {
Komal Seelam3d202862016-02-24 18:43:24 +0530150 struct hif_opaque_softc *hif_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Anurag Chouhan6d760662016-02-20 16:05:43 +0530152 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800153 if (unlikely(NULL == hif_ctx))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530154 QDF_ASSERT(NULL != hif_ctx);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800155 else
156 for (i = 0; i < CE_COUNT_MAX; i++)
157 if (hdd_napi_map & (0x01 << i)) {
158 if (0 <= hif_napi_destroy(
159 hif_ctx,
160 NAPI_PIPE2ID(i), force)) {
161 rc++;
162 hdd_napi_map &= ~(0x01 << i);
163 } else
164 hdd_err("cannot destroy napi %d: (pipe:%d), f=%d\n",
165 i,
166 NAPI_PIPE2ID(i), force);
167 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 }
169
170 /* if all instances are removed, it is likely that hif_context has been
171 * removed as well, so the cached value of the napi context also needs
172 * to be removed
173 */
174 if (force)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530175 QDF_ASSERT(hdd_napi_map == 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176 if (0 == hdd_napi_map)
177 hdd_napi_ctx = NULL;
178
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800179 NAPI_DEBUG("<-- [rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 return rc;
181}
182
183/**
184 * hdd_napi_enabled() - checks if NAPI is enabled (for a given id)
185 * @id: the id of the NAPI to check (any= -1)
186 *
187 * Return:
188 * int: 0 = false (NOT enabled)
189 * !0 = true (enabbled)
190 */
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800191int hdd_napi_enabled(int id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192{
Komal Seelam3d202862016-02-24 18:43:24 +0530193 struct hif_opaque_softc *hif;
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800194 int rc = 0; /* NOT enabled */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195
Anurag Chouhan6d760662016-02-20 16:05:43 +0530196 hif = cds_get_context(QDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800197 if (unlikely(NULL == hif))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530198 QDF_ASSERT(hif != NULL); /* WARN_ON; rc = 0 */
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800199 else if (-1 == id)
200 rc = hif_napi_enabled(hif, id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201 else
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800202 rc = hif_napi_enabled(hif, NAPI_ID2PIPE(id));
203 return rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204}
205
206/**
207 * hdd_napi_event() - relay the event detected by HDD to HIF NAPI decision maker
208 * @event: event code
209 * @data : event-specific auxiliary data
210 *
211 * Return code does not indicate a change, but whether or not NAPI is
212 * enabled at the time of the return of the function. That is, if NAPI
213 * was disabled before the call, and the event does not cause NAPI to be
214 * enabled, a value of 0 will be returned indicating that it is (still)
215 * disabled.
216 *
217 * Return:
218 * < 0: error code
219 * = 0: NAPI state = disabled (after processing the event)
220 * = 1: NAPI state = enabled (after processing the event)
221 */
222int hdd_napi_event(enum qca_napi_event event, void *data)
223{
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800224 int rc = -EFAULT; /* assume err */
Komal Seelam3d202862016-02-24 18:43:24 +0530225 struct hif_opaque_softc *hif;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800227 NAPI_DEBUG("-->(event=%d, aux=%p)", event, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228
Anurag Chouhan6d760662016-02-20 16:05:43 +0530229 hif = cds_get_context(QDF_MODULE_ID_HIF);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800230 if (unlikely(NULL == hif))
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530231 QDF_ASSERT(hif != NULL);
Orhan K AKYILDIZc4094612015-11-11 18:01:15 -0800232 else
233 rc = hif_napi_event(hif, event, data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234
Houston Hoffman43d47fa2016-02-24 16:34:30 -0800235 NAPI_DEBUG("<--[rc=%d]", rc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 return rc;
237}
238
239/**
240 * hdd_napi_poll() - NAPI poll function
241 * @napi : pointer to NAPI struct
242 * @budget: the pre-declared budget
243 *
244 * Implementation of poll function. This function is called
245 * by kernel during softirq processing.
246 *
247 * NOTE FOR THE MAINTAINER:
248 * Make sure this is very close to the ce_tasklet code.
249 *
250 * Return:
251 * int: the amount of work done ( <= budget )
252 */
253int hdd_napi_poll(struct napi_struct *napi, int budget)
254{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530255 return hif_napi_poll(cds_get_context(QDF_MODULE_ID_HIF), napi, budget);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256}