blob: 396eb3fb6cc8063500db70a6779ab0d19a74cf39 [file] [log] [blame]
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001/*
Komal Seelamf8600682016-02-02 18:17:13 +05302 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -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#include "htc_debug.h"
29#include "htc_internal.h"
Yue Mab16cf302016-03-08 18:30:25 -080030#include <hif.h>
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053031#include <qdf_nbuf.h> /* qdf_nbuf_t */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080032
33/* use credit flow control over HTC */
34unsigned int htc_credit_flow = 1;
35#ifndef DEBUG_CREDIT
36#define DEBUG_CREDIT 0
37#endif
38
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070039/* HTC credit flow global disable */
40void htc_global_credit_flow_disable(void)
41{
42 htc_credit_flow = 0;
43}
44
45/* HTC credit flow global enable */
46void htc_global_credit_flow_enable(void)
47{
48 htc_credit_flow = 1;
49}
50
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080051A_STATUS htc_connect_service(HTC_HANDLE HTCHandle,
52 HTC_SERVICE_CONNECT_REQ *pConnectReq,
53 HTC_SERVICE_CONNECT_RESP *pConnectResp)
54{
55 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
56 A_STATUS status = A_OK;
57 HTC_PACKET *pSendPacket = NULL;
58 HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg;
59 HTC_CONNECT_SERVICE_MSG *pConnectMsg;
60 HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX;
61 HTC_ENDPOINT *pEndpoint;
62 unsigned int maxMsgSize = 0;
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +053063 qdf_nbuf_t netbuf;
Yue Mab16cf302016-03-08 18:30:25 -080064 uint8_t txAlloc;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080065 int length;
Yue Mab16cf302016-03-08 18:30:25 -080066 bool disableCreditFlowCtrl = false;
67 uint16_t conn_flags;
68 uint16_t rsp_msg_id, rsp_msg_serv_id, rsp_msg_max_msg_size;
69 uint8_t rsp_msg_status, rsp_msg_end_id, rsp_msg_serv_meta_len;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080070
71 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
Houston Hoffman4f2f4592015-10-20 18:00:29 -070072 ("+htc_connect_service, target:%p SvcID:0x%X\n", target,
73 pConnectReq->service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080074
75 do {
76
Houston Hoffman4f2f4592015-10-20 18:00:29 -070077 AR_DEBUG_ASSERT(pConnectReq->service_id != 0);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080078
Houston Hoffman4f2f4592015-10-20 18:00:29 -070079 if (HTC_CTRL_RSVD_SVC == pConnectReq->service_id) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080080 /* special case for pseudo control service */
81 assignedEndpoint = ENDPOINT_0;
82 maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH;
83 txAlloc = 0;
84
85 } else {
86
Houston Hoffman4f2f4592015-10-20 18:00:29 -070087 txAlloc = htc_get_credit_allocation(target,
88 pConnectReq->service_id);
89
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080090 if (!txAlloc) {
91 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
92 ("Service %d does not allocate target credits!\n",
Houston Hoffman4f2f4592015-10-20 18:00:29 -070093 pConnectReq->service_id));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080094 }
95
96 /* allocate a packet to send to the target */
97 pSendPacket = htc_alloc_control_tx_packet(target);
98
99 if (NULL == pSendPacket) {
100 AR_DEBUG_ASSERT(false);
101 status = A_NO_MEMORY;
102 break;
103 }
104
105 netbuf =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530106 (qdf_nbuf_t)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800107 GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
108 length =
109 sizeof(HTC_CONNECT_SERVICE_MSG) +
110 pConnectReq->MetaDataLength;
111
112 /* assemble connect service message */
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530113 qdf_nbuf_put_tail(netbuf, length);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800114 pConnectMsg =
Vishwajith Upendra70f8b6e2016-03-01 16:28:23 +0530115 (HTC_CONNECT_SERVICE_MSG *) qdf_nbuf_data(netbuf);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800116
117 if (NULL == pConnectMsg) {
118 AR_DEBUG_ASSERT(0);
119 status = A_EFAULT;
120 break;
121 }
122
Yue Mab16cf302016-03-08 18:30:25 -0800123 qdf_mem_zero(pConnectMsg,
124 sizeof(HTC_CONNECT_SERVICE_MSG));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800125
126 conn_flags =
127 (pConnectReq->
128 ConnectionFlags & ~HTC_SET_RECV_ALLOC_MASK) |
129 HTC_CONNECT_FLAGS_SET_RECV_ALLOCATION(txAlloc);
130 HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG,
131 MESSAGEID, HTC_MSG_CONNECT_SERVICE_ID);
132 HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700133 SERVICE_ID, pConnectReq->service_id);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800134 HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG,
135 CONNECTIONFLAGS, conn_flags);
136
137 if (pConnectReq->
138 ConnectionFlags &
139 HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL) {
140 disableCreditFlowCtrl = true;
141 }
Yue Ma9be730f2016-03-08 17:40:42 -0800142
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800143 if (!htc_credit_flow) {
144 disableCreditFlowCtrl = true;
145 }
Yue Ma9be730f2016-03-08 17:40:42 -0800146
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800147 /* check caller if it wants to transfer meta data */
148 if ((pConnectReq->pMetaData != NULL) &&
149 (pConnectReq->MetaDataLength <=
150 HTC_SERVICE_META_DATA_MAX_LENGTH)) {
151 /* copy meta data into message buffer (after header ) */
Yue Mab16cf302016-03-08 18:30:25 -0800152 qdf_mem_copy((uint8_t *) pConnectMsg +
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800153 sizeof(HTC_CONNECT_SERVICE_MSG),
154 pConnectReq->pMetaData,
155 pConnectReq->MetaDataLength);
156
157 HTC_SET_FIELD(pConnectMsg,
158 HTC_CONNECT_SERVICE_MSG,
159 SERVICEMETALENGTH,
160 pConnectReq->MetaDataLength);
161 }
162
163 SET_HTC_PACKET_INFO_TX(pSendPacket,
164 NULL,
Yue Mab16cf302016-03-08 18:30:25 -0800165 (uint8_t *) pConnectMsg,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800166 length,
167 ENDPOINT_0,
168 HTC_SERVICE_TX_PACKET_TAG);
169
170 status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
171 /* we don't own it anymore */
172 pSendPacket = NULL;
173 if (A_FAILED(status)) {
174 break;
175 }
176
177 /* wait for response */
178 status = htc_wait_recv_ctrl_message(target);
179 if (A_FAILED(status)) {
180 break;
181 }
182 /* we controlled the buffer creation so it has to be properly aligned */
183 pResponseMsg =
184 (HTC_CONNECT_SERVICE_RESPONSE_MSG *) target->
185 CtrlResponseBuffer;
186
187 rsp_msg_id = HTC_GET_FIELD(pResponseMsg,
188 HTC_CONNECT_SERVICE_RESPONSE_MSG,
189 MESSAGEID);
190 rsp_msg_serv_id =
191 HTC_GET_FIELD(pResponseMsg,
192 HTC_CONNECT_SERVICE_RESPONSE_MSG,
193 SERVICEID);
194 rsp_msg_status =
195 HTC_GET_FIELD(pResponseMsg,
196 HTC_CONNECT_SERVICE_RESPONSE_MSG,
197 STATUS);
198 rsp_msg_end_id =
199 HTC_GET_FIELD(pResponseMsg,
200 HTC_CONNECT_SERVICE_RESPONSE_MSG,
201 ENDPOINTID);
202 rsp_msg_max_msg_size =
203 HTC_GET_FIELD(pResponseMsg,
204 HTC_CONNECT_SERVICE_RESPONSE_MSG,
205 MAXMSGSIZE);
206 rsp_msg_serv_meta_len =
207 HTC_GET_FIELD(pResponseMsg,
208 HTC_CONNECT_SERVICE_RESPONSE_MSG,
209 SERVICEMETALENGTH);
210
211 if ((rsp_msg_id != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID)
212 || (target->CtrlResponseLength <
213 sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
214 /* this message is not valid */
215 AR_DEBUG_ASSERT(false);
216 status = A_EPROTO;
217 break;
218 }
219
220 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
221 ("htc_connect_service, service 0x%X connect response from target status:%d, assigned ep: %d\n",
222 rsp_msg_serv_id, rsp_msg_status,
223 rsp_msg_end_id));
224
225 pConnectResp->ConnectRespCode = rsp_msg_status;
226
227 /* check response status */
228 if (rsp_msg_status != HTC_SERVICE_SUCCESS) {
229 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
230 (" Target failed service 0x%X connect request (status:%d)\n",
231 rsp_msg_serv_id,
232 rsp_msg_status));
233 status = A_EPROTO;
Houston Hoffmane6330442016-02-26 12:19:11 -0800234/* TODO: restore the ifdef when FW supports services 301 and 302 (HTT_MSG_DATA[23]_MSG_SVC)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800235#ifdef QCA_TX_HTT2_SUPPORT
Houston Hoffmane6330442016-02-26 12:19:11 -0800236*/
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800237 /* Keep work and not to block the control message. */
238 target->CtrlResponseProcessing = false;
Houston Hoffmane6330442016-02-26 12:19:11 -0800239/*#endif */ /* QCA_TX_HTT2_SUPPORT */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800240 break;
241 }
242
243 assignedEndpoint = (HTC_ENDPOINT_ID) rsp_msg_end_id;
244 maxMsgSize = rsp_msg_max_msg_size;
245
246 if ((pConnectResp->pMetaData != NULL) &&
247 (rsp_msg_serv_meta_len > 0) &&
248 (rsp_msg_serv_meta_len <=
249 HTC_SERVICE_META_DATA_MAX_LENGTH)) {
250 /* caller supplied a buffer and the target responded with data */
251 int copyLength =
252 min((int)pConnectResp->BufferLength,
253 (int)rsp_msg_serv_meta_len);
254 /* copy the meta data */
Yue Mab16cf302016-03-08 18:30:25 -0800255 qdf_mem_copy(pConnectResp->pMetaData,
256 ((uint8_t *) pResponseMsg) +
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800257 sizeof
258 (HTC_CONNECT_SERVICE_RESPONSE_MSG),
259 copyLength);
260 pConnectResp->ActualLength = copyLength;
261 }
262 /* done processing response buffer */
263 target->CtrlResponseProcessing = false;
264 }
265
266 /* the rest of these are parameter checks so set the error status */
267 status = A_EPROTO;
268
269 if (assignedEndpoint >= ENDPOINT_MAX) {
270 AR_DEBUG_ASSERT(false);
271 break;
272 }
273
274 if (0 == maxMsgSize) {
275 AR_DEBUG_ASSERT(false);
276 break;
277 }
278
Houston Hoffman29573d92015-10-20 17:49:44 -0700279 pEndpoint = &target->endpoint[assignedEndpoint];
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800280 pEndpoint->Id = assignedEndpoint;
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700281 if (pEndpoint->service_id != 0) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800282 /* endpoint already in use! */
283 AR_DEBUG_ASSERT(false);
284 break;
285 }
286
287 /* return assigned endpoint to caller */
288 pConnectResp->Endpoint = assignedEndpoint;
289 pConnectResp->MaxMsgLength = maxMsgSize;
290
291 /* setup the endpoint */
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700292 /* service_id marks the endpoint in use */
293 pEndpoint->service_id = pConnectReq->service_id;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800294 pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth;
295 pEndpoint->MaxMsgLength = maxMsgSize;
296 pEndpoint->TxCredits = txAlloc;
297 pEndpoint->TxCreditSize = target->TargetCreditSize;
298 pEndpoint->TxCreditsPerMaxMsg =
299 maxMsgSize / target->TargetCreditSize;
300 if (maxMsgSize % target->TargetCreditSize) {
301 pEndpoint->TxCreditsPerMaxMsg++;
302 }
303#if DEBUG_CREDIT
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530304 qdf_print(" Endpoint%d initial credit:%d, size:%d.\n",
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800305 pEndpoint->Id, pEndpoint->TxCredits,
306 pEndpoint->TxCreditSize);
307#endif
308
309 /* copy all the callbacks */
310 pEndpoint->EpCallBacks = pConnectReq->EpCallbacks;
311
312 status = hif_map_service_to_pipe(target->hif_dev,
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700313 pEndpoint->service_id,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800314 &pEndpoint->UL_PipeID,
315 &pEndpoint->DL_PipeID,
316 &pEndpoint->ul_is_polled,
317 &pEndpoint->dl_is_polled);
318 if (A_FAILED(status)) {
319 break;
320 }
321
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530322 qdf_assert(!pEndpoint->dl_is_polled); /* not currently supported */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800323
324 if (pEndpoint->ul_is_polled) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530325 qdf_timer_init(target->osdev,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800326 &pEndpoint->ul_poll_timer,
327 htc_send_complete_check_cleanup,
328 pEndpoint,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530329 QDF_TIMER_TYPE_SW);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800330 }
331
332 AR_DEBUG_PRINTF(ATH_DEBUG_SETUP,
333 ("HTC Service:0x%4.4X, ULpipe:%d DLpipe:%d id:%d Ready\n",
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700334 pEndpoint->service_id, pEndpoint->UL_PipeID,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800335 pEndpoint->DL_PipeID, pEndpoint->Id));
336
337 if (disableCreditFlowCtrl && pEndpoint->TxCreditFlowEnabled) {
338 pEndpoint->TxCreditFlowEnabled = false;
339 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
340 ("HTC Service:0x%4.4X ep:%d TX flow control disabled\n",
Houston Hoffman4f2f4592015-10-20 18:00:29 -0700341 pEndpoint->service_id,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800342 assignedEndpoint));
343 }
344
345 } while (false);
346
Komal Seelamf8600682016-02-02 18:17:13 +0530347 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_connect_service\n"));
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800348
349 return status;
350}
351
352void htc_set_credit_distribution(HTC_HANDLE HTCHandle,
353 void *pCreditDistContext,
354 HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
355 HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
356 HTC_SERVICE_ID ServicePriorityOrder[],
357 int ListLength)
358{
359 /* NOT Supported, this transport does not use a credit based flow control mechanism */
360
361}
362
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530363void htc_fw_event_handler(void *context, QDF_STATUS status)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800364{
365 HTC_TARGET *target = (HTC_TARGET *) context;
366 HTC_INIT_INFO *initInfo = &target->HTCInitInfo;
367
368 /* check if target failure handler exists and pass error code to it. */
369 if (target->HTCInitInfo.TargetFailure != NULL) {
370 initInfo->TargetFailure(initInfo->pContext, status);
371 }
372}