vchiq_core.h revision 278431
1278277Sgonzo/** 2278277Sgonzo * Copyright (c) 2010-2012 Broadcom. All rights reserved. 3278277Sgonzo * 4278277Sgonzo * Redistribution and use in source and binary forms, with or without 5278277Sgonzo * modification, are permitted provided that the following conditions 6278277Sgonzo * are met: 7278277Sgonzo * 1. Redistributions of source code must retain the above copyright 8278277Sgonzo * notice, this list of conditions, and the following disclaimer, 9278277Sgonzo * without modification. 10278277Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11278277Sgonzo * notice, this list of conditions and the following disclaimer in the 12278277Sgonzo * documentation and/or other materials provided with the distribution. 13278277Sgonzo * 3. The names of the above-listed copyright holders may not be used 14278277Sgonzo * to endorse or promote products derived from this software without 15278277Sgonzo * specific prior written permission. 16278277Sgonzo * 17278277Sgonzo * ALTERNATIVELY, this software may be distributed under the terms of the 18278277Sgonzo * GNU General Public License ("GPL") version 2, as published by the Free 19278277Sgonzo * Software Foundation. 20278277Sgonzo * 21278277Sgonzo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22278277Sgonzo * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23278277Sgonzo * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24278277Sgonzo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25278277Sgonzo * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26278277Sgonzo * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27278277Sgonzo * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28278277Sgonzo * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29278277Sgonzo * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30278277Sgonzo * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31278277Sgonzo * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32278277Sgonzo */ 33278277Sgonzo 34278277Sgonzo#ifndef VCHIQ_CORE_H 35278277Sgonzo#define VCHIQ_CORE_H 36278277Sgonzo 37278277Sgonzo#include <interface/compat/vchi_bsd.h> 38278277Sgonzo#include <interface/compat/list.h> 39278277Sgonzo 40278277Sgonzo#include "vchiq_cfg.h" 41278277Sgonzo 42278277Sgonzo#include "vchiq.h" 43278277Sgonzo 44278277Sgonzo/* Run time control of log level, based on KERN_XXX level. */ 45278277Sgonzo#ifndef VCHIQ_LOG_DEFAULT 46278277Sgonzo#define VCHIQ_LOG_DEFAULT 4 47278277Sgonzo#endif 48278277Sgonzo#define VCHIQ_LOG_ERROR 3 49278277Sgonzo#define VCHIQ_LOG_WARNING 4 50278277Sgonzo#define VCHIQ_LOG_INFO 6 51278277Sgonzo#define VCHIQ_LOG_TRACE 7 52278277Sgonzo 53278277Sgonzo#define VCHIQ_LOG_PREFIX "vchiq: " 54278277Sgonzo 55278277Sgonzo#ifndef vchiq_log_error 56278277Sgonzo#define vchiq_log_error(cat, fmt, ...) \ 57278277Sgonzo do { if (cat >= VCHIQ_LOG_ERROR) \ 58278277Sgonzo printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) 59278277Sgonzo#endif 60278277Sgonzo#ifndef vchiq_log_warning 61278277Sgonzo#define vchiq_log_warning(cat, fmt, ...) \ 62278277Sgonzo do { if (cat >= VCHIQ_LOG_WARNING) \ 63278277Sgonzo printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) 64278277Sgonzo#endif 65278277Sgonzo#ifndef vchiq_log_info 66278277Sgonzo#define vchiq_log_info(cat, fmt, ...) \ 67278277Sgonzo do { if (cat >= VCHIQ_LOG_INFO) \ 68278277Sgonzo printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) 69278277Sgonzo#endif 70278277Sgonzo#ifndef vchiq_log_trace 71278277Sgonzo#define vchiq_log_trace(cat, fmt, ...) \ 72278277Sgonzo do { if (cat >= VCHIQ_LOG_TRACE) \ 73278277Sgonzo printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) 74278277Sgonzo#endif 75278277Sgonzo 76278277Sgonzo#define vchiq_loud_error(...) \ 77278277Sgonzo vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__) 78278277Sgonzo 79278277Sgonzo#ifndef vchiq_static_assert 80278277Sgonzo#define vchiq_static_assert(cond) __attribute__((unused)) \ 81278277Sgonzo extern int vchiq_static_assert[(cond) ? 1 : -1] 82278277Sgonzo#endif 83278277Sgonzo 84278277Sgonzo#define IS_POW2(x) (x && ((x & (x - 1)) == 0)) 85278277Sgonzo 86278277Sgonzo/* Ensure that the slot size and maximum number of slots are powers of 2 */ 87278277Sgonzovchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE)); 88278277Sgonzovchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS)); 89278277Sgonzovchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); 90278277Sgonzo 91278277Sgonzo#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) 92278277Sgonzo#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) 93278277Sgonzo#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \ 94278277Sgonzo VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE) 95278277Sgonzo 96278277Sgonzo#define VCHIQ_MSG_PADDING 0 /* - */ 97278277Sgonzo#define VCHIQ_MSG_CONNECT 1 /* - */ 98278277Sgonzo#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ 99278277Sgonzo#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ 100278277Sgonzo#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ 101278277Sgonzo#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ 102278277Sgonzo#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ 103278277Sgonzo#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ 104278277Sgonzo#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ 105278277Sgonzo#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ 106278277Sgonzo#define VCHIQ_MSG_PAUSE 10 /* - */ 107278277Sgonzo#define VCHIQ_MSG_RESUME 11 /* - */ 108278277Sgonzo#define VCHIQ_MSG_REMOTE_USE 12 /* - */ 109278277Sgonzo#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ 110278277Sgonzo#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ 111278277Sgonzo 112278277Sgonzo#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) 113278277Sgonzo#define VCHIQ_PORT_FREE 0x1000 114278277Sgonzo#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE) 115278277Sgonzo#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ 116278277Sgonzo ((type<<24) | (srcport<<12) | (dstport<<0)) 117278277Sgonzo#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24) 118278277Sgonzo#define VCHIQ_MSG_SRCPORT(msgid) \ 119278277Sgonzo (unsigned short)(((unsigned int)msgid >> 12) & 0xfff) 120278277Sgonzo#define VCHIQ_MSG_DSTPORT(msgid) \ 121278277Sgonzo ((unsigned short)msgid & 0xfff) 122278277Sgonzo 123278277Sgonzo#define VCHIQ_FOURCC_AS_4CHARS(fourcc) \ 124278277Sgonzo ((fourcc) >> 24) & 0xff, \ 125278277Sgonzo ((fourcc) >> 16) & 0xff, \ 126278277Sgonzo ((fourcc) >> 8) & 0xff, \ 127278277Sgonzo (fourcc) & 0xff 128278277Sgonzo 129278277Sgonzo/* Ensure the fields are wide enough */ 130278277Sgonzovchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) 131278277Sgonzo == 0); 132278277Sgonzovchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); 133278277Sgonzovchiq_static_assert((unsigned int)VCHIQ_PORT_MAX < 134278277Sgonzo (unsigned int)VCHIQ_PORT_FREE); 135278277Sgonzo 136278277Sgonzo#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) 137278277Sgonzo#define VCHIQ_MSGID_CLAIMED 0x40000000 138278277Sgonzo 139278277Sgonzo#define VCHIQ_FOURCC_INVALID 0x00000000 140278277Sgonzo#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID) 141278277Sgonzo 142278277Sgonzo#define VCHIQ_BULK_ACTUAL_ABORTED -1 143278277Sgonzo 144278277Sgonzotypedef uint32_t BITSET_T; 145278277Sgonzo 146278277Sgonzovchiq_static_assert((sizeof(BITSET_T) * 8) == 32); 147278277Sgonzo 148278277Sgonzo#define BITSET_SIZE(b) ((b + 31) >> 5) 149278277Sgonzo#define BITSET_WORD(b) (b >> 5) 150278277Sgonzo#define BITSET_BIT(b) (1 << (b & 31)) 151278277Sgonzo#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs)) 152278277Sgonzo#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) 153278277Sgonzo#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) 154278277Sgonzo#define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b)) 155278277Sgonzo 156278277Sgonzo#if VCHIQ_ENABLE_STATS 157278277Sgonzo#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) 158278277Sgonzo#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) 159278277Sgonzo#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ 160278277Sgonzo (service->stats. stat += addend) 161278277Sgonzo#else 162278277Sgonzo#define VCHIQ_STATS_INC(state, stat) ((void)0) 163278277Sgonzo#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) 164278277Sgonzo#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) 165278277Sgonzo#endif 166278277Sgonzo 167278277Sgonzoenum { 168278277Sgonzo DEBUG_ENTRIES, 169278277Sgonzo#if VCHIQ_ENABLE_DEBUG 170278277Sgonzo DEBUG_SLOT_HANDLER_COUNT, 171278277Sgonzo DEBUG_SLOT_HANDLER_LINE, 172278277Sgonzo DEBUG_PARSE_LINE, 173278277Sgonzo DEBUG_PARSE_HEADER, 174278277Sgonzo DEBUG_PARSE_MSGID, 175278277Sgonzo DEBUG_AWAIT_COMPLETION_LINE, 176278277Sgonzo DEBUG_DEQUEUE_MESSAGE_LINE, 177278277Sgonzo DEBUG_SERVICE_CALLBACK_LINE, 178278277Sgonzo DEBUG_MSG_QUEUE_FULL_COUNT, 179278277Sgonzo DEBUG_COMPLETION_QUEUE_FULL_COUNT, 180278277Sgonzo#endif 181278277Sgonzo DEBUG_MAX 182278277Sgonzo}; 183278277Sgonzo 184278277Sgonzo#if VCHIQ_ENABLE_DEBUG 185278277Sgonzo 186278277Sgonzo#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; 187278277Sgonzo#define DEBUG_TRACE(d) \ 188278277Sgonzo do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) 189278277Sgonzo#define DEBUG_VALUE(d, v) \ 190278277Sgonzo do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) 191278277Sgonzo#define DEBUG_COUNT(d) \ 192278277Sgonzo do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) 193278277Sgonzo 194278277Sgonzo#else /* VCHIQ_ENABLE_DEBUG */ 195278277Sgonzo 196278277Sgonzo#define DEBUG_INITIALISE(local) 197278277Sgonzo#define DEBUG_TRACE(d) 198278277Sgonzo#define DEBUG_VALUE(d, v) 199278277Sgonzo#define DEBUG_COUNT(d) 200278277Sgonzo 201278277Sgonzo#endif /* VCHIQ_ENABLE_DEBUG */ 202278277Sgonzo 203278277Sgonzotypedef enum { 204278277Sgonzo VCHIQ_CONNSTATE_DISCONNECTED, 205278277Sgonzo VCHIQ_CONNSTATE_CONNECTING, 206278277Sgonzo VCHIQ_CONNSTATE_CONNECTED, 207278277Sgonzo VCHIQ_CONNSTATE_PAUSING, 208278277Sgonzo VCHIQ_CONNSTATE_PAUSE_SENT, 209278277Sgonzo VCHIQ_CONNSTATE_PAUSED, 210278277Sgonzo VCHIQ_CONNSTATE_RESUMING, 211278277Sgonzo VCHIQ_CONNSTATE_PAUSE_TIMEOUT, 212278277Sgonzo VCHIQ_CONNSTATE_RESUME_TIMEOUT 213278277Sgonzo} VCHIQ_CONNSTATE_T; 214278277Sgonzo 215278277Sgonzoenum { 216278277Sgonzo VCHIQ_SRVSTATE_FREE, 217278277Sgonzo VCHIQ_SRVSTATE_HIDDEN, 218278277Sgonzo VCHIQ_SRVSTATE_LISTENING, 219278277Sgonzo VCHIQ_SRVSTATE_OPENING, 220278277Sgonzo VCHIQ_SRVSTATE_OPEN, 221278277Sgonzo VCHIQ_SRVSTATE_OPENSYNC, 222278277Sgonzo VCHIQ_SRVSTATE_CLOSESENT, 223278277Sgonzo VCHIQ_SRVSTATE_CLOSERECVD, 224278277Sgonzo VCHIQ_SRVSTATE_CLOSEWAIT, 225278277Sgonzo VCHIQ_SRVSTATE_CLOSED 226278277Sgonzo}; 227278277Sgonzo 228278277Sgonzoenum { 229278277Sgonzo VCHIQ_POLL_TERMINATE, 230278277Sgonzo VCHIQ_POLL_REMOVE, 231278277Sgonzo VCHIQ_POLL_TXNOTIFY, 232278277Sgonzo VCHIQ_POLL_RXNOTIFY, 233278277Sgonzo VCHIQ_POLL_COUNT 234278277Sgonzo}; 235278277Sgonzo 236278277Sgonzotypedef enum { 237278277Sgonzo VCHIQ_BULK_TRANSMIT, 238278277Sgonzo VCHIQ_BULK_RECEIVE 239278277Sgonzo} VCHIQ_BULK_DIR_T; 240278277Sgonzo 241278277Sgonzotypedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); 242278277Sgonzo 243278277Sgonzotypedef struct vchiq_bulk_struct { 244278277Sgonzo short mode; 245278277Sgonzo short dir; 246278277Sgonzo void *userdata; 247278277Sgonzo VCHI_MEM_HANDLE_T handle; 248278277Sgonzo void *data; 249278277Sgonzo int size; 250278277Sgonzo void *remote_data; 251278277Sgonzo int remote_size; 252278277Sgonzo int actual; 253278277Sgonzo} VCHIQ_BULK_T; 254278277Sgonzo 255278277Sgonzotypedef struct vchiq_bulk_queue_struct { 256278277Sgonzo int local_insert; /* Where to insert the next local bulk */ 257278277Sgonzo int remote_insert; /* Where to insert the next remote bulk (master) */ 258278277Sgonzo int process; /* Bulk to transfer next */ 259278277Sgonzo int remote_notify; /* Bulk to notify the remote client of next (mstr) */ 260278277Sgonzo int remove; /* Bulk to notify the local client of, and remove, 261278277Sgonzo ** next */ 262278277Sgonzo VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; 263278277Sgonzo} VCHIQ_BULK_QUEUE_T; 264278277Sgonzo 265278277Sgonzotypedef struct remote_event_struct { 266278277Sgonzo int armed; 267278277Sgonzo int fired; 268278277Sgonzo struct semaphore *event; 269278277Sgonzo} REMOTE_EVENT_T; 270278277Sgonzo 271278277Sgonzotypedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; 272278277Sgonzo 273278277Sgonzotypedef struct vchiq_state_struct VCHIQ_STATE_T; 274278277Sgonzo 275278277Sgonzotypedef struct vchiq_slot_struct { 276278277Sgonzo char data[VCHIQ_SLOT_SIZE]; 277278277Sgonzo} VCHIQ_SLOT_T; 278278277Sgonzo 279278277Sgonzotypedef struct vchiq_slot_info_struct { 280278277Sgonzo /* Use two counters rather than one to avoid the need for a mutex. */ 281278277Sgonzo short use_count; 282278277Sgonzo short release_count; 283278431Sgonzo} VCHIQ_SLOT_INFO_T; 284278277Sgonzo 285278277Sgonzotypedef struct vchiq_service_struct { 286278277Sgonzo VCHIQ_SERVICE_BASE_T base; 287278277Sgonzo VCHIQ_SERVICE_HANDLE_T handle; 288278277Sgonzo unsigned int ref_count; 289278277Sgonzo int srvstate; 290278277Sgonzo VCHIQ_USERDATA_TERM_T userdata_term; 291278277Sgonzo unsigned int localport; 292278277Sgonzo unsigned int remoteport; 293278277Sgonzo int public_fourcc; 294278277Sgonzo int client_id; 295278277Sgonzo char auto_close; 296278277Sgonzo char sync; 297278277Sgonzo char closing; 298278277Sgonzo atomic_t poll_flags; 299278277Sgonzo short version; 300278277Sgonzo short version_min; 301278277Sgonzo short peer_version; 302278277Sgonzo 303278277Sgonzo VCHIQ_STATE_T *state; 304278277Sgonzo VCHIQ_INSTANCE_T instance; 305278277Sgonzo 306278277Sgonzo int service_use_count; 307278277Sgonzo 308278277Sgonzo VCHIQ_BULK_QUEUE_T bulk_tx; 309278277Sgonzo VCHIQ_BULK_QUEUE_T bulk_rx; 310278277Sgonzo 311278277Sgonzo struct semaphore remove_event; 312278277Sgonzo struct semaphore bulk_remove_event; 313278277Sgonzo struct mutex bulk_mutex; 314278277Sgonzo 315278277Sgonzo struct service_stats_struct { 316278277Sgonzo int quota_stalls; 317278277Sgonzo int slot_stalls; 318278277Sgonzo int bulk_stalls; 319278277Sgonzo int error_count; 320278277Sgonzo int ctrl_tx_count; 321278277Sgonzo int ctrl_rx_count; 322278277Sgonzo int bulk_tx_count; 323278277Sgonzo int bulk_rx_count; 324278277Sgonzo int bulk_aborted_count; 325278277Sgonzo uint64_t ctrl_tx_bytes; 326278277Sgonzo uint64_t ctrl_rx_bytes; 327278277Sgonzo uint64_t bulk_tx_bytes; 328278277Sgonzo uint64_t bulk_rx_bytes; 329278277Sgonzo } stats; 330278277Sgonzo} VCHIQ_SERVICE_T; 331278277Sgonzo 332278277Sgonzo/* The quota information is outside VCHIQ_SERVICE_T so that it can be 333278277Sgonzo statically allocated, since for accounting reasons a service's slot 334278277Sgonzo usage is carried over between users of the same port number. 335278277Sgonzo */ 336278277Sgonzotypedef struct vchiq_service_quota_struct { 337278277Sgonzo unsigned short slot_quota; 338278277Sgonzo unsigned short slot_use_count; 339278277Sgonzo unsigned short message_quota; 340278277Sgonzo unsigned short message_use_count; 341278277Sgonzo struct semaphore quota_event; 342278277Sgonzo int previous_tx_index; 343278277Sgonzo} VCHIQ_SERVICE_QUOTA_T; 344278277Sgonzo 345278277Sgonzotypedef struct vchiq_shared_state_struct { 346278277Sgonzo 347278277Sgonzo /* A non-zero value here indicates that the content is valid. */ 348278277Sgonzo int initialised; 349278277Sgonzo 350278277Sgonzo /* The first and last (inclusive) slots allocated to the owner. */ 351278277Sgonzo int slot_first; 352278277Sgonzo int slot_last; 353278277Sgonzo 354278277Sgonzo /* The slot allocated to synchronous messages from the owner. */ 355278277Sgonzo int slot_sync; 356278277Sgonzo 357278277Sgonzo /* Signalling this event indicates that owner's slot handler thread 358278277Sgonzo ** should run. */ 359278277Sgonzo REMOTE_EVENT_T trigger; 360278277Sgonzo 361278277Sgonzo /* Indicates the byte position within the stream where the next message 362278277Sgonzo ** will be written. The least significant bits are an index into the 363278277Sgonzo ** slot. The next bits are the index of the slot in slot_queue. */ 364278277Sgonzo int tx_pos; 365278277Sgonzo 366278277Sgonzo /* This event should be signalled when a slot is recycled. */ 367278277Sgonzo REMOTE_EVENT_T recycle; 368278277Sgonzo 369278277Sgonzo /* The slot_queue index where the next recycled slot will be written. */ 370278277Sgonzo int slot_queue_recycle; 371278277Sgonzo 372278277Sgonzo /* This event should be signalled when a synchronous message is sent. */ 373278277Sgonzo REMOTE_EVENT_T sync_trigger; 374278277Sgonzo 375278277Sgonzo /* This event should be signalled when a synchronous message has been 376278277Sgonzo ** released. */ 377278277Sgonzo REMOTE_EVENT_T sync_release; 378278277Sgonzo 379278277Sgonzo /* A circular buffer of slot indexes. */ 380278277Sgonzo int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; 381278277Sgonzo 382278277Sgonzo /* Debugging state */ 383278277Sgonzo int debug[DEBUG_MAX]; 384278431Sgonzo} VCHIQ_SHARED_STATE_T; 385278277Sgonzo 386278277Sgonzotypedef struct vchiq_slot_zero_struct { 387278277Sgonzo int magic; 388278277Sgonzo short version; 389278277Sgonzo short version_min; 390278277Sgonzo int slot_zero_size; 391278277Sgonzo int slot_size; 392278277Sgonzo int max_slots; 393278277Sgonzo int max_slots_per_side; 394278277Sgonzo int platform_data[2]; 395278277Sgonzo VCHIQ_SHARED_STATE_T master; 396278277Sgonzo VCHIQ_SHARED_STATE_T slave; 397278277Sgonzo VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; 398278431Sgonzo} VCHIQ_SLOT_ZERO_T; 399278277Sgonzo 400278277Sgonzostruct vchiq_state_struct { 401278277Sgonzo int id; 402278277Sgonzo int initialised; 403278277Sgonzo VCHIQ_CONNSTATE_T conn_state; 404278277Sgonzo int is_master; 405278277Sgonzo 406278277Sgonzo VCHIQ_SHARED_STATE_T *local; 407278277Sgonzo VCHIQ_SHARED_STATE_T *remote; 408278277Sgonzo VCHIQ_SLOT_T *slot_data; 409278277Sgonzo 410278277Sgonzo unsigned short default_slot_quota; 411278277Sgonzo unsigned short default_message_quota; 412278277Sgonzo 413278277Sgonzo /* Event indicating connect message received */ 414278277Sgonzo struct semaphore connect; 415278277Sgonzo 416278277Sgonzo /* Mutex protecting services */ 417278277Sgonzo struct mutex mutex; 418278277Sgonzo VCHIQ_INSTANCE_T *instance; 419278277Sgonzo 420278277Sgonzo /* Processes incoming messages */ 421278277Sgonzo VCHIQ_THREAD_T slot_handler_thread; 422278277Sgonzo 423278277Sgonzo /* Processes recycled slots */ 424278277Sgonzo VCHIQ_THREAD_T recycle_thread; 425278277Sgonzo 426278277Sgonzo /* Processes synchronous messages */ 427278277Sgonzo VCHIQ_THREAD_T sync_thread; 428278277Sgonzo 429278277Sgonzo /* Local implementation of the trigger remote event */ 430278277Sgonzo struct semaphore trigger_event; 431278277Sgonzo 432278277Sgonzo /* Local implementation of the recycle remote event */ 433278277Sgonzo struct semaphore recycle_event; 434278277Sgonzo 435278277Sgonzo /* Local implementation of the sync trigger remote event */ 436278277Sgonzo struct semaphore sync_trigger_event; 437278277Sgonzo 438278277Sgonzo /* Local implementation of the sync release remote event */ 439278277Sgonzo struct semaphore sync_release_event; 440278277Sgonzo 441278277Sgonzo char *tx_data; 442278277Sgonzo char *rx_data; 443278277Sgonzo VCHIQ_SLOT_INFO_T *rx_info; 444278277Sgonzo 445278277Sgonzo struct mutex slot_mutex; 446278277Sgonzo 447278277Sgonzo struct mutex recycle_mutex; 448278277Sgonzo 449278277Sgonzo struct mutex sync_mutex; 450278277Sgonzo 451278277Sgonzo struct mutex bulk_transfer_mutex; 452278277Sgonzo 453278277Sgonzo /* Indicates the byte position within the stream from where the next 454278277Sgonzo ** message will be read. The least significant bits are an index into 455278277Sgonzo ** the slot.The next bits are the index of the slot in 456278277Sgonzo ** remote->slot_queue. */ 457278277Sgonzo int rx_pos; 458278277Sgonzo 459278277Sgonzo /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read 460278277Sgonzo from remote->tx_pos. */ 461278277Sgonzo int local_tx_pos; 462278277Sgonzo 463278277Sgonzo /* The slot_queue index of the slot to become available next. */ 464278277Sgonzo int slot_queue_available; 465278277Sgonzo 466278277Sgonzo /* A flag to indicate if any poll has been requested */ 467278277Sgonzo int poll_needed; 468278277Sgonzo 469278277Sgonzo /* Ths index of the previous slot used for data messages. */ 470278277Sgonzo int previous_data_index; 471278277Sgonzo 472278277Sgonzo /* The number of slots occupied by data messages. */ 473278277Sgonzo unsigned short data_use_count; 474278277Sgonzo 475278277Sgonzo /* The maximum number of slots to be occupied by data messages. */ 476278277Sgonzo unsigned short data_quota; 477278277Sgonzo 478278277Sgonzo /* An array of bit sets indicating which services must be polled. */ 479278277Sgonzo atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; 480278277Sgonzo 481278277Sgonzo /* The number of the first unused service */ 482278277Sgonzo int unused_service; 483278277Sgonzo 484278277Sgonzo /* Signalled when a free slot becomes available. */ 485278277Sgonzo struct semaphore slot_available_event; 486278277Sgonzo 487278277Sgonzo struct semaphore slot_remove_event; 488278277Sgonzo 489278277Sgonzo /* Signalled when a free data slot becomes available. */ 490278277Sgonzo struct semaphore data_quota_event; 491278277Sgonzo 492278277Sgonzo /* Incremented when there are bulk transfers which cannot be processed 493278277Sgonzo * whilst paused and must be processed on resume */ 494278277Sgonzo int deferred_bulks; 495278277Sgonzo 496278277Sgonzo struct state_stats_struct { 497278277Sgonzo int slot_stalls; 498278277Sgonzo int data_stalls; 499278277Sgonzo int ctrl_tx_count; 500278277Sgonzo int ctrl_rx_count; 501278277Sgonzo int error_count; 502278277Sgonzo } stats; 503278277Sgonzo 504278277Sgonzo VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; 505278277Sgonzo VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; 506278277Sgonzo VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; 507278277Sgonzo 508278277Sgonzo VCHIQ_PLATFORM_STATE_T platform_state; 509278277Sgonzo}; 510278277Sgonzo 511278277Sgonzostruct bulk_waiter { 512278277Sgonzo VCHIQ_BULK_T *bulk; 513278277Sgonzo struct semaphore event; 514278277Sgonzo int actual; 515278277Sgonzo}; 516278277Sgonzo 517278277Sgonzoextern spinlock_t bulk_waiter_spinlock; 518278277Sgonzo 519278277Sgonzoextern int vchiq_core_log_level; 520278277Sgonzoextern int vchiq_core_msg_log_level; 521278277Sgonzoextern int vchiq_sync_log_level; 522278277Sgonzo 523278277Sgonzoextern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; 524278277Sgonzo 525278277Sgonzoextern const char * 526278277Sgonzoget_conn_state_name(VCHIQ_CONNSTATE_T conn_state); 527278277Sgonzo 528278277Sgonzoextern VCHIQ_SLOT_ZERO_T * 529278277Sgonzovchiq_init_slots(void *mem_base, int mem_size); 530278277Sgonzo 531278277Sgonzoextern VCHIQ_STATUS_T 532278277Sgonzovchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, 533278277Sgonzo int is_master); 534278277Sgonzo 535278277Sgonzoextern VCHIQ_STATUS_T 536278277Sgonzovchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); 537278277Sgonzo 538278277Sgonzoextern VCHIQ_SERVICE_T * 539278277Sgonzovchiq_add_service_internal(VCHIQ_STATE_T *state, 540278277Sgonzo const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, 541278277Sgonzo VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); 542278277Sgonzo 543278277Sgonzoextern VCHIQ_STATUS_T 544278277Sgonzovchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); 545278277Sgonzo 546278277Sgonzoextern VCHIQ_STATUS_T 547278277Sgonzovchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); 548278277Sgonzo 549278277Sgonzoextern void 550278277Sgonzovchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); 551278277Sgonzo 552278277Sgonzoextern void 553278277Sgonzovchiq_free_service_internal(VCHIQ_SERVICE_T *service); 554278277Sgonzo 555278277Sgonzoextern VCHIQ_STATUS_T 556278277Sgonzovchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); 557278277Sgonzo 558278277Sgonzoextern VCHIQ_STATUS_T 559278277Sgonzovchiq_pause_internal(VCHIQ_STATE_T *state); 560278277Sgonzo 561278277Sgonzoextern VCHIQ_STATUS_T 562278277Sgonzovchiq_resume_internal(VCHIQ_STATE_T *state); 563278277Sgonzo 564278277Sgonzoextern void 565278277Sgonzoremote_event_pollall(VCHIQ_STATE_T *state); 566278277Sgonzo 567278277Sgonzoextern VCHIQ_STATUS_T 568278277Sgonzovchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, 569278277Sgonzo VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, 570278277Sgonzo VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); 571278277Sgonzo 572278277Sgonzoextern void 573278277Sgonzovchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); 574278277Sgonzo 575278277Sgonzoextern void 576278277Sgonzovchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); 577278277Sgonzo 578278277Sgonzoextern void 579278277Sgonzovchiq_loud_error_header(void); 580278277Sgonzo 581278277Sgonzoextern void 582278277Sgonzovchiq_loud_error_footer(void); 583278277Sgonzo 584278277Sgonzoextern void 585278277Sgonzorequest_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); 586278277Sgonzo 587278277Sgonzostatic inline VCHIQ_SERVICE_T * 588278277Sgonzohandle_to_service(VCHIQ_SERVICE_HANDLE_T handle) 589278277Sgonzo{ 590278277Sgonzo VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & 591278277Sgonzo (VCHIQ_MAX_STATES - 1)]; 592278277Sgonzo if (!state) 593278277Sgonzo return NULL; 594278277Sgonzo 595278277Sgonzo return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; 596278277Sgonzo} 597278277Sgonzo 598278277Sgonzoextern VCHIQ_SERVICE_T * 599278277Sgonzofind_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); 600278277Sgonzo 601278277Sgonzoextern VCHIQ_SERVICE_T * 602278277Sgonzofind_service_by_port(VCHIQ_STATE_T *state, int localport); 603278277Sgonzo 604278277Sgonzoextern VCHIQ_SERVICE_T * 605278277Sgonzofind_service_for_instance(VCHIQ_INSTANCE_T instance, 606278277Sgonzo VCHIQ_SERVICE_HANDLE_T handle); 607278277Sgonzo 608278277Sgonzoextern VCHIQ_SERVICE_T * 609278277Sgonzonext_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, 610278277Sgonzo int *pidx); 611278277Sgonzo 612278277Sgonzoextern void 613278277Sgonzolock_service(VCHIQ_SERVICE_T *service); 614278277Sgonzo 615278277Sgonzoextern void 616278277Sgonzounlock_service(VCHIQ_SERVICE_T *service); 617278277Sgonzo 618278277Sgonzo/* The following functions are called from vchiq_core, and external 619278277Sgonzo** implementations must be provided. */ 620278277Sgonzo 621278277Sgonzoextern VCHIQ_STATUS_T 622278277Sgonzovchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, 623278277Sgonzo VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); 624278277Sgonzo 625278277Sgonzoextern void 626278277Sgonzovchiq_transfer_bulk(VCHIQ_BULK_T *bulk); 627278277Sgonzo 628278277Sgonzoextern void 629278277Sgonzovchiq_complete_bulk(VCHIQ_BULK_T *bulk); 630278277Sgonzo 631278277Sgonzoextern VCHIQ_STATUS_T 632278277Sgonzovchiq_copy_from_user(void *dst, const void *src, int size); 633278277Sgonzo 634278277Sgonzoextern void 635278277Sgonzoremote_event_signal(REMOTE_EVENT_T *event); 636278277Sgonzo 637278277Sgonzovoid 638278277Sgonzovchiq_platform_check_suspend(VCHIQ_STATE_T *state); 639278277Sgonzo 640278277Sgonzoextern void 641278277Sgonzovchiq_platform_paused(VCHIQ_STATE_T *state); 642278277Sgonzo 643278277Sgonzoextern VCHIQ_STATUS_T 644278277Sgonzovchiq_platform_resume(VCHIQ_STATE_T *state); 645278277Sgonzo 646278277Sgonzoextern void 647278277Sgonzovchiq_platform_resumed(VCHIQ_STATE_T *state); 648278277Sgonzo 649278277Sgonzoextern void 650278277Sgonzovchiq_dump(void *dump_context, const char *str, int len); 651278277Sgonzo 652278277Sgonzoextern void 653278277Sgonzovchiq_dump_platform_state(void *dump_context); 654278277Sgonzo 655278277Sgonzoextern void 656278277Sgonzovchiq_dump_platform_instances(void *dump_context); 657278277Sgonzo 658278277Sgonzoextern void 659278277Sgonzovchiq_dump_platform_service_state(void *dump_context, 660278277Sgonzo VCHIQ_SERVICE_T *service); 661278277Sgonzo 662278277Sgonzoextern VCHIQ_STATUS_T 663278277Sgonzovchiq_use_service_internal(VCHIQ_SERVICE_T *service); 664278277Sgonzo 665278277Sgonzoextern VCHIQ_STATUS_T 666278277Sgonzovchiq_release_service_internal(VCHIQ_SERVICE_T *service); 667278277Sgonzo 668278277Sgonzoextern void 669278277Sgonzovchiq_on_remote_use(VCHIQ_STATE_T *state); 670278277Sgonzo 671278277Sgonzoextern void 672278277Sgonzovchiq_on_remote_release(VCHIQ_STATE_T *state); 673278277Sgonzo 674278277Sgonzoextern VCHIQ_STATUS_T 675278277Sgonzovchiq_platform_init_state(VCHIQ_STATE_T *state); 676278277Sgonzo 677278277Sgonzoextern VCHIQ_STATUS_T 678278277Sgonzovchiq_check_service(VCHIQ_SERVICE_T *service); 679278277Sgonzo 680278277Sgonzoextern void 681278277Sgonzovchiq_on_remote_use_active(VCHIQ_STATE_T *state); 682278277Sgonzo 683278277Sgonzoextern VCHIQ_STATUS_T 684278277Sgonzovchiq_send_remote_use(VCHIQ_STATE_T *state); 685278277Sgonzo 686278277Sgonzoextern VCHIQ_STATUS_T 687278277Sgonzovchiq_send_remote_release(VCHIQ_STATE_T *state); 688278277Sgonzo 689278277Sgonzoextern VCHIQ_STATUS_T 690278277Sgonzovchiq_send_remote_use_active(VCHIQ_STATE_T *state); 691278277Sgonzo 692278277Sgonzoextern void 693278277Sgonzovchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, 694278277Sgonzo VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); 695278277Sgonzo 696278277Sgonzoextern void 697278277Sgonzovchiq_platform_handle_timeout(VCHIQ_STATE_T *state); 698278277Sgonzo 699278277Sgonzoextern void 700278277Sgonzovchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); 701278277Sgonzo 702278277Sgonzo 703278277Sgonzoextern void 704278277Sgonzovchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, 705278277Sgonzo size_t numBytes); 706278277Sgonzo 707278277Sgonzoextern void 708278277Sgonzovchiq_core_initialize(void); 709278277Sgonzo 710278277Sgonzo#endif 711