blob: f2bdae6a0ce49b34a02dfafd3d1b8cdd04325d30 [file] [log] [blame]
Sridhar Parasurambf391322015-01-23 09:29:07 -08001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above
9 copyright notice, this list of conditions and the following
10 disclaimer in the documentation and/or other materials provided
11 with the distribution.
12 * Neither the name of The Linux Foundation nor the names of its
13 contributors may be used to endorse or promote products derived
14 from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29
30/*===========================================================================
31 INCLUDE FILES
32===========================================================================*/
33#include <glink.h>
Steven Cahail8f9eb172015-08-21 10:20:08 -060034#include <glink_rpm.h>
Sridhar Parasurambf391322015-01-23 09:29:07 -080035#include <glink_os_utils.h>
36#include <glink_internal.h>
37#include <glink_vector.h>
Steven Cahail964ff2f2015-08-20 19:01:56 -060038
39#ifdef FEATURE_TRACER_PACKET
40#include "glink_tracer.h"
41#endif
Sridhar Parasurambf391322015-01-23 09:29:07 -080042
43#define GLINK_NOT_INITIALIZED 0
44#define GLINK_INITIALIZED 1
45
46/*===========================================================================
Sridhar Parasuram3b058122015-05-11 16:15:03 -070047 GLOBAL DATA DECLARATIONS
Sridhar Parasurambf391322015-01-23 09:29:07 -080048===========================================================================*/
Sridhar Parasurambf391322015-01-23 09:29:07 -080049/*===========================================================================
50 LOCAL FUNCTION DEFINITIONS
51===========================================================================*/
Sridhar Parasuram3b058122015-05-11 16:15:03 -070052
53/** Default implementation of optional callbacks */
Sridhar Parasurambf391322015-01-23 09:29:07 -080054static void glink_default_notify_rx_sigs
55(
56 glink_handle_type handle,
57 const void *priv,
58 uint32 prev,
59 uint32 curr
60)
61{
Steven Cahaila136c102015-08-21 13:29:10 -060062 GLINK_OS_UNREFERENCED_PARAM( handle );
63 GLINK_OS_UNREFERENCED_PARAM( priv );
64 GLINK_OS_UNREFERENCED_PARAM( prev );
65 GLINK_OS_UNREFERENCED_PARAM( curr );
Sridhar Parasurambf391322015-01-23 09:29:07 -080066 return;
67}
68
Sridhar Parasurambf391322015-01-23 09:29:07 -080069/*===========================================================================
70 EXTERNAL FUNCTION DEFINITIONS
71===========================================================================*/
Steven Cahaile41e9a02015-08-20 11:10:16 -060072
Sridhar Parasurambf391322015-01-23 09:29:07 -080073/**
74 * Opens a logical GLink based on the specified config params
75 *
76 * @param[in] cfg_ptr Pointer to the configuration structure for the
77 * GLink. See glink.h
78 * @param[out] handle GLink handle associated with the logical channel
79 *
80 * @return Standard GLink error codes
81 *
82 * @sideeffects Allocates channel resources and informs remote host about
83 * channel open.
84 */
85glink_err_type glink_open
86(
87 glink_open_config_type *cfg_ptr,
88 glink_handle_type *handle
89)
90{
Steven Cahaile41e9a02015-08-20 11:10:16 -060091 glink_transport_if_type *if_ptr;
Sridhar Parasurambf391322015-01-23 09:29:07 -080092 glink_channel_ctx_type *ch_ctx;
93 unsigned int remote_host;
Steven Cahaile41e9a02015-08-20 11:10:16 -060094 glink_xport_priority suggested_priority;
95 glink_channel_ctx_type *allocated_ch_ctx;
96 glink_err_type status;
Sridhar Parasurambf391322015-01-23 09:29:07 -080097
98 /* Param validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -060099 if(cfg_ptr == NULL ||
100 cfg_ptr->remote_ss == NULL ||
Sridhar Parasurambf391322015-01-23 09:29:07 -0800101 cfg_ptr->name == NULL ||
102 cfg_ptr->notify_state == NULL)
103 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600104 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_OPEN, "", "", "",
Sridhar Parasurambf391322015-01-23 09:29:07 -0800105 GLINK_STATUS_INVALID_PARAM);
106 return GLINK_STATUS_INVALID_PARAM;
107 }
108
109 /* Evaluate the equivalent edge name->enum for future use */
110 remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);
111
Steven Cahail964ff2f2015-08-20 19:01:56 -0600112 if (remote_host == GLINK_NUM_HOSTS)
113 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800114 /* Unknown transport name trying to register with GLink */
Steven Cahailb850bb62015-08-21 14:39:38 -0600115 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_REGISTER_XPORT,
116 cfg_ptr->name, "",
117 cfg_ptr->remote_ss,
118 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800119
120 return GLINK_STATUS_INVALID_PARAM;
121 }
122
123 /* Allocate and initialize channel info structure */
124 ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
Steven Cahailb850bb62015-08-21 14:39:38 -0600125 if(ch_ctx == NULL)
126 {
127 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_OPEN,
128 cfg_ptr->name, "", "",
129 GLINK_STATUS_OUT_OF_RESOURCES );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800130 return GLINK_STATUS_OUT_OF_RESOURCES;
131 }
132
133 /* Fill in the channel info structure */
134 glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
135 ch_ctx->priv = cfg_ptr->priv;
136 ch_ctx->notify_rx = cfg_ptr->notify_rx;
137 ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
138 ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
139 ch_ctx->notify_state = cfg_ptr->notify_state;
140 ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
141 ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
142 ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
143 ch_ctx->ch_open_options = cfg_ptr->options;
144 ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
145 ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;
146
Steven Cahail964ff2f2015-08-20 19:01:56 -0600147 if (ch_ctx->notify_rx_sigs == NULL)
148 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800149 /* set default callback */
150 ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
151 }
152
Steven Cahaile41e9a02015-08-20 11:10:16 -0600153 if_ptr = glinki_find_requested_xport( cfg_ptr->transport,
Steven Cahail964ff2f2015-08-20 19:01:56 -0600154 cfg_ptr->remote_ss,
Steven Cahaile41e9a02015-08-20 11:10:16 -0600155 cfg_ptr->options,
156 &suggested_priority );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800157
Steven Cahaile41e9a02015-08-20 11:10:16 -0600158 if( !if_ptr )
Sridhar Parasurambf391322015-01-23 09:29:07 -0800159 {
Steven Cahaile41e9a02015-08-20 11:10:16 -0600160 /* Code gets here if we are not able to find reqeusted transport */
Steven Cahailb850bb62015-08-21 14:39:38 -0600161 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_OPEN,
Steven Cahaile41e9a02015-08-20 11:10:16 -0600162 cfg_ptr->name,
163 cfg_ptr->transport,
164 cfg_ptr->remote_ss,
165 GLINK_STATUS_NO_TRANSPORT );
166 glink_os_free(ch_ctx);
167 return GLINK_STATUS_NO_TRANSPORT;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800168 }
Steven Cahaile41e9a02015-08-20 11:10:16 -0600169
Sridhar Parasurambf391322015-01-23 09:29:07 -0800170 status = glinki_add_ch_to_xport( if_ptr,
Sridhar Parasurambf391322015-01-23 09:29:07 -0800171 ch_ctx,
172 &allocated_ch_ctx,
173 TRUE,
Steven Cahaile41e9a02015-08-20 11:10:16 -0600174 suggested_priority );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800175
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700176 if( status == GLINK_STATUS_SUCCESS )
177 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800178 /* Set the handle and return */
179 *handle = allocated_ch_ctx;
Steven Cahailb850bb62015-08-21 14:39:38 -0600180 GLINK_LOG_EVENT( *handle,
181 GLINK_EVENT_CH_OPEN,
182 cfg_ptr->name,
183 cfg_ptr->transport,
184 cfg_ptr->remote_ss,
185 status );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800186 }
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700187 else
188 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800189 *handle = NULL;
Steven Cahailb850bb62015-08-21 14:39:38 -0600190 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_OPEN,
Steven Cahaile41e9a02015-08-20 11:10:16 -0600191 cfg_ptr->name,
192 cfg_ptr->transport,
193 cfg_ptr->remote_ss,
194 status );
Steven Cahailb850bb62015-08-21 14:39:38 -0600195 }
196
197
Sridhar Parasurambf391322015-01-23 09:29:07 -0800198
Sridhar Parasurambf391322015-01-23 09:29:07 -0800199 return status;
200 }
Sridhar Parasurambf391322015-01-23 09:29:07 -0800201
202/**
203 * Closes the GLink logical channel specified by the handle.
204 *
205 * @param[in] handle GLink handle associated with the logical channel
206 *
207 * @return Standard GLink error codes
208 *
209 * @sideeffects Closes local end of the channel and informs remote host
210 */
211glink_err_type glink_close
212(
213 glink_handle_type handle
214)
215{
216 glink_err_type status;
Steven Cahailb850bb62015-08-21 14:39:38 -0600217 glink_core_xport_ctx_type *xport_ctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800218
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700219 if(handle == NULL)
220 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600221 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_CLOSE, "", "", "",
222 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800223 return GLINK_STATUS_INVALID_PARAM;
224 }
225
Steven Cahail895a0da2015-08-24 15:26:37 -0600226 /* get xport context after NULL check */
227 xport_ctx = handle->if_ptr->glink_core_priv;
228
229 ASSERT( xport_ctx != NULL );
Steven Cahail964ff2f2015-08-20 19:01:56 -0600230
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700231 /* grab lock to change/check channel state atomically */
Steven Cahailef08a382015-08-24 17:11:51 -0600232 glink_os_cs_acquire( &xport_ctx->channel_q_cs );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700233
234 /* Check to see if closed called again for same channel */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600235 if (handle->local_state != GLINK_LOCAL_CH_OPENED &&
236 handle->local_state != GLINK_LOCAL_CH_OPENING)
Sridhar Parasurambf391322015-01-23 09:29:07 -0800237 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600238 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_CLOSE,
239 handle->name,
240 xport_ctx->xport,
241 xport_ctx->remote_ss,
242 handle->local_state );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700243
Steven Cahailef08a382015-08-24 17:11:51 -0600244 glink_os_cs_release(&xport_ctx->channel_q_cs);
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700245
Steven Cahailb850bb62015-08-21 14:39:38 -0600246 return GLINK_STATUS_CH_ALREADY_CLOSED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800247 }
248
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700249 handle->local_state = GLINK_LOCAL_CH_CLOSING;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800250
Steven Cahail895a0da2015-08-24 15:26:37 -0600251 if (handle->remote_state == GLINK_REMOTE_CH_SSR_RESET ||
252 glinki_xport_linkup(handle->if_ptr) == FALSE)
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700253 {
Steven Cahail895a0da2015-08-24 15:26:37 -0600254 /* SSR happened on remote-SS OR XPORT link is down. Fake close_ack from here */
Steven Cahailef08a382015-08-24 17:11:51 -0600255 glink_os_cs_release( &xport_ctx->channel_q_cs);
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700256
257 handle->if_ptr->glink_core_if_ptr->rx_cmd_ch_close_ack( handle->if_ptr,
258 handle->lcid );
259
260 status = GLINK_STATUS_SUCCESS;
261 }
262 else
263 {
Steven Cahailef08a382015-08-24 17:11:51 -0600264 glink_os_cs_release(&xport_ctx->channel_q_cs);
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700265
266 status = handle->if_ptr->tx_cmd_ch_close(handle->if_ptr, handle->lcid);
267
Steven Cahailb850bb62015-08-21 14:39:38 -0600268 GLINK_LOG_EVENT( handle,
269 GLINK_EVENT_CH_CLOSE,
270 handle->name,
271 xport_ctx->xport,
272 xport_ctx->remote_ss,
273 status );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700274 }
275
Sridhar Parasurambf391322015-01-23 09:29:07 -0800276 return status;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800277}
278
279/**
280 * Transmit the provided buffer over GLink.
281 *
282 * @param[in] handle GLink handle associated with the logical channel
283 *
284 * @param[in] *pkt_priv Per packet private data
285 *
286 * @param[in] *data Pointer to the data buffer to be transmitted
287 *
288 * @param[in] size Size of buffer
289 *
290 * @param[in] req_intent Whether to block and request for remote rx intent in
291 * case it is not available for this pkt tx
292 *
293 * @return Standard GLink error codes
294 *
295 * @sideeffects Causes remote host to wake-up and process rx pkt
296 */
297glink_err_type glink_tx
298(
299 glink_handle_type handle,
300 const void *pkt_priv,
301 const void *data,
302 size_t size,
303 uint32 options
304)
305{
306 return glink_txv(handle, pkt_priv, (void*)data, size,
307 &glink_dummy_tx_vprovider, NULL, options);
308
309}
310
311/**
312 * Transmit the provided vector buffer over GLink.
313 *
314 * @param[in] handle GLink handle associated with the logical channel
315 *
316 * @param[in] *pkt_priv Per packet private data
317 *
318 * @param[in] *iovec Pointer to the vector buffer to be transmitted
319 *
320 * @param[in] size Size of buffer
321 *
322 * @param[in] vprovider Buffer provider for virtual space
323 *
324 * @param[in] pprovider Buffer provider for physical space
325 *
326 * @param[in] req_intent Whether to block and request for remote rx intent in
327 * case it is not available for this pkt tx
328 *
329 * @return Standard GLink error codes
330 *
331 * @sideeffects Causes remote host to wake-up and process rx pkt
332 */
333glink_err_type glink_txv
334(
335 glink_handle_type handle,
336 const void *pkt_priv,
337 void *iovec,
338 size_t size,
339 glink_buffer_provider_fn vprovider,
340 glink_buffer_provider_fn pprovider,
341 uint32 options
342)
343{
344 glink_err_type status;
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700345 glink_core_tx_pkt_type *pctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800346 boolean req_intent = options & GLINK_TX_REQ_INTENT;
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700347
348 glink_core_xport_ctx_type *xport_ctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800349
350 /* Input validation */
351 if(handle == NULL || iovec == NULL || size == 0 ||
Steven Cahail964ff2f2015-08-20 19:01:56 -0600352 (vprovider == NULL && pprovider == NULL))
353 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600354 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_TX, "", "", "",
355 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800356 return GLINK_STATUS_INVALID_PARAM;
357 }
358
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700359 xport_ctx = handle->if_ptr->glink_core_priv;
360
Steven Cahail964ff2f2015-08-20 19:01:56 -0600361 if (!glinki_channel_fully_opened(handle))
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700362 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600363 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_TX,
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700364 handle->name,
365 xport_ctx->xport,
366 xport_ctx->remote_ss,
Steven Cahailb850bb62015-08-21 14:39:38 -0600367 GLINK_STATUS_CH_NOT_FULLY_OPENED );
368 return GLINK_STATUS_CH_NOT_FULLY_OPENED;
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700369 }
370
371 pctx = glink_os_calloc( sizeof( glink_core_tx_pkt_type ) );
372
373 if (pctx == NULL)
Sridhar Parasurambf391322015-01-23 09:29:07 -0800374 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600375 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_TX,
376 handle->name,
377 xport_ctx->xport,
378 xport_ctx->remote_ss,
379 GLINK_STATUS_OUT_OF_RESOURCES );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700380 return GLINK_STATUS_OUT_OF_RESOURCES;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800381 }
382
383 /* Protect the entire tx operation under a lock as a client may call
384 tx in different thread context */
385 glink_os_cs_acquire(&handle->tx_cs);
386
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700387 pctx->pkt_priv = pkt_priv;
388 pctx->size = size;
389 pctx->size_remaining = size;
390 pctx->vprovider = vprovider;
391 pctx->pprovider = pprovider;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800392
393 if (vprovider == &glink_dummy_tx_vprovider)
394 {
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700395 pctx->data = (void*)iovec;
396 pctx->iovec = pctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800397 }
398 else
399 {
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700400 pctx->data = (void*)iovec;
401 pctx->iovec = iovec;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800402 }
403
Steven Cahail964ff2f2015-08-20 19:01:56 -0600404#ifdef FEATURE_TRACER_PACKET
405 pctx->tracer_pkt = options & GLINK_TX_TRACER_PKT ? TRUE : FALSE;
406 if( pctx->tracer_pkt )
407 {
408 glink_tracer_packet_log_pctx_pkt( pctx, GLINK_CORE_TX );
409 }
410#endif
Sridhar Parasurambf391322015-01-23 09:29:07 -0800411
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700412 status = xport_ctx->channel_submit_pkt(handle, pctx, req_intent);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800413
Steven Cahailb850bb62015-08-21 14:39:38 -0600414 /*Update the channel stats*/
415 GLINK_UPDATE_CHANNEL_STATS( handle->ch_stats, tx_request, size);
416
417 GLINK_LOG_EVENT( handle,
418 GLINK_EVENT_CH_TX,
419 handle->name,
420 xport_ctx->xport,
421 xport_ctx->remote_ss,
422 status);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800423
424 glink_os_cs_release(&handle->tx_cs);
425 return status;
426}
427
428/**
429 * Queue one or more Rx intent for the logical GPIC Link channel.
430 *
431 * @param[in] handle GLink handle associated with the logical channel
432 *
433 * @param[in] *pkt_priv Per packet private data
434 *
435 * @param[in] size Size of buffer
436 *
437 * @return Standard GLink error codes
438 *
439 * @sideeffects GLink XAL allocates rx buffers for receiving packets
440 */
441glink_err_type glink_queue_rx_intent
442(
443 glink_handle_type handle,
444 const void *pkt_priv,
445 size_t size
446)
447{
448 glink_err_type status;
449 glink_rx_intent_type *lc_intent;
Steven Cahail964ff2f2015-08-20 19:01:56 -0600450 glink_core_xport_ctx_type *xport_ctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800451 size_t tmp;
452
453 /* Input validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600454 if(handle == NULL || size == 0)
455 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600456 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_Q_RX_INTENT, "", "", "",
457 GLINK_STATUS_INVALID_PARAM);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800458 return GLINK_STATUS_INVALID_PARAM;
459 }
460
Steven Cahail964ff2f2015-08-20 19:01:56 -0600461 xport_ctx = handle->if_ptr->glink_core_priv;
462
Sridhar Parasurambf391322015-01-23 09:29:07 -0800463 /* short circuit for intentless mode */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600464 if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS)
465 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600466 return GLINK_STATUS_API_NOT_SUPPORTED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800467 }
468
Steven Cahail964ff2f2015-08-20 19:01:56 -0600469 if (!glinki_channel_fully_opened(handle))
Sridhar Parasurambf391322015-01-23 09:29:07 -0800470 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600471 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_Q_RX_INTENT,
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700472 handle->name,
473 xport_ctx->xport,
474 xport_ctx->remote_ss,
Steven Cahailb850bb62015-08-21 14:39:38 -0600475 GLINK_STATUS_CH_NOT_FULLY_OPENED );
476 return GLINK_STATUS_CH_NOT_FULLY_OPENED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800477 }
478
479 /* Allocate an intent structure */
480 lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
Steven Cahail964ff2f2015-08-20 19:01:56 -0600481 if(lc_intent == NULL)
482 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600483 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_Q_RX_INTENT,
484 handle->name,
485 xport_ctx->xport,
486 xport_ctx->remote_ss,
487 GLINK_STATUS_OUT_OF_RESOURCES );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800488 return GLINK_STATUS_OUT_OF_RESOURCES;
489 }
490
Sridhar Parasurambf391322015-01-23 09:29:07 -0800491 /* Call transport API to allocate rx intent buffer */
492 status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
Steven Cahail964ff2f2015-08-20 19:01:56 -0600493 if(status != GLINK_STATUS_SUCCESS)
494 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800495 glink_os_free(lc_intent);
Steven Cahailb850bb62015-08-21 14:39:38 -0600496 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_Q_RX_INTENT,
497 handle->name,
498 xport_ctx->xport,
499 xport_ctx->remote_ss,
500 status );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800501 return status;
502 }
503
504 if (handle->notify_rxv == NULL &&
Steven Cahail964ff2f2015-08-20 19:01:56 -0600505 (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size))
506 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800507 /* Allocate bounce buffer for non-vectored Rx */
508 lc_intent->data = glink_os_malloc(size);
509
Steven Cahail964ff2f2015-08-20 19:01:56 -0600510 if(lc_intent->data == NULL)
511 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800512 handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
513 glink_os_free(lc_intent);
Steven Cahailb850bb62015-08-21 14:39:38 -0600514 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_Q_RX_INTENT,
515 handle->name,
516 xport_ctx->xport,
517 xport_ctx->remote_ss,
518 GLINK_STATUS_OUT_OF_RESOURCES );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800519 return GLINK_STATUS_OUT_OF_RESOURCES;
520 }
521 }
522
Steven Cahail964ff2f2015-08-20 19:01:56 -0600523 glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);
524
Sridhar Parasurambf391322015-01-23 09:29:07 -0800525 /* push the intent on local queue. Do this before calling tx cmd
526 as transport may try to read data into the newly queued rx_buffer */
527 lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
528 lc_intent->size = size;
529 lc_intent->pkt_priv = pkt_priv;
Steven Cahail964ff2f2015-08-20 19:01:56 -0600530 glinki_enqueue_item(&handle->pintents->local_intent_q,
531 lc_intent,
532 &handle->pintents->intent_q_cs);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800533
534 /* Call transport API to queue rx intent */
535 /* Increment the local intent ID counter associated with this channel */
536 handle->if_ptr->glink_core_priv->liid++;
537
538 status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
539 handle->lcid, size, lc_intent->iid);
Steven Cahail964ff2f2015-08-20 19:01:56 -0600540 if(status != GLINK_STATUS_SUCCESS)
541 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800542 /* Failure */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600543 glinki_dequeue_item(&handle->pintents->local_intent_q,
544 lc_intent,
545 &handle->pintents->intent_q_cs);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800546
547 handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
548 glink_os_free(lc_intent->data);
549 glink_os_free(lc_intent);
550 }
551 glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
552
Steven Cahailb850bb62015-08-21 14:39:38 -0600553 GLINK_LOG_EVENT( handle,
554 GLINK_EVENT_CH_Q_RX_INTENT,
555 handle->name,
556 xport_ctx->xport,
557 xport_ctx->remote_ss,
558 status );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800559 return status;
560}
561
562/**
563 * Client uses this to signal to GLink layer that it is done with the received
564 * data buffer. This API should be called to free up the receive buffer, which,
565 * in zero-copy mode is actually remote-side's transmit buffer.
566 *
567 * @param[in] handle GLink handle associated with the logical channel
568 *
569 * @param[in] *ptr Pointer to the received buffer
570 *
571 * @param[in] reuse Reuse intent
572 *
573 * @return Standard GLink error codes
574 *
575 * @sideeffects GLink XAL frees the Rx buffer
576 */
577glink_err_type glink_rx_done
578(
579 glink_handle_type handle,
580 const void *ptr,
581 boolean reuse
582)
583{
584 glink_rx_intent_type *lc_intent;
585 glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
586
587 /* Input validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600588 if(handle == NULL || ptr == NULL)
589 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600590 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_RX_DONE, "", "", "",
591 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800592 return GLINK_STATUS_INVALID_PARAM;
593 }
594
595 /* short circuit for intentless mode */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600596 if (xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS)
597 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600598 return GLINK_STATUS_API_NOT_SUPPORTED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800599 }
600
Steven Cahail964ff2f2015-08-20 19:01:56 -0600601 if (!glinki_channel_fully_opened(handle))
Sridhar Parasurambf391322015-01-23 09:29:07 -0800602 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600603 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_RX_DONE,
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700604 handle->name,
605 xport_ctx->xport,
606 xport_ctx->remote_ss,
Steven Cahailb850bb62015-08-21 14:39:38 -0600607 GLINK_STATUS_CH_NOT_FULLY_OPENED );
608 return GLINK_STATUS_CH_NOT_FULLY_OPENED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800609 }
610
611 /* Free the intent */
612 lc_intent = smem_list_first(&handle->pintents->local_intent_client_q);
Steven Cahail964ff2f2015-08-20 19:01:56 -0600613 while(lc_intent != NULL)
614 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800615 size_t tmp;
616
617 if(lc_intent->iovec == ptr || (handle->notify_rxv == NULL &&
618 (lc_intent->data == ptr ||
Steven Cahail964ff2f2015-08-20 19:01:56 -0600619 ptr == lc_intent->vprovider(lc_intent->iovec, 0, &tmp))))
620 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800621
622 uint32 iid;
623
624 /* Found intent, delete it */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600625 glinki_dequeue_item(&handle->pintents->local_intent_client_q,
626 lc_intent,
627 &handle->pintents->intent_q_cs);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800628
629 iid = lc_intent->iid;
630
Steven Cahailb850bb62015-08-21 14:39:38 -0600631 GLINK_UPDATE_CHANNEL_STATS( handle->ch_stats, rx_done, lc_intent->pkt_sz);
632
Sridhar Parasurambf391322015-01-23 09:29:07 -0800633 if (reuse)
634 {
635 lc_intent->used = 0;
636
Steven Cahail964ff2f2015-08-20 19:01:56 -0600637 glinki_enqueue_item(&handle->pintents->local_intent_q,
638 lc_intent,
639 &handle->pintents->intent_q_cs);
640
Sridhar Parasurambf391322015-01-23 09:29:07 -0800641 }
642 else
643 {
644 /* Free the intent */
645 handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
Steven Cahail964ff2f2015-08-20 19:01:56 -0600646 if(lc_intent->data)
647 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800648 /* Free the bounce buffer if we had allocated one */
649 glink_os_free(lc_intent->data);
650 }
651 glink_os_free(lc_intent);
652 }
653
654 /* Note that the actual buffer, lc_intent->data, was allocated by the
655 * transport and should be freed by the xport. We should not touch it */
656 /* Let the xport know we are done with the buffer */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600657 handle->if_ptr->tx_cmd_local_rx_done(handle->if_ptr,
658 handle->lcid,
659 iid,
660 reuse);
Sridhar Parasurambf391322015-01-23 09:29:07 -0800661
Steven Cahailb850bb62015-08-21 14:39:38 -0600662 GLINK_LOG_EVENT( handle,
663 GLINK_EVENT_CH_RX_DONE,
664 handle->name,
665 xport_ctx->xport,
666 xport_ctx->remote_ss,
667 GLINK_STATUS_SUCCESS );
668
Sridhar Parasurambf391322015-01-23 09:29:07 -0800669 return GLINK_STATUS_SUCCESS;
670 }
671 lc_intent = smem_list_next(lc_intent);
672 }
673
Steven Cahailb850bb62015-08-21 14:39:38 -0600674 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_RX_DONE,
675 handle->name,
676 xport_ctx->xport,
677 xport_ctx->remote_ss,
678 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800679 return GLINK_STATUS_INVALID_PARAM;
680}
681
682/**
683 * Set the 32 bit control signal field. Depending on the transport, it may
684 * take appropriate actions on the set bit-mask, or transmit the entire
685 * 32-bit value to the remote host.
686 *
687 * @param[in] handle GLink handle associated with the logical channel
688 *
689 * @param[in] sig_value 32 bit signal word
690 *
691 * @return Standard GLink error codes
692 *
693 * @sideeffects None
694 */
695glink_err_type glink_sigs_set
696(
697 glink_handle_type handle,
698 uint32 sig_value
699)
700{
Steven Cahailb850bb62015-08-21 14:39:38 -0600701 glink_core_xport_ctx_type *xport_ctx;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800702 glink_err_type status;
703
704 /* Input validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600705 if(handle == NULL)
706 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600707 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_SIG_SET, "", "", "",
708 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800709 return GLINK_STATUS_INVALID_PARAM;
710 }
711
Steven Cahailb850bb62015-08-21 14:39:38 -0600712 xport_ctx = handle->if_ptr->glink_core_priv;
713
714 ASSERT( xport_ctx != NULL );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700715
Steven Cahail964ff2f2015-08-20 19:01:56 -0600716 if (!glinki_channel_fully_opened(handle))
Sridhar Parasurambf391322015-01-23 09:29:07 -0800717 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600718 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_SIG_SET,
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700719 handle->name,
720 xport_ctx->xport,
721 xport_ctx->remote_ss,
Steven Cahailb850bb62015-08-21 14:39:38 -0600722 GLINK_STATUS_CH_NOT_FULLY_OPENED );
Sridhar Parasuram3b058122015-05-11 16:15:03 -0700723
Steven Cahailb850bb62015-08-21 14:39:38 -0600724 return GLINK_STATUS_CH_NOT_FULLY_OPENED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800725 }
726
Steven Cahail964ff2f2015-08-20 19:01:56 -0600727 status = handle->if_ptr->tx_cmd_set_sigs(handle->if_ptr,
728 handle->lcid,
Sridhar Parasurambf391322015-01-23 09:29:07 -0800729 sig_value);
Steven Cahail964ff2f2015-08-20 19:01:56 -0600730 if(GLINK_STATUS_SUCCESS == status)
731 {
Sridhar Parasurambf391322015-01-23 09:29:07 -0800732 /* Update local copy of local control signal state */
733 handle->local_sigs = sig_value;
734 }
735
736 return status;
737}
738
739/**
740 * Get the local 32 bit control signal bit-field.
741 *
742 * @param[in] handle GLink handle associated with the logical channel
743 *
744 * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
745 *
746 * @return Standard GLink error codes
747 *
748 * @sideeffects None
749 */
750glink_err_type glink_sigs_local_get
751(
752 glink_handle_type handle,
753 uint32 *sig_value
754)
755{
756 /* Input validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600757 if(handle == NULL || sig_value == NULL)
758 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600759 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_SIG_L_GET, "", "", "",
760 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800761 return GLINK_STATUS_INVALID_PARAM;
762 }
763
764 *sig_value = handle->local_sigs;
765
766 return GLINK_STATUS_SUCCESS;
767}
768
769/**
770 * Get the remote 32 bit control signal bit-field.
771 *
772 * @param[in] handle GLink handle associated with the logical channel
773 *
774 * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
775 *
776 * @return Standard GLink error codes
777 *
778 * @sideeffects None
779 */
780glink_err_type glink_sigs_remote_get
781(
782 glink_handle_type handle,
783 uint32 *sig_value
784)
785{
786 /* Input validation */
Steven Cahail964ff2f2015-08-20 19:01:56 -0600787 if(handle == NULL || sig_value == NULL)
788 {
Steven Cahailb850bb62015-08-21 14:39:38 -0600789 GLINK_LOG_ERROR_EVENT( GLINK_EVENT_CH_SIG_R_GET, "", "", "",
790 GLINK_STATUS_INVALID_PARAM );
Sridhar Parasurambf391322015-01-23 09:29:07 -0800791 return GLINK_STATUS_INVALID_PARAM;
792 }
793
794 *sig_value = handle->remote_sigs;
795
796 return GLINK_STATUS_SUCCESS;
797}
798
Steven Cahail964ff2f2015-08-20 19:01:56 -0600799/**
800 * Regsiters a client specified callback to be invoked when the specified
801 * transport (link) is up/down.
802 *
803 * @param[in] link_id Pointer to the configuration structure for the
804 * xport(link) to be monitored. See glink.h
805 * @param[in] priv Callback data returned to client when callback
806 * is invoked.
807 *
808 * @return Standard GLink error codes
809 *
810 * @sideeffects Puts the callback in a queue which gets scanned when a
811 * transport(link) comes up OR an SSR happnes.
812 */
813glink_err_type glink_register_link_state_cb
814(
815 glink_link_id_type *link_id,
816 void* priv
817)
818{
819 glink_link_notif_data_type* link_notif_data;
820 unsigned int remote_host;
821
822 /* Input validation */
823 if (link_id == NULL ||
824 link_id->version != GLINK_LINK_ID_VER ||
825 link_id->link_notifier == NULL)
826 {
827 return GLINK_STATUS_INVALID_PARAM;
828 }
829
830 /* Check for remote_ss validity */
831 if (link_id->remote_ss != NULL)
832 {
833 remote_host = glinki_find_remote_host(link_id->remote_ss);
834 if (remote_host == GLINK_NUM_HOSTS)
835 {
836 return GLINK_STATUS_INVALID_PARAM;
837 }
838 }
839
840 /* Save the callback on the notification list */
841 if((link_notif_data = glink_os_calloc(sizeof(glink_link_notif_data_type)))
842 == NULL)
843 {
844 return GLINK_STATUS_OUT_OF_RESOURCES;
845 }
846
847 link_notif_data->xport = link_id->xport;
848 link_notif_data->remote_ss = link_id->remote_ss;
849 link_notif_data->link_notifier = link_id->link_notifier;
850 link_notif_data->priv = priv; /* private client data */
851
852 /* Append the request to the list for link UP/DOWN notifications */
853 glinki_register_link_notif_data(link_notif_data);
854 link_id->handle = (glink_link_handle_type)link_notif_data;
855
856 /* Scan the list of available transport to see if this link is already up */
857 glinki_scan_xports_and_notify(link_notif_data);
858
859 return GLINK_STATUS_SUCCESS;
860}
861
862/**
863 * Degsiter the link UP/DOWN notification callback associated with the
864 * provided handle.
865 *
866 * @param[in] handle Callback handler returned by
867 * glink_register_link_state_cb
868 *
869 * @return Standard GLink error codes
870 *
871 * @sideeffects Removes the callback in a queue which gets scanned when a
872 * transport(link) comes up OR an SSR happnes.
873 */
874glink_err_type glink_deregister_link_state_cb
875(
876 glink_link_handle_type handle
877)
878{
879 /* check if glink handle is NULL and return appropriate
880 return code */
881 if(handle == NULL)
882 {
883 return GLINK_STATUS_INVALID_PARAM;
884 }
885
886 glinki_deregister_link_notif_data((glink_link_notif_data_type *)handle);
887
888 glink_os_free(handle);
889
890 return GLINK_STATUS_SUCCESS;
891}
892
Sridhar Parasurambf391322015-01-23 09:29:07 -0800893/*================= RESTRICTED API ==========================*/
894
895/**
896 * This API allows the RPM client to poll the transport for any new data
897 * that might have come in. It would *usually* be used when incoming interrupts
898 * are disabled.
899 *
900 * @param[in] handle GLink handle associated with the logical channel
901 *
902 * @return Standard GLink error codes
903 *
904 * @sideeffects None
905 */
906glink_err_type glink_rpm_rx_poll
907(
908 glink_handle_type handle
909)
910{
Steven Cahail964ff2f2015-08-20 19:01:56 -0600911 if (!handle)
912 {
913 return GLINK_STATUS_INVALID_PARAM;
914 }
Sridhar Parasurambf391322015-01-23 09:29:07 -0800915
916 if(handle->if_ptr->poll) {
917 return handle->if_ptr->poll(handle->if_ptr);
918 }
Steven Cahailb850bb62015-08-21 14:39:38 -0600919 return GLINK_STATUS_API_NOT_SUPPORTED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800920}
921
922/**
923 * This API allows the RPM client to mask/unmask rx interrupts
924 *
925 * @param[in] handle GLink handle associated with the logical channel
926 *
927 * @param[in] mask Whether to mask or un-mask the incoming interrupt
928 *
929 * @param[in] platform_struct Any platform specific into that transport may
930 require
931 *
932 * @return Standard GLink error codes
933 *
934 * @sideeffects None
935 */
936glink_err_type glink_rpm_mask_rx_interrupt
937(
938 glink_handle_type handle,
939 boolean mask,
940 void *platform_struct
941)
942{
Steven Cahail964ff2f2015-08-20 19:01:56 -0600943 if (!handle)
944 {
945 return GLINK_STATUS_INVALID_PARAM;
946 }
Sridhar Parasurambf391322015-01-23 09:29:07 -0800947
948 if(handle->if_ptr->mask_rx_irq) {
949 return handle->if_ptr->mask_rx_irq(handle->if_ptr, mask);
950 }
Steven Cahailb850bb62015-08-21 14:39:38 -0600951 return GLINK_STATUS_API_NOT_SUPPORTED;
Sridhar Parasurambf391322015-01-23 09:29:07 -0800952}
953
954/**
955 * This API waits until link is down.
956 *
957 * @param[in] handle GLink handle associated with the logical channel
958 *
959 * @return Standard GLink error codes
960 *
961 * @sideeffects None
962 */
963glink_err_type glink_wait_link_down
964(
965 glink_handle_type handle
966)
967{
968 ASSERT(handle && handle->if_ptr && handle->if_ptr->wait_link_down);
969
970 return handle->if_ptr->wait_link_down(handle->if_ptr) ?
971 GLINK_STATUS_SUCCESS : GLINK_STATUS_FAILURE;
972}