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; 298290245Sgonzo char trace; 299278277Sgonzo atomic_t poll_flags; 300278277Sgonzo short version; 301278277Sgonzo short version_min; 302278277Sgonzo short peer_version; 303278277Sgonzo 304278277Sgonzo VCHIQ_STATE_T *state; 305278277Sgonzo VCHIQ_INSTANCE_T instance; 306278277Sgonzo 307278277Sgonzo int service_use_count; 308278277Sgonzo 309278277Sgonzo VCHIQ_BULK_QUEUE_T bulk_tx; 310278277Sgonzo VCHIQ_BULK_QUEUE_T bulk_rx; 311278277Sgonzo 312278277Sgonzo struct semaphore remove_event; 313278277Sgonzo struct semaphore bulk_remove_event; 314278277Sgonzo struct mutex bulk_mutex; 315278277Sgonzo 316278277Sgonzo struct service_stats_struct { 317278277Sgonzo int quota_stalls; 318278277Sgonzo int slot_stalls; 319278277Sgonzo int bulk_stalls; 320278277Sgonzo int error_count; 321278277Sgonzo int ctrl_tx_count; 322278277Sgonzo int ctrl_rx_count; 323278277Sgonzo int bulk_tx_count; 324278277Sgonzo int bulk_rx_count; 325278277Sgonzo int bulk_aborted_count; 326278277Sgonzo uint64_t ctrl_tx_bytes; 327278277Sgonzo uint64_t ctrl_rx_bytes; 328278277Sgonzo uint64_t bulk_tx_bytes; 329278277Sgonzo uint64_t bulk_rx_bytes; 330278277Sgonzo } stats; 331278277Sgonzo} VCHIQ_SERVICE_T; 332278277Sgonzo 333278277Sgonzo/* The quota information is outside VCHIQ_SERVICE_T so that it can be 334278277Sgonzo statically allocated, since for accounting reasons a service's slot 335278277Sgonzo usage is carried over between users of the same port number. 336278277Sgonzo */ 337278277Sgonzotypedef struct vchiq_service_quota_struct { 338278277Sgonzo unsigned short slot_quota; 339278277Sgonzo unsigned short slot_use_count; 340278277Sgonzo unsigned short message_quota; 341278277Sgonzo unsigned short message_use_count; 342278277Sgonzo struct semaphore quota_event; 343278277Sgonzo int previous_tx_index; 344278277Sgonzo} VCHIQ_SERVICE_QUOTA_T; 345278277Sgonzo 346278277Sgonzotypedef struct vchiq_shared_state_struct { 347278277Sgonzo 348278277Sgonzo /* A non-zero value here indicates that the content is valid. */ 349278277Sgonzo int initialised; 350278277Sgonzo 351278277Sgonzo /* The first and last (inclusive) slots allocated to the owner. */ 352278277Sgonzo int slot_first; 353278277Sgonzo int slot_last; 354278277Sgonzo 355278277Sgonzo /* The slot allocated to synchronous messages from the owner. */ 356278277Sgonzo int slot_sync; 357278277Sgonzo 358278277Sgonzo /* Signalling this event indicates that owner's slot handler thread 359278277Sgonzo ** should run. */ 360278277Sgonzo REMOTE_EVENT_T trigger; 361278277Sgonzo 362278277Sgonzo /* Indicates the byte position within the stream where the next message 363278277Sgonzo ** will be written. The least significant bits are an index into the 364278277Sgonzo ** slot. The next bits are the index of the slot in slot_queue. */ 365278277Sgonzo int tx_pos; 366278277Sgonzo 367278277Sgonzo /* This event should be signalled when a slot is recycled. */ 368278277Sgonzo REMOTE_EVENT_T recycle; 369278277Sgonzo 370278277Sgonzo /* The slot_queue index where the next recycled slot will be written. */ 371278277Sgonzo int slot_queue_recycle; 372278277Sgonzo 373278277Sgonzo /* This event should be signalled when a synchronous message is sent. */ 374278277Sgonzo REMOTE_EVENT_T sync_trigger; 375278277Sgonzo 376278277Sgonzo /* This event should be signalled when a synchronous message has been 377278277Sgonzo ** released. */ 378278277Sgonzo REMOTE_EVENT_T sync_release; 379278277Sgonzo 380278277Sgonzo /* A circular buffer of slot indexes. */ 381278277Sgonzo int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; 382278277Sgonzo 383278277Sgonzo /* Debugging state */ 384278277Sgonzo int debug[DEBUG_MAX]; 385278431Sgonzo} VCHIQ_SHARED_STATE_T; 386278277Sgonzo 387278277Sgonzotypedef struct vchiq_slot_zero_struct { 388278277Sgonzo int magic; 389278277Sgonzo short version; 390278277Sgonzo short version_min; 391278277Sgonzo int slot_zero_size; 392278277Sgonzo int slot_size; 393278277Sgonzo int max_slots; 394278277Sgonzo int max_slots_per_side; 395278277Sgonzo int platform_data[2]; 396278277Sgonzo VCHIQ_SHARED_STATE_T master; 397278277Sgonzo VCHIQ_SHARED_STATE_T slave; 398278277Sgonzo VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; 399278431Sgonzo} VCHIQ_SLOT_ZERO_T; 400278277Sgonzo 401278277Sgonzostruct vchiq_state_struct { 402278277Sgonzo int id; 403278277Sgonzo int initialised; 404278277Sgonzo VCHIQ_CONNSTATE_T conn_state; 405278277Sgonzo int is_master; 406290245Sgonzo short version_common; 407278277Sgonzo 408278277Sgonzo VCHIQ_SHARED_STATE_T *local; 409278277Sgonzo VCHIQ_SHARED_STATE_T *remote; 410278277Sgonzo VCHIQ_SLOT_T *slot_data; 411278277Sgonzo 412278277Sgonzo unsigned short default_slot_quota; 413278277Sgonzo unsigned short default_message_quota; 414278277Sgonzo 415278277Sgonzo /* Event indicating connect message received */ 416278277Sgonzo struct semaphore connect; 417278277Sgonzo 418278277Sgonzo /* Mutex protecting services */ 419278277Sgonzo struct mutex mutex; 420278277Sgonzo VCHIQ_INSTANCE_T *instance; 421278277Sgonzo 422278277Sgonzo /* Processes incoming messages */ 423278277Sgonzo VCHIQ_THREAD_T slot_handler_thread; 424278277Sgonzo 425278277Sgonzo /* Processes recycled slots */ 426278277Sgonzo VCHIQ_THREAD_T recycle_thread; 427278277Sgonzo 428278277Sgonzo /* Processes synchronous messages */ 429278277Sgonzo VCHIQ_THREAD_T sync_thread; 430278277Sgonzo 431278277Sgonzo /* Local implementation of the trigger remote event */ 432278277Sgonzo struct semaphore trigger_event; 433278277Sgonzo 434278277Sgonzo /* Local implementation of the recycle remote event */ 435278277Sgonzo struct semaphore recycle_event; 436278277Sgonzo 437278277Sgonzo /* Local implementation of the sync trigger remote event */ 438278277Sgonzo struct semaphore sync_trigger_event; 439278277Sgonzo 440278277Sgonzo /* Local implementation of the sync release remote event */ 441278277Sgonzo struct semaphore sync_release_event; 442278277Sgonzo 443278277Sgonzo char *tx_data; 444278277Sgonzo char *rx_data; 445278277Sgonzo VCHIQ_SLOT_INFO_T *rx_info; 446278277Sgonzo 447278277Sgonzo struct mutex slot_mutex; 448278277Sgonzo 449278277Sgonzo struct mutex recycle_mutex; 450278277Sgonzo 451278277Sgonzo struct mutex sync_mutex; 452278277Sgonzo 453278277Sgonzo struct mutex bulk_transfer_mutex; 454278277Sgonzo 455278277Sgonzo /* Indicates the byte position within the stream from where the next 456278277Sgonzo ** message will be read. The least significant bits are an index into 457278277Sgonzo ** the slot.The next bits are the index of the slot in 458278277Sgonzo ** remote->slot_queue. */ 459278277Sgonzo int rx_pos; 460278277Sgonzo 461278277Sgonzo /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read 462278277Sgonzo from remote->tx_pos. */ 463278277Sgonzo int local_tx_pos; 464278277Sgonzo 465278277Sgonzo /* The slot_queue index of the slot to become available next. */ 466278277Sgonzo int slot_queue_available; 467278277Sgonzo 468278277Sgonzo /* A flag to indicate if any poll has been requested */ 469278277Sgonzo int poll_needed; 470278277Sgonzo 471278277Sgonzo /* Ths index of the previous slot used for data messages. */ 472278277Sgonzo int previous_data_index; 473278277Sgonzo 474278277Sgonzo /* The number of slots occupied by data messages. */ 475278277Sgonzo unsigned short data_use_count; 476278277Sgonzo 477278277Sgonzo /* The maximum number of slots to be occupied by data messages. */ 478278277Sgonzo unsigned short data_quota; 479278277Sgonzo 480278277Sgonzo /* An array of bit sets indicating which services must be polled. */ 481278277Sgonzo atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; 482278277Sgonzo 483278277Sgonzo /* The number of the first unused service */ 484278277Sgonzo int unused_service; 485278277Sgonzo 486278277Sgonzo /* Signalled when a free slot becomes available. */ 487278277Sgonzo struct semaphore slot_available_event; 488278277Sgonzo 489278277Sgonzo struct semaphore slot_remove_event; 490278277Sgonzo 491278277Sgonzo /* Signalled when a free data slot becomes available. */ 492278277Sgonzo struct semaphore data_quota_event; 493278277Sgonzo 494278277Sgonzo /* Incremented when there are bulk transfers which cannot be processed 495278277Sgonzo * whilst paused and must be processed on resume */ 496278277Sgonzo int deferred_bulks; 497278277Sgonzo 498278277Sgonzo struct state_stats_struct { 499278277Sgonzo int slot_stalls; 500278277Sgonzo int data_stalls; 501278277Sgonzo int ctrl_tx_count; 502278277Sgonzo int ctrl_rx_count; 503278277Sgonzo int error_count; 504278277Sgonzo } stats; 505278277Sgonzo 506278277Sgonzo VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; 507278277Sgonzo VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; 508278277Sgonzo VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; 509278277Sgonzo 510278277Sgonzo VCHIQ_PLATFORM_STATE_T platform_state; 511278277Sgonzo}; 512278277Sgonzo 513278277Sgonzostruct bulk_waiter { 514278277Sgonzo VCHIQ_BULK_T *bulk; 515278277Sgonzo struct semaphore event; 516278277Sgonzo int actual; 517278277Sgonzo}; 518278277Sgonzo 519278277Sgonzoextern spinlock_t bulk_waiter_spinlock; 520278277Sgonzo 521278277Sgonzoextern int vchiq_core_log_level; 522278277Sgonzoextern int vchiq_core_msg_log_level; 523278277Sgonzoextern int vchiq_sync_log_level; 524278277Sgonzo 525278277Sgonzoextern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; 526278277Sgonzo 527278277Sgonzoextern const char * 528278277Sgonzoget_conn_state_name(VCHIQ_CONNSTATE_T conn_state); 529278277Sgonzo 530278277Sgonzoextern VCHIQ_SLOT_ZERO_T * 531278277Sgonzovchiq_init_slots(void *mem_base, int mem_size); 532278277Sgonzo 533278277Sgonzoextern VCHIQ_STATUS_T 534278277Sgonzovchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, 535278277Sgonzo int is_master); 536278277Sgonzo 537278277Sgonzoextern VCHIQ_STATUS_T 538278277Sgonzovchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); 539278277Sgonzo 540278277Sgonzoextern VCHIQ_SERVICE_T * 541278277Sgonzovchiq_add_service_internal(VCHIQ_STATE_T *state, 542278277Sgonzo const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, 543278277Sgonzo VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); 544278277Sgonzo 545278277Sgonzoextern VCHIQ_STATUS_T 546278277Sgonzovchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); 547278277Sgonzo 548278277Sgonzoextern VCHIQ_STATUS_T 549278277Sgonzovchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); 550278277Sgonzo 551278277Sgonzoextern void 552278277Sgonzovchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); 553278277Sgonzo 554278277Sgonzoextern void 555278277Sgonzovchiq_free_service_internal(VCHIQ_SERVICE_T *service); 556278277Sgonzo 557278277Sgonzoextern VCHIQ_STATUS_T 558278277Sgonzovchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); 559278277Sgonzo 560278277Sgonzoextern VCHIQ_STATUS_T 561278277Sgonzovchiq_pause_internal(VCHIQ_STATE_T *state); 562278277Sgonzo 563278277Sgonzoextern VCHIQ_STATUS_T 564278277Sgonzovchiq_resume_internal(VCHIQ_STATE_T *state); 565278277Sgonzo 566278277Sgonzoextern void 567278277Sgonzoremote_event_pollall(VCHIQ_STATE_T *state); 568278277Sgonzo 569278277Sgonzoextern VCHIQ_STATUS_T 570278277Sgonzovchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, 571278277Sgonzo VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, 572278277Sgonzo VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); 573278277Sgonzo 574278277Sgonzoextern void 575278277Sgonzovchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); 576278277Sgonzo 577278277Sgonzoextern void 578278277Sgonzovchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); 579278277Sgonzo 580278277Sgonzoextern void 581278277Sgonzovchiq_loud_error_header(void); 582278277Sgonzo 583278277Sgonzoextern void 584278277Sgonzovchiq_loud_error_footer(void); 585278277Sgonzo 586278277Sgonzoextern void 587278277Sgonzorequest_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); 588278277Sgonzo 589278277Sgonzostatic inline VCHIQ_SERVICE_T * 590278277Sgonzohandle_to_service(VCHIQ_SERVICE_HANDLE_T handle) 591278277Sgonzo{ 592278277Sgonzo VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & 593278277Sgonzo (VCHIQ_MAX_STATES - 1)]; 594278277Sgonzo if (!state) 595278277Sgonzo return NULL; 596278277Sgonzo 597278277Sgonzo return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; 598278277Sgonzo} 599278277Sgonzo 600278277Sgonzoextern VCHIQ_SERVICE_T * 601278277Sgonzofind_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); 602278277Sgonzo 603278277Sgonzoextern VCHIQ_SERVICE_T * 604278277Sgonzofind_service_by_port(VCHIQ_STATE_T *state, int localport); 605278277Sgonzo 606278277Sgonzoextern VCHIQ_SERVICE_T * 607278277Sgonzofind_service_for_instance(VCHIQ_INSTANCE_T instance, 608278277Sgonzo VCHIQ_SERVICE_HANDLE_T handle); 609278277Sgonzo 610278277Sgonzoextern VCHIQ_SERVICE_T * 611290245Sgonzofind_closed_service_for_instance(VCHIQ_INSTANCE_T instance, 612290245Sgonzo VCHIQ_SERVICE_HANDLE_T handle); 613290245Sgonzo 614290245Sgonzoextern VCHIQ_SERVICE_T * 615278277Sgonzonext_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, 616278277Sgonzo int *pidx); 617278277Sgonzo 618278277Sgonzoextern void 619278277Sgonzolock_service(VCHIQ_SERVICE_T *service); 620278277Sgonzo 621278277Sgonzoextern void 622278277Sgonzounlock_service(VCHIQ_SERVICE_T *service); 623278277Sgonzo 624278277Sgonzo/* The following functions are called from vchiq_core, and external 625278277Sgonzo** implementations must be provided. */ 626278277Sgonzo 627278277Sgonzoextern VCHIQ_STATUS_T 628278277Sgonzovchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, 629278277Sgonzo VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); 630278277Sgonzo 631278277Sgonzoextern void 632278277Sgonzovchiq_transfer_bulk(VCHIQ_BULK_T *bulk); 633278277Sgonzo 634278277Sgonzoextern void 635278277Sgonzovchiq_complete_bulk(VCHIQ_BULK_T *bulk); 636278277Sgonzo 637278277Sgonzoextern VCHIQ_STATUS_T 638278277Sgonzovchiq_copy_from_user(void *dst, const void *src, int size); 639278277Sgonzo 640278277Sgonzoextern void 641278277Sgonzoremote_event_signal(REMOTE_EVENT_T *event); 642278277Sgonzo 643278277Sgonzovoid 644278277Sgonzovchiq_platform_check_suspend(VCHIQ_STATE_T *state); 645278277Sgonzo 646278277Sgonzoextern void 647278277Sgonzovchiq_platform_paused(VCHIQ_STATE_T *state); 648278277Sgonzo 649278277Sgonzoextern VCHIQ_STATUS_T 650278277Sgonzovchiq_platform_resume(VCHIQ_STATE_T *state); 651278277Sgonzo 652278277Sgonzoextern void 653278277Sgonzovchiq_platform_resumed(VCHIQ_STATE_T *state); 654278277Sgonzo 655278277Sgonzoextern void 656278277Sgonzovchiq_dump(void *dump_context, const char *str, int len); 657278277Sgonzo 658278277Sgonzoextern void 659278277Sgonzovchiq_dump_platform_state(void *dump_context); 660278277Sgonzo 661278277Sgonzoextern void 662278277Sgonzovchiq_dump_platform_instances(void *dump_context); 663278277Sgonzo 664278277Sgonzoextern void 665278277Sgonzovchiq_dump_platform_service_state(void *dump_context, 666278277Sgonzo VCHIQ_SERVICE_T *service); 667278277Sgonzo 668278277Sgonzoextern VCHIQ_STATUS_T 669278277Sgonzovchiq_use_service_internal(VCHIQ_SERVICE_T *service); 670278277Sgonzo 671278277Sgonzoextern VCHIQ_STATUS_T 672278277Sgonzovchiq_release_service_internal(VCHIQ_SERVICE_T *service); 673278277Sgonzo 674278277Sgonzoextern void 675278277Sgonzovchiq_on_remote_use(VCHIQ_STATE_T *state); 676278277Sgonzo 677278277Sgonzoextern void 678278277Sgonzovchiq_on_remote_release(VCHIQ_STATE_T *state); 679278277Sgonzo 680278277Sgonzoextern VCHIQ_STATUS_T 681278277Sgonzovchiq_platform_init_state(VCHIQ_STATE_T *state); 682278277Sgonzo 683278277Sgonzoextern VCHIQ_STATUS_T 684278277Sgonzovchiq_check_service(VCHIQ_SERVICE_T *service); 685278277Sgonzo 686278277Sgonzoextern void 687278277Sgonzovchiq_on_remote_use_active(VCHIQ_STATE_T *state); 688278277Sgonzo 689278277Sgonzoextern VCHIQ_STATUS_T 690278277Sgonzovchiq_send_remote_use(VCHIQ_STATE_T *state); 691278277Sgonzo 692278277Sgonzoextern VCHIQ_STATUS_T 693278277Sgonzovchiq_send_remote_release(VCHIQ_STATE_T *state); 694278277Sgonzo 695278277Sgonzoextern VCHIQ_STATUS_T 696278277Sgonzovchiq_send_remote_use_active(VCHIQ_STATE_T *state); 697278277Sgonzo 698278277Sgonzoextern void 699278277Sgonzovchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, 700278277Sgonzo VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); 701278277Sgonzo 702278277Sgonzoextern void 703278277Sgonzovchiq_platform_handle_timeout(VCHIQ_STATE_T *state); 704278277Sgonzo 705278277Sgonzoextern void 706278277Sgonzovchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); 707278277Sgonzo 708278277Sgonzo 709278277Sgonzoextern void 710278277Sgonzovchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, 711278277Sgonzo size_t numBytes); 712278277Sgonzo 713278277Sgonzoextern void 714278277Sgonzovchiq_core_initialize(void); 715278277Sgonzo 716278277Sgonzo#endif 717