blob: 2b38d84e64d7a3b9749f73cf104d4fd5abf100c4 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*===========================================================================
43
44 W L A N _ Q C T _ C T S . C
45
46 OVERVIEW:
47
48 This software unit holds the implementation of the WLAN Control Transport
49 Service Layer.
50
51 The functions externalized by this module are to be called by the DAL Core
52 that wishes to use a platform agnostic API to communicate with the WLAN SS.
53
54 DEPENDENCIES:
55
56 Are listed for each API below.
57
58
59 Copyright (c) 2010-2011 QUALCOMM Incorporated.
60 All Rights Reserved.
61 Qualcomm Confidential and Proprietary
62===========================================================================*/
63
64/*===========================================================================
65
66 EDIT HISTORY FOR FILE
67
68
69 This section contains comments describing changes made to the module.
70 Notice that changes are listed in reverse chronological order.
71
72
73 $Header$$DateTime$$Author$
74
75
76 when who what, where, why
77 ---------- --- --------------------------------------------------------
78 2011-02-28 jtj Linux/Android implementation which utilizes SMD
79 2010-08-09 mss Created module
80
81===========================================================================*/
82
83
84
85/*===========================================================================
86
87 INCLUDE FILES FOR MODULE
88
89===========================================================================*/
90
91/*----------------------------------------------------------------------------
92 * Include Files
93 * -------------------------------------------------------------------------*/
94#include "wlan_qct_wdi_cts.h"
95#include "wlan_qct_pal_msg.h"
96#include "wlan_qct_pal_api.h"
97#include "wlan_qct_pal_trace.h"
98#include "wlan_qct_os_list.h"
99#include "wlan_qct_wdi.h"
100#include "wlan_qct_wdi_i.h"
101#ifdef CONFIG_ANDROID
102#include <mach/msm_smd.h>
103#include <linux/delay.h>
104#else
105#include "msm_smd.h"
106#endif
107
108/* Global context for CTS handle, it is required to keep this
109 * transport open during SSR shutdown */
110static WCTS_HandleType gwctsHandle;
111/*----------------------------------------------------------------------------
112 * Preprocessor Definitions and Constants
113 * -------------------------------------------------------------------------*/
114
115/* Magic value to validate a WCTS CB (value is little endian ASCII: WCTS */
116#define WCTS_CB_MAGIC 0x53544357
117
118/* time to wait for SMD channel to open (in msecs) */
119#define WCTS_SMD_OPEN_TIMEOUT 5000
120
121/* time to wait for SMD channel to close (in msecs) */
122#define WCTS_SMD_CLOSE_TIMEOUT 5000
123
124/*----------------------------------------------------------------------------
125 * Type Declarations
126 * -------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------
128 WCTS_StateType
129 ---------------------------------------------------------------------------*/
130typedef enum
131{
132 WCTS_STATE_CLOSED, /* Closed */
133 WCTS_STATE_OPEN_PENDING, /* Waiting for the OPEN event from SMD */
134 WCTS_STATE_OPEN, /* Open event received from SMD */
135 WCTS_STATE_DEFERRED, /* Write pending, SMD chennel is full */
136 WCTS_STATE_REM_CLOSED, /* Remote end closed the SMD channel */
137 WCTS_STATE_MAX
138} WCTS_StateType;
139
140/*---------------------------------------------------------------------------
141 Control Transport Control Block Type
142 ---------------------------------------------------------------------------*/
143typedef struct
144{
145 WCTS_NotifyCBType wctsNotifyCB;
146 void* wctsNotifyCBData;
147 WCTS_RxMsgCBType wctsRxMsgCB;
148 void* wctsRxMsgCBData;
149 WCTS_StateType wctsState;
150 smd_channel_t* wctsChannel;
151 wpt_list wctsPendingQueue;
152 wpt_uint32 wctsMagic;
153 wpt_msg wctsOpenMsg;
154 wpt_msg wctsDataMsg;
155 wpt_event wctsEvent;
156} WCTS_ControlBlockType;
157
158/*---------------------------------------------------------------------------
159 WDI CTS Buffer Type
160 ---------------------------------------------------------------------------*/
161typedef struct
162{
163 /*Node for linking pending buffers into a linked list */
164 wpt_list_node node;
165
166 /*Buffer associated with the request */
167 void* pBuffer;
168
169 /*Buffer Size*/
170 int bufferSize;
171
172} WCTS_BufferType;
173
174/*----------------------------------------------------------------------------
175 * Global Data Definitions
176 * -------------------------------------------------------------------------*/
177
178/*----------------------------------------------------------------------------
179 * Static Variable Definitions
180 * -------------------------------------------------------------------------*/
181#ifdef FEATURE_R33D
182/* R33D will not close SMD port
183 * If receive close request from WDI, just pretend as port closed,
184 * Store control block info static memory, and reuse next open */
185static WCTS_ControlBlockType *ctsCB;
186
187/* If port open once, not try to actual open next time */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700188static int port_open;
Jeff Johnson295189b2012-06-20 16:38:30 -0700189#endif /* FEATURE_R33D */
190/*----------------------------------------------------------------------------
191 * Static Function Declarations and Definitions
192 * -------------------------------------------------------------------------*/
193
194
195
196/**
197 @brief Callback function for serializing WCTS Open
198 processing in the control context
199 @param
200
201 pMsg - pointer to the message
202
203 @see
204 @return void
205*/
206static void
207WCTS_PALOpenCallback
208(
209 wpt_msg *pMsg
210)
211{
212 WCTS_ControlBlockType* pWCTSCb;
213 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
214
215 /* extract our context from the message */
216 pWCTSCb = pMsg->pContext;
217
218 /*--------------------------------------------------------------------
219 Sanity check
220 --------------------------------------------------------------------*/
221 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) {
222 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
223 "WCTS_PALOpenCallback: Invalid parameters received.");
224 return;
225 }
226
227 if (WCTS_STATE_OPEN_PENDING != pWCTSCb->wctsState) {
228 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
229 "WCTS_PALOpenCallback: Invoke from invalid state %d.",
230 pWCTSCb->wctsState);
231 return;
232 }
233
234 /* notified registered client that the channel is open */
235 pWCTSCb->wctsState = WCTS_STATE_OPEN;
236 pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb,
237 WCTS_EVENT_OPEN,
238 pWCTSCb->wctsNotifyCBData);
239
240 /* signal event for WCTS_OpenTransport to proceed */
241 wpalEventSet(&pWCTSCb->wctsEvent);
242
243}/*WCTS_PALOpenCallback*/
244
245
246
247/**
248 @brief Callback function for serializing WCTS Read
249 processing in the control context
250
251 @param pWCTSCb WCTS Control Block
252
253 @see
254 @return void
255*/
256static void
257WCTS_PALReadCallback
258(
259 WCTS_ControlBlockType* pWCTSCb
260)
261{
262 void* buffer;
263 int packet_size;
264 int available;
265 int bytes_read;
266
267 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
268
269 /*--------------------------------------------------------------------
270 Sanity check
271 --------------------------------------------------------------------*/
272 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) {
273 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
274 "WCTS_PALReadCallback: Invalid parameter received.");
275 return;
276 }
277
278 /* iterate until no more packets are available */
279 while (1) {
280 /* check the length of the next packet */
281 packet_size = smd_cur_packet_size(pWCTSCb->wctsChannel);
282 if (0 == packet_size) {
283 /* No more data to be read */
284 return;
285 }
286
287 /* Check how much of the data is available */
288 available = smd_read_avail(pWCTSCb->wctsChannel);
289 if (available < packet_size) {
290 /* Entire packet not yet ready to be read --
291 There will be another notification when it is ready */
292 return;
293 }
294
295 buffer = wpalMemoryAllocate(packet_size);
296 if (NULL == buffer) {
297 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
298 "WCTS_PALReadCallback: Memory allocation failure");
299 WPAL_ASSERT(0);
300 return;
301 }
302
303 bytes_read = smd_read(pWCTSCb->wctsChannel,
304 buffer,
305 packet_size);
306
307 if (bytes_read != packet_size) {
308 /*Some problem, do not forward it to WDI.*/
309 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
310 "WCTS_PALReadCallback: Failed to read data from SMD");
311 wpalMemoryFree(buffer);
312 WPAL_ASSERT(0);
313 return;
314 }
315
316 /* forward the message to the registered handler */
317 pWCTSCb->wctsRxMsgCB((WCTS_HandleType)pWCTSCb,
318 buffer,
319 packet_size,
320 pWCTSCb->wctsRxMsgCBData);
321
322 /* Free the allocated buffer*/
323 wpalMemoryFree(buffer);
324 }
325
326} /*WCTS_PALReadCallback*/
327
328
329
330/**
331 @brief Callback function for serializing WCTS Write
332 processing in the control context
333
334 @param pWCTSCb WCTS Control Block
335
336 @see
337 @return void
338*/
339static void
340WCTS_PALWriteCallback
341(
342 WCTS_ControlBlockType* pWCTSCb
343)
344{
345 wpt_list_node* pNode;
346 WCTS_BufferType* pBufferQueue;
347 void* pBuffer;
348 int len;
349 int available;
350 int written;
351
352 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
353
354 /*--------------------------------------------------------------------
355 Sanity check
356 --------------------------------------------------------------------*/
357 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) {
358 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
359 "WCTS_PALWriteCallback: Invalid parameter received.");
360 return;
361 }
362
363 /* if we are not deferred, then there are no pending packets */
364 if (WCTS_STATE_DEFERRED != pWCTSCb->wctsState) {
365 return;
366 }
367
368 /* Keep sending deferred messages as long as there is room in
369 the channel. Note that we initially peek at the head of the
370 list to access the parameters for the next message; we don't
371 actually remove the next message from the deferred list until
372 we know the channel can handle it */
373 while (eWLAN_PAL_STATUS_SUCCESS ==
374 wpal_list_peek_front(&pWCTSCb->wctsPendingQueue, &pNode)) {
375 pBufferQueue = container_of(pNode, WCTS_BufferType, node);
376 pBuffer = pBufferQueue->pBuffer;
377 len = pBufferQueue->bufferSize;
378
379 available = smd_write_avail(pWCTSCb->wctsChannel);
380 if (available < len) {
381 /* channel has no room for the next packet so we are done */
382 return;
383 }
384
385 /* there is room for the next message, so we can now remove
386 it from the deferred message queue and send it */
387 wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode);
388
389 /* note that pNode will be the same as when we peeked, so
390 there is no need to update pBuffer or len */
391
392 written = smd_write(pWCTSCb->wctsChannel, pBuffer, len);
393 if (written != len) {
394 /* Something went wrong */
395 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
396 "WCTS_PALWriteCallback: channel write failure");
397
398 /* we were unable to send the message that was at the head
399 of the deferred list. there is nothing else we can do
400 other than drop it, so we will just fall through to the
401 "success" processing.
402 hopefully the client can recover from this since there is
403 nothing else we can do here */
404 }
405
406 /* whether we had success or failure, reclaim all memory */
407 wpalMemoryFree(pBuffer);
408 wpalMemoryFree(pBufferQueue);
409
410 /* we'll continue to iterate until the channel is full or all
411 of the deferred messages have been sent */
412 }
413
414 /* if we've exited the loop, then we have drained the deferred queue.
415 set the state to indicate we are no longer deferred, and turn off
416 the remote read interrupt */
417 pWCTSCb->wctsState = WCTS_STATE_OPEN;
418 smd_disable_read_intr(pWCTSCb->wctsChannel);
419
420} /*WCTS_PALWriteCallback*/
421
422
423
424/**
425 @brief Callback function for serializing SMD DATA Event
426 processing in the control context
427 @param
428
429 pMsg - pointer to the message
430
431 @see
432 @return void
433*/
434static void
435WCTS_PALDataCallback
436(
437 wpt_msg *pMsg
438)
439{
440 WCTS_ControlBlockType* pWCTSCb;
441 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
442
443 /* extract our context from the message */
444 pWCTSCb = pMsg->pContext;
445
446 /* process any incoming messages */
447 WCTS_PALReadCallback(pWCTSCb);
448
449 /* send any deferred messages */
450 WCTS_PALWriteCallback(pWCTSCb);
451
452} /*WCTS_PALDataCallback*/
453
454/**
455 @brief This helper function is used to clean up the pending
456 messages in the transport queue
457
458 @param wctsHandlehandle: transport handle
459
460 @see
461 @return 0 for success
462*/
Madan Mohan Koyyalamudifab2a7e2012-09-28 15:20:00 -0700463wpt_uint32
Jeff Johnson295189b2012-06-20 16:38:30 -0700464WCTS_ClearPendingQueue
465(
466 WCTS_HandleType wctsHandle
467)
468{
469 WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle;
470 wpt_list_node* pNode = NULL;
471 WCTS_BufferType* pBufferQueue = NULL;
472 void* pBuffer = NULL;
473
474 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
475
476 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) {
477 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
478 "WCTS_ClearPendingQueue: Invalid parameters received.");
479 return eWLAN_PAL_STATUS_E_INVAL;
480 }
481
482 /*Free the buffers in the pending queue.*/
483 while (eWLAN_PAL_STATUS_SUCCESS ==
484 wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode)) {
485 pBufferQueue = container_of(pNode, WCTS_BufferType, node);
486 pBuffer = pBufferQueue->pBuffer;
487 wpalMemoryFree(pBuffer);
488 wpalMemoryFree(pBufferQueue);
489 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700490 return eWLAN_PAL_STATUS_SUCCESS;
491
492}/*WCTS_ClearPendingQueue*/
493
494
495/**
496 * Notification callback when SMD needs to communicate asynchronously with
497 * the client.
498 *
499 * This callback function may be called from interrupt context; clients must
500 * not block or call any functions that block.
501 *
502 * @param[in] data The user-supplied data provided to smd_named_open_on_edge()
503 * @param[in] event The event that occurred
504 *
505 * @return void
506 */
507
508static void
509WCTS_NotifyCallback
510(
511 void *data,
512 unsigned event
513)
514{
515 wpt_msg *palMsg;
516 WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) data;
517
518 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
519
520 /*--------------------------------------------------------------------
521 Sanity check
522 --------------------------------------------------------------------*/
523 if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) {
524 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
525 "%s: Received unexpected SMD event %u",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700526 __func__, event);
Jeff Johnson295189b2012-06-20 16:38:30 -0700527
528 /* TODO_PRIMA what error recovery options do we have? */
529 return;
530 }
531
532 /* Serialize processing in the control thread */
533 switch (event) {
534 case SMD_EVENT_OPEN:
535 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700536 "%s: received SMD_EVENT_OPEN from SMD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 /* If the prev state was 'remote closed' then it is a Riva 'restart',
538 * subsystem restart re-init
539 */
540 if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState)
541 {
542 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
543 "%s: received SMD_EVENT_OPEN in WCTS_STATE_REM_CLOSED state",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700544 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700545 /* call subsystem restart re-init function */
546 wpalDriverReInit();
547 return;
548 }
549 palMsg = &pWCTSCb->wctsOpenMsg;
550 break;
551
552 case SMD_EVENT_DATA:
553 if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState)
554 {
555 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
556 "%s: received SMD data when the state is remote closed ",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 /* we should not be getting any data now */
559 return;
560 }
561 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700562 "%s: received SMD_EVENT_DATA from SMD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 palMsg = &pWCTSCb->wctsDataMsg;
564 break;
565
566 case SMD_EVENT_CLOSE:
567 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700568 "%s: received SMD_EVENT_CLOSE from SMD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700569 /* SMD channel was closed from the remote side,
570 * this would happen only when Riva crashed and SMD is
571 * closing the channel on behalf of Riva */
572 pWCTSCb->wctsState = WCTS_STATE_REM_CLOSED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700573 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
574 "%s: received SMD_EVENT_CLOSE WLAN driver going down now",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700575 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 /* subsystem restart: shutdown */
577 wpalDriverShutdown();
578 return;
579
580 case SMD_EVENT_STATUS:
581 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700582 "%s: received SMD_EVENT_STATUS from SMD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 return;
584
585 case SMD_EVENT_REOPEN_READY:
Sameer Thalappil6d69cbd2013-06-27 13:07:15 -0700586 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700587 "%s: received SMD_EVENT_REOPEN_READY from SMD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700588
589 /* unlike other events which occur when our kernel threads are
590 running, this one is received when the threads are closed and
591 the rmmod thread is waiting. so just unblock that thread */
592 wpalEventSet(&pWCTSCb->wctsEvent);
593 return;
594
595 default:
596 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
597 "%s: Unexpected event %u received from SMD",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700598 __func__, event);
Jeff Johnson295189b2012-06-20 16:38:30 -0700599
600 return;
601 }
602
603 /* serialize this event */
604 wpalPostCtrlMsg(WDI_GET_PAL_CTX(), palMsg);
605
606} /*WCTS_NotifyCallback*/
607
608
609
610/*----------------------------------------------------------------------------
611 * Externalized Function Definitions
612 * -------------------------------------------------------------------------*/
613
614
615/**
616 @brief This function is used by the DAL Core to initialize the Control
617 Transport for processing. It must be called prior to calling any
618 other APIs of the Control Transport.
619
620
621 @param szName: unique name for the channel that is to be opened
622 uSize: size of the channel that must be opened (should fit the
623 largest size of packet that the Dal Core wishes to send)
624 wctsCBs: a list of callbacks that the CT needs to use to send
625 notification and messages back to DAL
626
627 @see
628 @return A handle that must be used for further communication with the CTS.
629 This is an opaque structure for the caller and it will be used in
630 all communications to and from the CTS.
631
632*/
633WCTS_HandleType
634WCTS_OpenTransport
635(
636 const wpt_uint8* szName,
637 wpt_uint32 uSize,
638 WCTS_TransportCBsType* wctsCBs
639)
640{
641 WCTS_ControlBlockType* pWCTSCb;
642 wpt_status status;
643 int smdstatus;
644
645 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
646
647 /*---------------------------------------------------------------------
648 Sanity check
649 ---------------------------------------------------------------------*/
650 if ((NULL == wctsCBs) || (NULL == szName) ||
651 (NULL == wctsCBs->wctsNotifyCB) || (NULL == wctsCBs->wctsRxMsgCB)) {
652 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
653 "WCTS_OpenTransport: Invalid parameters received.");
654
655 return NULL;
656 }
657
658 /* This open is coming after a SSR, we don't need to reopen SMD,
659 * the SMD port was never closed during SSR*/
660 if (gwctsHandle) {
661 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
Arif Hussain9a5d5382013-11-17 22:05:35 -0800662 "WCTS_OpenTransport port is already open");
Jeff Johnson295189b2012-06-20 16:38:30 -0700663
664 pWCTSCb = gwctsHandle;
665 if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) {
666 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
667 "WCTS_OpenTransport: Invalid magic.");
668 return NULL;
669 }
670 pWCTSCb->wctsState = WCTS_STATE_OPEN;
671
672 pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb,
673 WCTS_EVENT_OPEN,
674 pWCTSCb->wctsNotifyCBData);
675
676 /* we initially don't want read interrupts
677 (we only want them if we get into deferred write mode) */
678 smd_disable_read_intr(pWCTSCb->wctsChannel);
679
680 return (WCTS_HandleType)pWCTSCb;
681 }
682
683#ifdef FEATURE_R33D
684 if(port_open)
685 {
686 /* Port open before, not need to open again */
687 /* notified registered client that the channel is open */
688 ctsCB->wctsState = WCTS_STATE_OPEN;
689 ctsCB->wctsNotifyCB((WCTS_HandleType)ctsCB,
690 WCTS_EVENT_OPEN,
691 ctsCB->wctsNotifyCBData);
692 return (WCTS_HandleType)ctsCB;
693 }
694#endif /* FEATURE_R33D */
695
696 /* allocate a ControlBlock to hold all context */
697 pWCTSCb = wpalMemoryAllocate(sizeof(*pWCTSCb));
698 if (NULL == pWCTSCb) {
699 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
700 "WCTS_OpenTransport: Memory allocation failure.");
701 return NULL;
702 }
703
704 /* make sure the control block is initialized. in particular we need
705 to make sure the embedded event and list structures are initialized
706 to prevent "magic number" tests from being run against uninitialized
707 values */
708 wpalMemoryZero(pWCTSCb, sizeof(*pWCTSCb));
709
710#ifdef FEATURE_R33D
711 smd_init(0);
712 port_open = 1;
713 ctsCB = pWCTSCb;
714#endif /* FEATURE_R33D */
715
716 /*Initialise the event*/
717 wpalEventInit(&pWCTSCb->wctsEvent);
718
719 /* save the user-supplied information */
720 pWCTSCb->wctsNotifyCB = wctsCBs->wctsNotifyCB;
721 pWCTSCb->wctsNotifyCBData = wctsCBs->wctsNotifyCBData;
722 pWCTSCb->wctsRxMsgCB = wctsCBs->wctsRxMsgCB;
723 pWCTSCb->wctsRxMsgCBData = wctsCBs->wctsRxMsgCBData;
724
725 /* initialize the remaining fields */
726 wpal_list_init(&pWCTSCb->wctsPendingQueue);
727 pWCTSCb->wctsMagic = WCTS_CB_MAGIC;
728 pWCTSCb->wctsState = WCTS_STATE_OPEN_PENDING;
729 pWCTSCb->wctsChannel = NULL;
730
731 /* since SMD will callback in interrupt context, we will used
732 * canned messages to serialize the SMD events into a thread
733 * context
734 */
735 pWCTSCb->wctsOpenMsg.callback = WCTS_PALOpenCallback;
736 pWCTSCb->wctsOpenMsg.pContext = pWCTSCb;
Leo Chang0f24ca12013-12-17 13:35:00 -0800737 pWCTSCb->wctsOpenMsg.type= WPAL_MC_MSG_SMD_NOTIF_OPEN_SIG;
Jeff Johnson295189b2012-06-20 16:38:30 -0700738
739 pWCTSCb->wctsDataMsg.callback = WCTS_PALDataCallback;
740 pWCTSCb->wctsDataMsg.pContext = pWCTSCb;
Leo Chang0f24ca12013-12-17 13:35:00 -0800741 pWCTSCb-> wctsDataMsg.type= WPAL_MC_MSG_SMD_NOTIF_DATA_SIG;
Jeff Johnson295189b2012-06-20 16:38:30 -0700742
743 /*---------------------------------------------------------------------
744 Open the SMD channel
745 ---------------------------------------------------------------------*/
746
747 wpalEventReset(&pWCTSCb->wctsEvent);
748 smdstatus = smd_named_open_on_edge(szName,
749 SMD_APPS_WCNSS,
750 &pWCTSCb->wctsChannel,
751 pWCTSCb,
752 WCTS_NotifyCallback);
753 if (0 != smdstatus) {
754 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
755 "%s: smd_named_open_on_edge failed with status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700756 __func__, smdstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700757 goto fail;
758 }
759
760 /* wait for the channel to be fully opened before we proceed */
761 status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_OPEN_TIMEOUT);
762 if (eWLAN_PAL_STATUS_SUCCESS != status) {
763 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
764 "%s: failed to receive SMD_EVENT_OPEN",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700765 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700766 /* since we opened one end of the channel, close it */
767 smdstatus = smd_close(pWCTSCb->wctsChannel);
768 if (0 != smdstatus) {
769 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
770 "%s: smd_close failed with status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700771 __func__, smdstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 }
773 goto fail;
774 }
775
776 /* we initially don't want read interrupts
777 (we only want them if we get into deferred write mode) */
778 smd_disable_read_intr(pWCTSCb->wctsChannel);
779
780 /* we have successfully opened the SMD channel */
781 gwctsHandle = pWCTSCb;
782 return (WCTS_HandleType)pWCTSCb;
783
784 fail:
785 /* we were unable to open the SMD channel */
786 pWCTSCb->wctsMagic = 0;
787 wpalMemoryFree(pWCTSCb);
788 return NULL;
789
790}/*WCTS_OpenTransport*/
791
792
793
794/**
795 @brief This function is used by the DAL Core to close the
796 Control Transport when its services are no longer
797 needed. Full close notification will be receive
798 asynchronously on the notification callback
799 registered on Open
800
801
802 @param wctsHandlehandle: received upon open
803
804 @see
805 @return 0 for success
806*/
807wpt_uint32
808WCTS_CloseTransport
809(
810 WCTS_HandleType wctsHandle
811)
812{
813 WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle;
814 wpt_list_node* pNode = NULL;
815 WCTS_BufferType* pBufferQueue = NULL;
816 void* pBuffer = NULL;
817 wpt_status status;
818 int smdstatus;
819
820 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
821
822 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) {
823 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
824 "WCTS_CloseTransport: Invalid parameters received.");
825 return eWLAN_PAL_STATUS_E_INVAL;
826 }
827
828#ifdef FEATURE_R33D
829 /* Not actually close port, just pretend */
830 /* notified registered client that the channel is closed */
831 pWCTSCb->wctsState = WCTS_STATE_CLOSED;
832 pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb,
833 WCTS_EVENT_CLOSE,
834 pWCTSCb->wctsNotifyCBData);
835
836 printk(KERN_ERR "R33D Not need to close");
837 return eWLAN_PAL_STATUS_SUCCESS;
838#endif /* FEATURE_R33D */
839
840 /*Free the buffers in the pending queue.*/
841 while (eWLAN_PAL_STATUS_SUCCESS ==
842 wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode)) {
843 pBufferQueue = container_of(pNode, WCTS_BufferType, node);
844 pBuffer = pBufferQueue->pBuffer;
845 wpalMemoryFree(pBuffer);
846 wpalMemoryFree(pBufferQueue);
847 }
848
849 /* Reset the state */
850 pWCTSCb->wctsState = WCTS_STATE_CLOSED;
851
852 wpalEventReset(&pWCTSCb->wctsEvent);
853 smdstatus = smd_close(pWCTSCb->wctsChannel);
854 if (0 != smdstatus) {
855 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
856 "%s: smd_close failed with status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700857 __func__, smdstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 /* SMD did not successfully close the channel, therefore we
859 won't receive an asynchronous close notification so don't
860 bother to wait for an event that won't come */
861
862 } else {
863 /* close command was sent -- wait for the callback to complete */
864 status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_CLOSE_TIMEOUT);
865 if (eWLAN_PAL_STATUS_SUCCESS != status) {
866 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
867 "%s: failed to receive SMD_EVENT_REOPEN_READY",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700868 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 }
870
871 /* During the close sequence we deregistered from SMD. As part
872 of deregistration SMD will call back into our driver with an
873 event to let us know the channel is closed. We need to
874 insert a brief delay to allow that thread of execution to
875 exit our module. Otherwise our module may be unloaded while
876 there is still code running within the address space, and
877 that code will crash when the memory is unmapped */
878 msleep(50);
879 }
880
881 /* channel has (hopefully) been closed */
882 pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb,
883 WCTS_EVENT_CLOSE,
884 pWCTSCb->wctsNotifyCBData);
885
886 /* release the resource */
887 pWCTSCb->wctsMagic = 0;
888 wpalMemoryFree(pWCTSCb);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700889 gwctsHandle = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700890
891 return eWLAN_PAL_STATUS_SUCCESS;
892
893}/*WCTS_CloseTransport*/
894
895
896
897/**
898 @brief This function is used by the DAL Core to to send a
899 message over to the WLAN sub-system.
900
901 Once a buffer has been passed into the Send Message
902 API, CT takes full ownership of it and it is responsible for
903 freeing the associated resources. (This prevents a memcpy in
904 case of a deferred write)
905
906 The messages transported through the CT on both RX and TX are
907 flat memory buffers that can be accessed and manipulated
908 through standard memory functions.
909
910 @param wctsHandlehandle: received upon open
911 pMsg: the message to be sent
912 uLen: the length of the message
913
914 @see
915 @return 0 for success
916*/
917wpt_uint32
918WCTS_SendMessage
919(
920 WCTS_HandleType wctsHandle,
921 void* pMsg,
922 wpt_uint32 uLen
923)
924{
925 WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle;
926 WCTS_BufferType* pBufferQueue;
927 int len;
928 int written = 0;
929 int available;
930
931 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
932
933 /*--------------------------------------------------------------------
934 Sanity check
935 --------------------------------------------------------------------*/
936 if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) ||
937 (NULL == pMsg) || (0 == uLen) || (0x7fffffff < uLen)) {
938 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
939 "WCTS_SendMessage: Invalid parameters received.");
940 WPAL_ASSERT(0);
941 if (NULL != pMsg) {
942 wpalMemoryFree(pMsg);
943 }
944 return eWLAN_PAL_STATUS_E_INVAL;
945 }
946
947 /* the SMD API uses int instead of uint, so change types here */
948 len = (int)uLen;
949
950 if (WCTS_STATE_OPEN == pWCTSCb->wctsState) {
951 available = smd_write_avail(pWCTSCb->wctsChannel);
952 if (available >= len) {
953 written = smd_write(pWCTSCb->wctsChannel, pMsg, len);
954 }
955 } else if (WCTS_STATE_DEFERRED == pWCTSCb->wctsState) {
956 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
957 "WCTS_SendMessage: FIFO space not available, the packets will be queued");
958 } else {
959 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
960 "WCTS_SendMessage: Channel in illegal state [%d].",
961 pWCTSCb->wctsState);
962 /* force following logic to reclaim the buffer */
963 written = -1;
964 }
965
966 if (-1 == written) {
967 /*Something wrong*/
968 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
969 "WCTS_SendMessage: Failed to send message over the bus.");
970 wpalMemoryFree(pMsg);
971 WPAL_ASSERT(0);
972 return eWLAN_PAL_STATUS_E_FAILURE;
973 } else if (written == len) {
974 /* Message sent! No deferred state, free the buffer*/
975 wpalMemoryFree(pMsg);
976 } else {
977 /* This much data cannot be written at this time,
978 queue the rest of the data for later*/
979 pBufferQueue = wpalMemoryAllocate(sizeof(WCTS_BufferType));
980 if (NULL == pBufferQueue) {
981 WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
982 "WCTS_SendMessage: Cannot allocate memory for queuing the buffer");
983 wpalMemoryFree(pMsg);
984 WPAL_ASSERT(0);
985 return eWLAN_PAL_STATUS_E_NOMEM;
986 }
987
988 pBufferQueue->bufferSize = len;
989 pBufferQueue->pBuffer = pMsg;
990 wpal_list_insert_back(&pWCTSCb->wctsPendingQueue, &pBufferQueue->node);
991
992 /* if we are not already in the deferred state, then transition
993 to that state. when we do so, we enable the remote read
994 interrupt so that we'll be notified when messages are read
995 from the remote end */
996 if (WCTS_STATE_DEFERRED != pWCTSCb->wctsState) {
997
998 /* Mark the state as deferred.
999 Later: We may need to protect wctsState by locks*/
1000 pWCTSCb->wctsState = WCTS_STATE_DEFERRED;
1001
1002 smd_enable_read_intr(pWCTSCb->wctsChannel);
1003 }
Gopichand Nakkalaa5e3ede2012-12-21 15:28:36 -08001004
1005 /*indicate to client that message was placed in deferred queue*/
1006 return eWLAN_PAL_STATUS_E_RESOURCES;
Jeff Johnson295189b2012-06-20 16:38:30 -07001007 }
1008
1009 return eWLAN_PAL_STATUS_SUCCESS;
1010
1011}/*WCTS_SendMessage*/