From bf9f0b00bb7fd0470c1255bcc8e76c81d122a609 Mon Sep 17 00:00:00 2001 From: Jai Luthra Date: Wed, 29 Oct 2025 16:00:08 +0530 Subject: include: linux: Destage VCHIQ interface headers Move the VCHIQ headers from drivers/staging/vc04_services/include to include/linux/raspberrypi This is done so that they can be shared between the VCHIQ interface (which is going to be de-staged in a subsequent commit from staging) and the VCHIQ drivers left in the staging/vc04_services (namely bcm2835-audio, bcm2835-camera). The include/linux/raspberrypi/ provides a central location to serve both of these areas. Co-developed-by: Umang Jain Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Signed-off-by: Jai Luthra Link: https://patch.msgid.link/20251029-vchiq-destage-v3-4-da8d6c83c2c5@ideasonboard.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + .../vc04_services/bcm2835-audio/bcm2835-vchiq.c | 5 +- .../staging/vc04_services/bcm2835-audio/bcm2835.c | 3 +- .../staging/vc04_services/bcm2835-audio/bcm2835.h | 3 +- .../include/linux/raspberrypi/vchiq.h | 112 ---- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 9 +- .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 164 ------ .../vc04_services/interface/vchiq_arm/vchiq_bus.c | 4 +- .../vc04_services/interface/vchiq_arm/vchiq_bus.h | 60 -- .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 41 -- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 4 +- .../vc04_services/interface/vchiq_arm/vchiq_core.h | 646 --------------------- .../interface/vchiq_arm/vchiq_debugfs.c | 6 +- .../interface/vchiq_arm/vchiq_debugfs.h | 22 - .../vc04_services/interface/vchiq_arm/vchiq_dev.c | 7 +- .../interface/vchiq_arm/vchiq_ioctl.h | 3 +- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 5 +- include/linux/raspberrypi/vchiq.h | 112 ++++ include/linux/raspberrypi/vchiq_arm.h | 164 ++++++ include/linux/raspberrypi/vchiq_bus.h | 60 ++ include/linux/raspberrypi/vchiq_cfg.h | 41 ++ include/linux/raspberrypi/vchiq_core.h | 646 +++++++++++++++++++++ include/linux/raspberrypi/vchiq_debugfs.h | 22 + 23 files changed, 1072 insertions(+), 1068 deletions(-) delete mode 100644 drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h delete mode 100644 drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h create mode 100644 include/linux/raspberrypi/vchiq.h create mode 100644 include/linux/raspberrypi/vchiq_arm.h create mode 100644 include/linux/raspberrypi/vchiq_bus.h create mode 100644 include/linux/raspberrypi/vchiq_cfg.h create mode 100644 include/linux/raspberrypi/vchiq_core.h create mode 100644 include/linux/raspberrypi/vchiq_debugfs.h diff --git a/MAINTAINERS b/MAINTAINERS index 3da2c26a796b..cd223e119d48 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4829,6 +4829,7 @@ T: git https://github.com/broadcom/stblinux.git F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml F: drivers/pci/controller/pcie-brcmstb.c F: drivers/staging/vc04_services +F: include/linux/raspberrypi/vchiq* N: bcm2711 N: bcm2712 N: bcm283* diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 0dbe76ee5570..7368b384497f 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -4,11 +4,12 @@ #include #include #include + +#include + #include "bcm2835.h" #include "vc_vchi_audioserv_defs.h" -#include "../interface/vchiq_arm/vchiq_arm.h" - struct bcm2835_audio_instance { struct device *dev; unsigned int service_handle; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c index b74cb104e9de..f292a6618166 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c @@ -6,7 +6,8 @@ #include #include -#include "../interface/vchiq_arm/vchiq_bus.h" +#include + #include "bcm2835.h" static bool enable_hdmi; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h index 49ec5b496edb..5a1348747ff4 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h @@ -5,13 +5,12 @@ #define __SOUND_ARM_BCM2835_H #include +#include #include #include #include #include -#include "../include/linux/raspberrypi/vchiq.h" - #define MAX_SUBSTREAMS (8) #define AVAIL_SUBSTREAMS_MASK (0xff) diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h deleted file mode 100644 index ee4469f4fc51..000000000000 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_H -#define VCHIQ_H - -#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ - (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) - -enum vchiq_reason { - VCHIQ_SERVICE_OPENED, /* service, -, - */ - VCHIQ_SERVICE_CLOSED, /* service, -, - */ - VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ - VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ - VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ - VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ - VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ -}; - -enum vchiq_bulk_mode { - VCHIQ_BULK_MODE_CALLBACK, - VCHIQ_BULK_MODE_BLOCKING, - VCHIQ_BULK_MODE_NOCALLBACK, - VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ -}; - -enum vchiq_service_option { - VCHIQ_SERVICE_OPTION_AUTOCLOSE, - VCHIQ_SERVICE_OPTION_SLOT_QUOTA, - VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, - VCHIQ_SERVICE_OPTION_SYNCHRONOUS, - VCHIQ_SERVICE_OPTION_TRACE -}; - -struct vchiq_header { - /* The message identifier - opaque to applications. */ - int msgid; - - /* Size of message data. */ - unsigned int size; - - char data[]; /* message */ -}; - -struct vchiq_element { - const void __user *data; - unsigned int size; -}; - -struct vchiq_instance; -struct vchiq_state; - -struct vchiq_service_base { - int fourcc; - int (*callback)(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *cb_data, void __user *cb_userdata); - void *userdata; -}; - -struct vchiq_completion_data_kernel { - enum vchiq_reason reason; - struct vchiq_header *header; - void *service_userdata; - void *cb_data; - void __user *cb_userdata; -}; - -struct vchiq_service_params_kernel { - int fourcc; - int (*callback)(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *cb_data, void __user *cb_userdata); - void *userdata; - short version; /* Increment for non-trivial changes */ - short version_min; /* Update for incompatible changes */ -}; - -extern int vchiq_initialise(struct vchiq_state *state, - struct vchiq_instance **pinstance); -extern int vchiq_shutdown(struct vchiq_instance *instance); -extern int vchiq_connect(struct vchiq_instance *instance); -extern int vchiq_open_service(struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *pservice); -extern int vchiq_close_service(struct vchiq_instance *instance, - unsigned int service); -extern int vchiq_use_service(struct vchiq_instance *instance, unsigned int service); -extern int vchiq_release_service(struct vchiq_instance *instance, - unsigned int service); -extern void vchiq_msg_queue_push(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_header *header); -extern void vchiq_release_message(struct vchiq_instance *instance, unsigned int service, - struct vchiq_header *header); -extern int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, - void *data, unsigned int size); -extern int vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int service, - const void *data, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode); -extern int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int service, - void *data, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode); -extern void *vchiq_get_service_userdata(struct vchiq_instance *instance, unsigned int service); -extern int vchiq_get_peer_version(struct vchiq_instance *instance, unsigned int handle, - short *peer_version); -extern struct vchiq_header *vchiq_msg_hold(struct vchiq_instance *instance, unsigned int handle); - -#endif /* VCHIQ_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index a2074069e79e..6a7b96d3dae6 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -30,11 +30,12 @@ #include #include -#include "vchiq_core.h" +#include +#include +#include +#include + #include "vchiq_ioctl.h" -#include "vchiq_arm.h" -#include "vchiq_bus.h" -#include "vchiq_debugfs.h" #define DEVICE_NAME "vchiq" diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h deleted file mode 100644 index e32b02f99024..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* - * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - */ - -#ifndef VCHIQ_ARM_H -#define VCHIQ_ARM_H - -#include -#include -#include -#include -#include "vchiq_core.h" -#include "vchiq_debugfs.h" - -/* Some per-instance constants */ -#define MAX_COMPLETIONS 128 -#define MAX_SERVICES 64 -#define MAX_ELEMENTS 8 -#define MSG_QUEUE_SIZE 128 - -#define VCHIQ_DRV_MAX_CALLBACKS 10 - -struct rpi_firmware; -struct vchiq_device; - -enum USE_TYPE_E { - USE_TYPE_SERVICE, - USE_TYPE_VCHIQ -}; - -struct vchiq_platform_info { - unsigned int cache_line_size; -}; - -struct vchiq_drv_mgmt { - struct rpi_firmware *fw; - const struct vchiq_platform_info *info; - - bool connected; - int num_deferred_callbacks; - /* Protects connected and num_deferred_callbacks */ - struct mutex connected_mutex; - - void (*deferred_callback[VCHIQ_DRV_MAX_CALLBACKS])(void); - - struct semaphore free_fragments_sema; - struct semaphore free_fragments_mutex; - char *fragments_base; - char *free_fragments; - unsigned int fragments_size; - - void __iomem *regs; - - struct vchiq_state state; -}; - -struct user_service { - struct vchiq_service *service; - void __user *userdata; - struct vchiq_instance *instance; - char is_vchi; - char dequeue_pending; - char close_pending; - int message_available_pos; - int msg_insert; - int msg_remove; - struct completion insert_event; - struct completion remove_event; - struct completion close_event; - struct vchiq_header *msg_queue[MSG_QUEUE_SIZE]; -}; - -struct bulk_waiter_node { - struct bulk_waiter bulk_waiter; - int pid; - struct list_head list; -}; - -struct vchiq_instance { - struct vchiq_state *state; - struct vchiq_completion_data_kernel completions[MAX_COMPLETIONS]; - int completion_insert; - int completion_remove; - struct completion insert_event; - struct completion remove_event; - struct mutex completion_mutex; - - int connected; - int closing; - int pid; - int mark; - int use_close_delivered; - int trace; - - struct list_head bulk_waiter_list; - struct mutex bulk_waiter_list_mutex; - - struct vchiq_debugfs_node debugfs_node; -}; - -int -vchiq_use_service(struct vchiq_instance *instance, unsigned int handle); - -extern int -vchiq_release_service(struct vchiq_instance *instance, unsigned int handle); - -extern int -vchiq_check_service(struct vchiq_service *service); - -extern void -vchiq_dump_service_use_state(struct vchiq_state *state); - -extern int -vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, - enum USE_TYPE_E use_type); -extern int -vchiq_release_internal(struct vchiq_state *state, - struct vchiq_service *service); - -extern struct vchiq_debugfs_node * -vchiq_instance_get_debugfs_node(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_use_count(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_pid(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_trace(struct vchiq_instance *instance); - -extern void -vchiq_instance_set_trace(struct vchiq_instance *instance, int trace); - -extern void -vchiq_add_connected_callback(struct vchiq_device *device, - void (*callback)(void)); - -#if IS_ENABLED(CONFIG_VCHIQ_CDEV) - -extern void -vchiq_deregister_chrdev(void); - -extern int -vchiq_register_chrdev(struct device *parent); - -#else - -static inline void vchiq_deregister_chrdev(void) { } -static inline int vchiq_register_chrdev(struct device *parent) { return 0; } - -#endif /* IS_ENABLED(CONFIG_VCHIQ_CDEV) */ - -extern int -service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, - struct vchiq_header *header, unsigned int handle, - void *cb_data, void __user *cb_userdata); - -extern void -free_bulk_waiter(struct vchiq_instance *instance); - -#endif /* VCHIQ_ARM_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c index 41ece91ab88a..f50e637d505c 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c @@ -11,8 +11,8 @@ #include #include -#include "vchiq_arm.h" -#include "vchiq_bus.h" +#include +#include static int vchiq_bus_type_match(struct device *dev, const struct device_driver *drv) { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h deleted file mode 100644 index 9de179b39f85..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2023 Ideas On Board Oy - */ - -#ifndef _VCHIQ_DEVICE_H -#define _VCHIQ_DEVICE_H - -#include -#include - -struct vchiq_drv_mgmt; - -struct vchiq_device { - struct device dev; - struct vchiq_drv_mgmt *drv_mgmt; -}; - -struct vchiq_driver { - int (*probe)(struct vchiq_device *device); - void (*remove)(struct vchiq_device *device); - int (*resume)(struct vchiq_device *device); - int (*suspend)(struct vchiq_device *device, - pm_message_t state); - - const struct vchiq_device_id *id_table; - struct device_driver driver; -}; - -static inline struct vchiq_device *to_vchiq_device(struct device *d) -{ - return container_of(d, struct vchiq_device, dev); -} - -static inline struct vchiq_driver *to_vchiq_driver(struct device_driver *d) -{ - return container_of(d, struct vchiq_driver, driver); -} - -extern const struct bus_type vchiq_bus_type; - -struct vchiq_device * -vchiq_device_register(struct device *parent, const char *name); -void vchiq_device_unregister(struct vchiq_device *dev); - -int vchiq_driver_register(struct vchiq_driver *vchiq_drv); -void vchiq_driver_unregister(struct vchiq_driver *vchiq_drv); - -/** - * module_vchiq_driver() - Helper macro for registering a vchiq driver - * @__vchiq_driver: vchiq driver struct - * - * Helper macro for vchiq drivers which do not do anything special in - * module init/exit. This eliminates a lot of boilerplate. Each module may only - * use this macro once, and calling it replaces module_init() and module_exit() - */ -#define module_vchiq_driver(__vchiq_driver) \ - module_driver(__vchiq_driver, vchiq_driver_register, vchiq_driver_unregister) - -#endif /* _VCHIQ_DEVICE_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h deleted file mode 100644 index a16d0299996c..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2014 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_CFG_H -#define VCHIQ_CFG_H - -#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') -/* The version of VCHIQ - change with any non-trivial change */ -#define VCHIQ_VERSION 8 -/* - * The minimum compatible version - update to match VCHIQ_VERSION with any - * incompatible change - */ -#define VCHIQ_VERSION_MIN 3 - -/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ -#define VCHIQ_VERSION_LIB_VERSION 7 - -/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ -#define VCHIQ_VERSION_CLOSE_DELIVERED 7 - -/* The version that made it safe to use SYNCHRONOUS mode */ -#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 - -#define VCHIQ_MAX_STATES 1 -#define VCHIQ_MAX_SERVICES 4096 -#define VCHIQ_MAX_SLOTS 128 -#define VCHIQ_MAX_SLOTS_PER_SIDE 64 - -#define VCHIQ_NUM_CURRENT_BULKS 32 -#define VCHIQ_NUM_SERVICE_BULKS 4 - -#ifndef VCHIQ_ENABLE_DEBUG -#define VCHIQ_ENABLE_DEBUG 1 -#endif - -#ifndef VCHIQ_ENABLE_STATS -#define VCHIQ_ENABLE_STATS 1 -#endif - -#endif /* VCHIQ_CFG_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 130be2f58342..83de27cfd469 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -15,8 +15,8 @@ #include #include -#include "vchiq_arm.h" -#include "vchiq_core.h" +#include +#include #define VCHIQ_SLOT_HANDLER_STACK 8192 diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h deleted file mode 100644 index e3ed50d26c37..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ /dev/null @@ -1,646 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_CORE_H -#define VCHIQ_CORE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../include/linux/raspberrypi/vchiq.h" -#include "vchiq_cfg.h" - -/* Do this so that we can test-build the code on non-rpi systems */ -#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) - -#else - -#ifndef dsb -#define dsb(a) -#endif - -#endif /* IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) */ - -#define VCHIQ_SERVICE_HANDLE_INVALID 0 - -#define VCHIQ_SLOT_SIZE 4096 -#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) - -#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) -#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) -#define VCHIQ_SLOT_ZERO_SLOTS DIV_ROUND_UP(sizeof(struct vchiq_slot_zero), \ - VCHIQ_SLOT_SIZE) - -#define BITSET_SIZE(b) ((b + 31) >> 5) -#define BITSET_WORD(b) (b >> 5) -#define BITSET_BIT(b) (1 << (b & 31)) -#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) -#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) - -enum { - DEBUG_ENTRIES, -#if VCHIQ_ENABLE_DEBUG - DEBUG_SLOT_HANDLER_COUNT, - DEBUG_SLOT_HANDLER_LINE, - DEBUG_PARSE_LINE, - DEBUG_PARSE_HEADER, - DEBUG_PARSE_MSGID, - DEBUG_AWAIT_COMPLETION_LINE, - DEBUG_DEQUEUE_MESSAGE_LINE, - DEBUG_SERVICE_CALLBACK_LINE, - DEBUG_MSG_QUEUE_FULL_COUNT, - DEBUG_COMPLETION_QUEUE_FULL_COUNT, -#endif - DEBUG_MAX -}; - -#if VCHIQ_ENABLE_DEBUG - -#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug -#define DEBUG_TRACE(d) \ - do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0) -#define DEBUG_VALUE(d, v) \ - do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0) -#define DEBUG_COUNT(d) \ - do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0) - -#else /* VCHIQ_ENABLE_DEBUG */ - -#define DEBUG_INITIALISE(local) -#define DEBUG_TRACE(d) -#define DEBUG_VALUE(d, v) -#define DEBUG_COUNT(d) - -#endif /* VCHIQ_ENABLE_DEBUG */ - -enum vchiq_connstate { - VCHIQ_CONNSTATE_DISCONNECTED, - VCHIQ_CONNSTATE_CONNECTING, - VCHIQ_CONNSTATE_CONNECTED, - VCHIQ_CONNSTATE_PAUSING, - VCHIQ_CONNSTATE_PAUSE_SENT, - VCHIQ_CONNSTATE_PAUSED, - VCHIQ_CONNSTATE_RESUMING, - VCHIQ_CONNSTATE_PAUSE_TIMEOUT, - VCHIQ_CONNSTATE_RESUME_TIMEOUT -}; - -enum { - VCHIQ_SRVSTATE_FREE, - VCHIQ_SRVSTATE_HIDDEN, - VCHIQ_SRVSTATE_LISTENING, - VCHIQ_SRVSTATE_OPENING, - VCHIQ_SRVSTATE_OPEN, - VCHIQ_SRVSTATE_OPENSYNC, - VCHIQ_SRVSTATE_CLOSESENT, - VCHIQ_SRVSTATE_CLOSERECVD, - VCHIQ_SRVSTATE_CLOSEWAIT, - VCHIQ_SRVSTATE_CLOSED -}; - -enum vchiq_bulk_dir { - VCHIQ_BULK_TRANSMIT, - VCHIQ_BULK_RECEIVE -}; - -struct vchiq_bulk { - short mode; - short dir; - void *cb_data; - void __user *cb_userdata; - struct bulk_waiter *waiter; - dma_addr_t dma_addr; - int size; - void *remote_data; - int remote_size; - int actual; - void *offset; - void __user *uoffset; -}; - -struct vchiq_bulk_queue { - int local_insert; /* Where to insert the next local bulk */ - int remote_insert; /* Where to insert the next remote bulk (master) */ - int process; /* Bulk to transfer next */ - int remote_notify; /* Bulk to notify the remote client of next (mstr) */ - int remove; /* Bulk to notify the local client of, and remove, next */ - struct vchiq_bulk bulks[VCHIQ_NUM_SERVICE_BULKS]; -}; - -/* - * Remote events provide a way of presenting several virtual doorbells to a - * peer (ARM host to VPU) using only one physical doorbell. They can be thought - * of as a way for the peer to signal a semaphore, in this case implemented as - * a workqueue. - * - * Remote events remain signalled until acknowledged by the receiver, and they - * are non-counting. They are designed in such a way as to minimise the number - * of interrupts and avoid unnecessary waiting. - * - * A remote_event is as small data structures that live in shared memory. It - * comprises two booleans - armed and fired: - * - * The sender sets fired when they signal the receiver. - * If fired is set, the receiver has been signalled and need not wait. - * The receiver sets the armed field before they begin to wait. - * If armed is set, the receiver is waiting and wishes to be woken by interrupt. - */ -struct remote_event { - int armed; - int fired; - u32 __unused; -}; - -struct opaque_platform_state; - -struct vchiq_slot { - char data[VCHIQ_SLOT_SIZE]; -}; - -struct vchiq_slot_info { - /* Use two counters rather than one to avoid the need for a mutex. */ - short use_count; - short release_count; -}; - -/* - * VCHIQ is a reliable connection-oriented datagram protocol. - * - * A VCHIQ service is equivalent to a TCP connection, except: - * + FOURCCs are used for the rendezvous, and port numbers are assigned at the - * time the connection is established. - * + There is less of a distinction between server and client sockets, the only - * difference being which end makes the first move. - * + For a multi-client server, the server creates new "listening" services as - * the existing one becomes connected - there is no need to specify the - * maximum number of clients up front. - * + Data transfer is reliable but packetized (messages have defined ends). - * + Messages can be either short (capable of fitting in a slot) and in-band, - * or copied between external buffers (bulk transfers). - */ -struct vchiq_service { - struct vchiq_service_base base; - unsigned int handle; - struct kref ref_count; - struct rcu_head rcu; - int srvstate; - void (*userdata_term)(void *userdata); - unsigned int localport; - unsigned int remoteport; - int public_fourcc; - int client_id; - char auto_close; - char sync; - char closing; - char trace; - atomic_t poll_flags; - short version; - short version_min; - short peer_version; - - struct vchiq_state *state; - struct vchiq_instance *instance; - - int service_use_count; - - struct vchiq_bulk_queue bulk_tx; - struct vchiq_bulk_queue bulk_rx; - - struct completion remove_event; - struct completion bulk_remove_event; - struct mutex bulk_mutex; - - struct service_stats_struct { - int quota_stalls; - int slot_stalls; - int bulk_stalls; - int error_count; - int ctrl_tx_count; - int ctrl_rx_count; - int bulk_tx_count; - int bulk_rx_count; - int bulk_aborted_count; - u64 ctrl_tx_bytes; - u64 ctrl_rx_bytes; - u64 bulk_tx_bytes; - u64 bulk_rx_bytes; - } stats; - - int msg_queue_read; - int msg_queue_write; - struct completion msg_queue_pop; - struct completion msg_queue_push; - struct vchiq_header *msg_queue[VCHIQ_MAX_SLOTS]; -}; - -/* - * The quota information is outside struct vchiq_service so that it can - * be statically allocated, since for accounting reasons a service's slot - * usage is carried over between users of the same port number. - */ -struct vchiq_service_quota { - unsigned short slot_quota; - unsigned short slot_use_count; - unsigned short message_quota; - unsigned short message_use_count; - struct completion quota_event; - int previous_tx_index; -}; - -struct vchiq_shared_state { - /* A non-zero value here indicates that the content is valid. */ - int initialised; - - /* The first and last (inclusive) slots allocated to the owner. */ - int slot_first; - int slot_last; - - /* The slot allocated to synchronous messages from the owner. */ - int slot_sync; - - /* - * Signalling this event indicates that owner's slot handler thread - * should run. - */ - struct remote_event trigger; - - /* - * Indicates the byte position within the stream where the next message - * will be written. The least significant bits are an index into the - * slot. The next bits are the index of the slot in slot_queue. - */ - int tx_pos; - - /* This event should be signalled when a slot is recycled. */ - struct remote_event recycle; - - /* The slot_queue index where the next recycled slot will be written. */ - int slot_queue_recycle; - - /* This event should be signalled when a synchronous message is sent. */ - struct remote_event sync_trigger; - - /* - * This event should be signalled when a synchronous message has been - * released. - */ - struct remote_event sync_release; - - /* A circular buffer of slot indexes. */ - int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; - - /* Debugging state */ - int debug[DEBUG_MAX]; -}; - -/* - * vchiq_slot_zero describes the memory shared between the ARM host and the - * VideoCore VPU. The "master" and "slave" states are owned by the respective - * sides but visible to the other; the slots are shared, and the remaining - * fields are read-only. - * - * In the configuration used by this implementation, the memory is allocated - * by the host, the VPU is the master (the side which controls the DMA for bulk - * transfers), and the host is the slave. - * - * The ownership of slots changes with use: - * + When empty they are owned by the sender. - * + When partially filled they are shared with the receiver. - * + When completely full they are owned by the receiver. - * + When the receiver has finished processing the contents, they are recycled - * back to the sender. - */ -struct vchiq_slot_zero { - int magic; - short version; - short version_min; - int slot_zero_size; - int slot_size; - int max_slots; - int max_slots_per_side; - int platform_data[2]; - struct vchiq_shared_state master; - struct vchiq_shared_state slave; - struct vchiq_slot_info slots[VCHIQ_MAX_SLOTS]; -}; - -/* - * This is the private runtime state used by each side. The same structure was - * originally used by both sides, but implementations have since diverged. - */ -struct vchiq_state { - struct device *dev; - int id; - int initialised; - enum vchiq_connstate conn_state; - short version_common; - - struct vchiq_shared_state *local; - struct vchiq_shared_state *remote; - struct vchiq_slot *slot_data; - - unsigned short default_slot_quota; - unsigned short default_message_quota; - - /* Event indicating connect message received */ - struct completion connect; - - /* Mutex protecting services */ - struct mutex mutex; - struct vchiq_instance **instance; - - /* Processes all incoming messages which aren't synchronous */ - struct task_struct *slot_handler_thread; - - /* - * Slots which have been fully processed and released by the (peer) - * receiver are added to the receiver queue, which is asynchronously - * processed by the recycle thread. - */ - struct task_struct *recycle_thread; - - /* - * Processes incoming synchronous messages - * - * The synchronous message channel is shared between all synchronous - * services, and provides a way for urgent messages to bypass - * potentially long queues of asynchronous messages in the normal slots. - * - * There can be only one outstanding synchronous message in - * each direction, and as a precious shared resource synchronous - * services should be used sparingly. - */ - struct task_struct *sync_thread; - - /* Local implementation of the trigger remote event */ - wait_queue_head_t trigger_event; - - /* Local implementation of the recycle remote event */ - wait_queue_head_t recycle_event; - - /* Local implementation of the sync trigger remote event */ - wait_queue_head_t sync_trigger_event; - - /* Local implementation of the sync release remote event */ - wait_queue_head_t sync_release_event; - - char *tx_data; - char *rx_data; - struct vchiq_slot_info *rx_info; - - struct mutex slot_mutex; - - struct mutex recycle_mutex; - - struct mutex sync_mutex; - - spinlock_t msg_queue_spinlock; - - spinlock_t bulk_waiter_spinlock; - - spinlock_t quota_spinlock; - - /* - * Indicates the byte position within the stream from where the next - * message will be read. The least significant bits are an index into - * the slot.The next bits are the index of the slot in - * remote->slot_queue. - */ - int rx_pos; - - /* - * A cached copy of local->tx_pos. Only write to local->tx_pos, and read - * from remote->tx_pos. - */ - int local_tx_pos; - - /* The slot_queue index of the slot to become available next. */ - int slot_queue_available; - - /* A flag to indicate if any poll has been requested */ - int poll_needed; - - /* Ths index of the previous slot used for data messages. */ - int previous_data_index; - - /* The number of slots occupied by data messages. */ - unsigned short data_use_count; - - /* The maximum number of slots to be occupied by data messages. */ - unsigned short data_quota; - - /* An array of bit sets indicating which services must be polled. */ - atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; - - /* The number of the first unused service */ - int unused_service; - - /* Signalled when a free slot becomes available. */ - struct completion slot_available_event; - - /* Signalled when a free data slot becomes available. */ - struct completion data_quota_event; - - struct state_stats_struct { - int slot_stalls; - int data_stalls; - int ctrl_tx_count; - int ctrl_rx_count; - int error_count; - } stats; - - struct vchiq_service __rcu *services[VCHIQ_MAX_SERVICES]; - struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES]; - struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS]; - - struct opaque_platform_state *platform_state; -}; - -struct pagelist { - u32 length; - u16 type; - u16 offset; - u32 addrs[1]; /* N.B. 12 LSBs hold the number - * of following pages at consecutive - * addresses. - */ -}; - -struct vchiq_pagelist_info { - struct pagelist *pagelist; - size_t pagelist_buffer_size; - dma_addr_t dma_addr; - enum dma_data_direction dma_dir; - unsigned int num_pages; - unsigned int pages_need_release; - struct page **pages; - struct scatterlist *scatterlist; - unsigned int scatterlist_mapped; -}; - -static inline bool vchiq_remote_initialised(const struct vchiq_state *state) -{ - return state->remote && state->remote->initialised; -} - -struct bulk_waiter { - struct vchiq_bulk *bulk; - struct completion event; - int actual; -}; - -struct vchiq_config { - unsigned int max_msg_size; - unsigned int bulk_threshold; /* The message size above which it - * is better to use a bulk transfer - * (<= max_msg_size) - */ - unsigned int max_outstanding_bulks; - unsigned int max_services; - short version; /* The version of VCHIQ */ - short version_min; /* The minimum compatible version of VCHIQ */ -}; - -extern spinlock_t bulk_waiter_spinlock; - -extern const char * -get_conn_state_name(enum vchiq_connstate conn_state); - -extern struct vchiq_slot_zero * -vchiq_init_slots(struct device *dev, void *mem_base, int mem_size); - -extern int -vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, struct device *dev); - -extern int -vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance); - -struct vchiq_service * -vchiq_add_service_internal(struct vchiq_state *state, - const struct vchiq_service_params_kernel *params, - int srvstate, struct vchiq_instance *instance, - void (*userdata_term)(void *userdata)); - -extern int -vchiq_open_service_internal(struct vchiq_service *service, int client_id); - -extern int -vchiq_close_service_internal(struct vchiq_service *service, int close_recvd); - -extern void -vchiq_terminate_service_internal(struct vchiq_service *service); - -extern void -vchiq_free_service_internal(struct vchiq_service *service); - -extern void -vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance); - -extern void -remote_event_pollall(struct vchiq_state *state); - -extern int -vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle, - struct bulk_waiter *userdata); - -extern int -vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk); - -extern int -vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk); - -extern void -vchiq_dump_state(struct seq_file *f, struct vchiq_state *state); - -extern void -request_poll(struct vchiq_state *state, struct vchiq_service *service, - int poll_type); - -struct vchiq_service *handle_to_service(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_service_by_handle(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_service_by_port(struct vchiq_state *state, unsigned int localport); - -extern struct vchiq_service * -find_service_for_instance(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_closed_service_for_instance(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -__next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx); - -extern struct vchiq_service * -next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx); - -extern void -vchiq_service_get(struct vchiq_service *service); - -extern void -vchiq_service_put(struct vchiq_service *service); - -extern int -vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, - size_t size); - -void vchiq_dump_platform_state(struct seq_file *f); - -void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f); - -void vchiq_dump_platform_service_state(struct seq_file *f, struct vchiq_service *service); - -int vchiq_use_service_internal(struct vchiq_service *service); - -int vchiq_release_service_internal(struct vchiq_service *service); - -void vchiq_on_remote_use(struct vchiq_state *state); - -void vchiq_on_remote_release(struct vchiq_state *state); - -int vchiq_platform_init_state(struct vchiq_state *state); - -int vchiq_check_service(struct vchiq_service *service); - -int vchiq_send_remote_use(struct vchiq_state *state); - -int vchiq_send_remote_use_active(struct vchiq_state *state); - -void vchiq_platform_conn_state_changed(struct vchiq_state *state, - enum vchiq_connstate oldstate, - enum vchiq_connstate newstate); - -void vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate); - -void vchiq_log_dump_mem(struct device *dev, const char *label, u32 addr, - const void *void_mem, size_t num_bytes); - -int vchiq_remove_service(struct vchiq_instance *instance, unsigned int service); - -int vchiq_get_client_id(struct vchiq_instance *instance, unsigned int service); - -void vchiq_get_config(struct vchiq_config *config); - -int vchiq_set_service_option(struct vchiq_instance *instance, unsigned int service, - enum vchiq_service_option option, int value); - -#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c index d5f7f61c5626..c82326a9b6d9 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -5,9 +5,9 @@ */ #include -#include "vchiq_core.h" -#include "vchiq_arm.h" -#include "vchiq_debugfs.h" +#include +#include +#include #ifdef CONFIG_DEBUG_FS diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h deleted file mode 100644 index b29e6693c949..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. */ - -#ifndef VCHIQ_DEBUGFS_H -#define VCHIQ_DEBUGFS_H - -struct vchiq_state; -struct vchiq_instance; - -struct vchiq_debugfs_node { - struct dentry *dentry; -}; - -void vchiq_debugfs_init(struct vchiq_state *state); - -void vchiq_debugfs_deinit(void); - -void vchiq_debugfs_add_instance(struct vchiq_instance *instance); - -void vchiq_debugfs_remove_instance(struct vchiq_instance *instance); - -#endif /* VCHIQ_DEBUGFS_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c index 3b20ba5c7362..0f3dde2657d6 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c @@ -11,10 +11,11 @@ #include #include -#include "vchiq_core.h" +#include +#include +#include + #include "vchiq_ioctl.h" -#include "vchiq_arm.h" -#include "vchiq_debugfs.h" static const char *const ioctl_names[] = { "CONNECT", diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h index afb71a83cfe7..d0c759f6d8ea 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -5,8 +5,7 @@ #define VCHIQ_IOCTLS_H #include - -#include "../../include/linux/raspberrypi/vchiq.h" +#include #define VCHIQ_IOC_MAGIC 0xc4 #define VCHIQ_INVALID_HANDLE (~0) diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index c2b5a37915f2..cd073ed3ea2d 100644 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -22,11 +22,12 @@ #include #include #include +#include #include #include -#include "../include/linux/raspberrypi/vchiq.h" -#include "../interface/vchiq_arm/vchiq_arm.h" +#include + #include "mmal-common.h" #include "mmal-vchiq.h" #include "mmal-msg.h" diff --git a/include/linux/raspberrypi/vchiq.h b/include/linux/raspberrypi/vchiq.h new file mode 100644 index 000000000000..ee4469f4fc51 --- /dev/null +++ b/include/linux/raspberrypi/vchiq.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ + +#ifndef VCHIQ_H +#define VCHIQ_H + +#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ + (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) + +enum vchiq_reason { + VCHIQ_SERVICE_OPENED, /* service, -, - */ + VCHIQ_SERVICE_CLOSED, /* service, -, - */ + VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ + VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ +}; + +enum vchiq_bulk_mode { + VCHIQ_BULK_MODE_CALLBACK, + VCHIQ_BULK_MODE_BLOCKING, + VCHIQ_BULK_MODE_NOCALLBACK, + VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ +}; + +enum vchiq_service_option { + VCHIQ_SERVICE_OPTION_AUTOCLOSE, + VCHIQ_SERVICE_OPTION_SLOT_QUOTA, + VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, + VCHIQ_SERVICE_OPTION_SYNCHRONOUS, + VCHIQ_SERVICE_OPTION_TRACE +}; + +struct vchiq_header { + /* The message identifier - opaque to applications. */ + int msgid; + + /* Size of message data. */ + unsigned int size; + + char data[]; /* message */ +}; + +struct vchiq_element { + const void __user *data; + unsigned int size; +}; + +struct vchiq_instance; +struct vchiq_state; + +struct vchiq_service_base { + int fourcc; + int (*callback)(struct vchiq_instance *instance, + enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, + void *cb_data, void __user *cb_userdata); + void *userdata; +}; + +struct vchiq_completion_data_kernel { + enum vchiq_reason reason; + struct vchiq_header *header; + void *service_userdata; + void *cb_data; + void __user *cb_userdata; +}; + +struct vchiq_service_params_kernel { + int fourcc; + int (*callback)(struct vchiq_instance *instance, + enum vchiq_reason reason, + struct vchiq_header *header, + unsigned int handle, + void *cb_data, void __user *cb_userdata); + void *userdata; + short version; /* Increment for non-trivial changes */ + short version_min; /* Update for incompatible changes */ +}; + +extern int vchiq_initialise(struct vchiq_state *state, + struct vchiq_instance **pinstance); +extern int vchiq_shutdown(struct vchiq_instance *instance); +extern int vchiq_connect(struct vchiq_instance *instance); +extern int vchiq_open_service(struct vchiq_instance *instance, + const struct vchiq_service_params_kernel *params, + unsigned int *pservice); +extern int vchiq_close_service(struct vchiq_instance *instance, + unsigned int service); +extern int vchiq_use_service(struct vchiq_instance *instance, unsigned int service); +extern int vchiq_release_service(struct vchiq_instance *instance, + unsigned int service); +extern void vchiq_msg_queue_push(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_header *header); +extern void vchiq_release_message(struct vchiq_instance *instance, unsigned int service, + struct vchiq_header *header); +extern int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, + void *data, unsigned int size); +extern int vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int service, + const void *data, unsigned int size, void *userdata, + enum vchiq_bulk_mode mode); +extern int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int service, + void *data, unsigned int size, void *userdata, + enum vchiq_bulk_mode mode); +extern void *vchiq_get_service_userdata(struct vchiq_instance *instance, unsigned int service); +extern int vchiq_get_peer_version(struct vchiq_instance *instance, unsigned int handle, + short *peer_version); +extern struct vchiq_header *vchiq_msg_hold(struct vchiq_instance *instance, unsigned int handle); + +#endif /* VCHIQ_H */ diff --git a/include/linux/raspberrypi/vchiq_arm.h b/include/linux/raspberrypi/vchiq_arm.h new file mode 100644 index 000000000000..e32b02f99024 --- /dev/null +++ b/include/linux/raspberrypi/vchiq_arm.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + */ + +#ifndef VCHIQ_ARM_H +#define VCHIQ_ARM_H + +#include +#include +#include +#include +#include "vchiq_core.h" +#include "vchiq_debugfs.h" + +/* Some per-instance constants */ +#define MAX_COMPLETIONS 128 +#define MAX_SERVICES 64 +#define MAX_ELEMENTS 8 +#define MSG_QUEUE_SIZE 128 + +#define VCHIQ_DRV_MAX_CALLBACKS 10 + +struct rpi_firmware; +struct vchiq_device; + +enum USE_TYPE_E { + USE_TYPE_SERVICE, + USE_TYPE_VCHIQ +}; + +struct vchiq_platform_info { + unsigned int cache_line_size; +}; + +struct vchiq_drv_mgmt { + struct rpi_firmware *fw; + const struct vchiq_platform_info *info; + + bool connected; + int num_deferred_callbacks; + /* Protects connected and num_deferred_callbacks */ + struct mutex connected_mutex; + + void (*deferred_callback[VCHIQ_DRV_MAX_CALLBACKS])(void); + + struct semaphore free_fragments_sema; + struct semaphore free_fragments_mutex; + char *fragments_base; + char *free_fragments; + unsigned int fragments_size; + + void __iomem *regs; + + struct vchiq_state state; +}; + +struct user_service { + struct vchiq_service *service; + void __user *userdata; + struct vchiq_instance *instance; + char is_vchi; + char dequeue_pending; + char close_pending; + int message_available_pos; + int msg_insert; + int msg_remove; + struct completion insert_event; + struct completion remove_event; + struct completion close_event; + struct vchiq_header *msg_queue[MSG_QUEUE_SIZE]; +}; + +struct bulk_waiter_node { + struct bulk_waiter bulk_waiter; + int pid; + struct list_head list; +}; + +struct vchiq_instance { + struct vchiq_state *state; + struct vchiq_completion_data_kernel completions[MAX_COMPLETIONS]; + int completion_insert; + int completion_remove; + struct completion insert_event; + struct completion remove_event; + struct mutex completion_mutex; + + int connected; + int closing; + int pid; + int mark; + int use_close_delivered; + int trace; + + struct list_head bulk_waiter_list; + struct mutex bulk_waiter_list_mutex; + + struct vchiq_debugfs_node debugfs_node; +}; + +int +vchiq_use_service(struct vchiq_instance *instance, unsigned int handle); + +extern int +vchiq_release_service(struct vchiq_instance *instance, unsigned int handle); + +extern int +vchiq_check_service(struct vchiq_service *service); + +extern void +vchiq_dump_service_use_state(struct vchiq_state *state); + +extern int +vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type); +extern int +vchiq_release_internal(struct vchiq_state *state, + struct vchiq_service *service); + +extern struct vchiq_debugfs_node * +vchiq_instance_get_debugfs_node(struct vchiq_instance *instance); + +extern int +vchiq_instance_get_use_count(struct vchiq_instance *instance); + +extern int +vchiq_instance_get_pid(struct vchiq_instance *instance); + +extern int +vchiq_instance_get_trace(struct vchiq_instance *instance); + +extern void +vchiq_instance_set_trace(struct vchiq_instance *instance, int trace); + +extern void +vchiq_add_connected_callback(struct vchiq_device *device, + void (*callback)(void)); + +#if IS_ENABLED(CONFIG_VCHIQ_CDEV) + +extern void +vchiq_deregister_chrdev(void); + +extern int +vchiq_register_chrdev(struct device *parent); + +#else + +static inline void vchiq_deregister_chrdev(void) { } +static inline int vchiq_register_chrdev(struct device *parent) { return 0; } + +#endif /* IS_ENABLED(CONFIG_VCHIQ_CDEV) */ + +extern int +service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, + struct vchiq_header *header, unsigned int handle, + void *cb_data, void __user *cb_userdata); + +extern void +free_bulk_waiter(struct vchiq_instance *instance); + +#endif /* VCHIQ_ARM_H */ diff --git a/include/linux/raspberrypi/vchiq_bus.h b/include/linux/raspberrypi/vchiq_bus.h new file mode 100644 index 000000000000..9de179b39f85 --- /dev/null +++ b/include/linux/raspberrypi/vchiq_bus.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Ideas On Board Oy + */ + +#ifndef _VCHIQ_DEVICE_H +#define _VCHIQ_DEVICE_H + +#include +#include + +struct vchiq_drv_mgmt; + +struct vchiq_device { + struct device dev; + struct vchiq_drv_mgmt *drv_mgmt; +}; + +struct vchiq_driver { + int (*probe)(struct vchiq_device *device); + void (*remove)(struct vchiq_device *device); + int (*resume)(struct vchiq_device *device); + int (*suspend)(struct vchiq_device *device, + pm_message_t state); + + const struct vchiq_device_id *id_table; + struct device_driver driver; +}; + +static inline struct vchiq_device *to_vchiq_device(struct device *d) +{ + return container_of(d, struct vchiq_device, dev); +} + +static inline struct vchiq_driver *to_vchiq_driver(struct device_driver *d) +{ + return container_of(d, struct vchiq_driver, driver); +} + +extern const struct bus_type vchiq_bus_type; + +struct vchiq_device * +vchiq_device_register(struct device *parent, const char *name); +void vchiq_device_unregister(struct vchiq_device *dev); + +int vchiq_driver_register(struct vchiq_driver *vchiq_drv); +void vchiq_driver_unregister(struct vchiq_driver *vchiq_drv); + +/** + * module_vchiq_driver() - Helper macro for registering a vchiq driver + * @__vchiq_driver: vchiq driver struct + * + * Helper macro for vchiq drivers which do not do anything special in + * module init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_vchiq_driver(__vchiq_driver) \ + module_driver(__vchiq_driver, vchiq_driver_register, vchiq_driver_unregister) + +#endif /* _VCHIQ_DEVICE_H */ diff --git a/include/linux/raspberrypi/vchiq_cfg.h b/include/linux/raspberrypi/vchiq_cfg.h new file mode 100644 index 000000000000..a16d0299996c --- /dev/null +++ b/include/linux/raspberrypi/vchiq_cfg.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright (c) 2010-2014 Broadcom. All rights reserved. */ + +#ifndef VCHIQ_CFG_H +#define VCHIQ_CFG_H + +#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') +/* The version of VCHIQ - change with any non-trivial change */ +#define VCHIQ_VERSION 8 +/* + * The minimum compatible version - update to match VCHIQ_VERSION with any + * incompatible change + */ +#define VCHIQ_VERSION_MIN 3 + +/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ +#define VCHIQ_VERSION_LIB_VERSION 7 + +/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ +#define VCHIQ_VERSION_CLOSE_DELIVERED 7 + +/* The version that made it safe to use SYNCHRONOUS mode */ +#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 + +#define VCHIQ_MAX_STATES 1 +#define VCHIQ_MAX_SERVICES 4096 +#define VCHIQ_MAX_SLOTS 128 +#define VCHIQ_MAX_SLOTS_PER_SIDE 64 + +#define VCHIQ_NUM_CURRENT_BULKS 32 +#define VCHIQ_NUM_SERVICE_BULKS 4 + +#ifndef VCHIQ_ENABLE_DEBUG +#define VCHIQ_ENABLE_DEBUG 1 +#endif + +#ifndef VCHIQ_ENABLE_STATS +#define VCHIQ_ENABLE_STATS 1 +#endif + +#endif /* VCHIQ_CFG_H */ diff --git a/include/linux/raspberrypi/vchiq_core.h b/include/linux/raspberrypi/vchiq_core.h new file mode 100644 index 000000000000..e7bf7a114985 --- /dev/null +++ b/include/linux/raspberrypi/vchiq_core.h @@ -0,0 +1,646 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ + +#ifndef VCHIQ_CORE_H +#define VCHIQ_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vchiq.h" +#include "vchiq_cfg.h" + +/* Do this so that we can test-build the code on non-rpi systems */ +#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) + +#else + +#ifndef dsb +#define dsb(a) +#endif + +#endif /* IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) */ + +#define VCHIQ_SERVICE_HANDLE_INVALID 0 + +#define VCHIQ_SLOT_SIZE 4096 +#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) + +#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) +#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) +#define VCHIQ_SLOT_ZERO_SLOTS DIV_ROUND_UP(sizeof(struct vchiq_slot_zero), \ + VCHIQ_SLOT_SIZE) + +#define BITSET_SIZE(b) ((b + 31) >> 5) +#define BITSET_WORD(b) (b >> 5) +#define BITSET_BIT(b) (1 << (b & 31)) +#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) +#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) + +enum { + DEBUG_ENTRIES, +#if VCHIQ_ENABLE_DEBUG + DEBUG_SLOT_HANDLER_COUNT, + DEBUG_SLOT_HANDLER_LINE, + DEBUG_PARSE_LINE, + DEBUG_PARSE_HEADER, + DEBUG_PARSE_MSGID, + DEBUG_AWAIT_COMPLETION_LINE, + DEBUG_DEQUEUE_MESSAGE_LINE, + DEBUG_SERVICE_CALLBACK_LINE, + DEBUG_MSG_QUEUE_FULL_COUNT, + DEBUG_COMPLETION_QUEUE_FULL_COUNT, +#endif + DEBUG_MAX +}; + +#if VCHIQ_ENABLE_DEBUG + +#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug +#define DEBUG_TRACE(d) \ + do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0) +#define DEBUG_VALUE(d, v) \ + do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0) +#define DEBUG_COUNT(d) \ + do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0) + +#else /* VCHIQ_ENABLE_DEBUG */ + +#define DEBUG_INITIALISE(local) +#define DEBUG_TRACE(d) +#define DEBUG_VALUE(d, v) +#define DEBUG_COUNT(d) + +#endif /* VCHIQ_ENABLE_DEBUG */ + +enum vchiq_connstate { + VCHIQ_CONNSTATE_DISCONNECTED, + VCHIQ_CONNSTATE_CONNECTING, + VCHIQ_CONNSTATE_CONNECTED, + VCHIQ_CONNSTATE_PAUSING, + VCHIQ_CONNSTATE_PAUSE_SENT, + VCHIQ_CONNSTATE_PAUSED, + VCHIQ_CONNSTATE_RESUMING, + VCHIQ_CONNSTATE_PAUSE_TIMEOUT, + VCHIQ_CONNSTATE_RESUME_TIMEOUT +}; + +enum { + VCHIQ_SRVSTATE_FREE, + VCHIQ_SRVSTATE_HIDDEN, + VCHIQ_SRVSTATE_LISTENING, + VCHIQ_SRVSTATE_OPENING, + VCHIQ_SRVSTATE_OPEN, + VCHIQ_SRVSTATE_OPENSYNC, + VCHIQ_SRVSTATE_CLOSESENT, + VCHIQ_SRVSTATE_CLOSERECVD, + VCHIQ_SRVSTATE_CLOSEWAIT, + VCHIQ_SRVSTATE_CLOSED +}; + +enum vchiq_bulk_dir { + VCHIQ_BULK_TRANSMIT, + VCHIQ_BULK_RECEIVE +}; + +struct vchiq_bulk { + short mode; + short dir; + void *cb_data; + void __user *cb_userdata; + struct bulk_waiter *waiter; + dma_addr_t dma_addr; + int size; + void *remote_data; + int remote_size; + int actual; + void *offset; + void __user *uoffset; +}; + +struct vchiq_bulk_queue { + int local_insert; /* Where to insert the next local bulk */ + int remote_insert; /* Where to insert the next remote bulk (master) */ + int process; /* Bulk to transfer next */ + int remote_notify; /* Bulk to notify the remote client of next (mstr) */ + int remove; /* Bulk to notify the local client of, and remove, next */ + struct vchiq_bulk bulks[VCHIQ_NUM_SERVICE_BULKS]; +}; + +/* + * Remote events provide a way of presenting several virtual doorbells to a + * peer (ARM host to VPU) using only one physical doorbell. They can be thought + * of as a way for the peer to signal a semaphore, in this case implemented as + * a workqueue. + * + * Remote events remain signalled until acknowledged by the receiver, and they + * are non-counting. They are designed in such a way as to minimise the number + * of interrupts and avoid unnecessary waiting. + * + * A remote_event is as small data structures that live in shared memory. It + * comprises two booleans - armed and fired: + * + * The sender sets fired when they signal the receiver. + * If fired is set, the receiver has been signalled and need not wait. + * The receiver sets the armed field before they begin to wait. + * If armed is set, the receiver is waiting and wishes to be woken by interrupt. + */ +struct remote_event { + int armed; + int fired; + u32 __unused; +}; + +struct opaque_platform_state; + +struct vchiq_slot { + char data[VCHIQ_SLOT_SIZE]; +}; + +struct vchiq_slot_info { + /* Use two counters rather than one to avoid the need for a mutex. */ + short use_count; + short release_count; +}; + +/* + * VCHIQ is a reliable connection-oriented datagram protocol. + * + * A VCHIQ service is equivalent to a TCP connection, except: + * + FOURCCs are used for the rendezvous, and port numbers are assigned at the + * time the connection is established. + * + There is less of a distinction between server and client sockets, the only + * difference being which end makes the first move. + * + For a multi-client server, the server creates new "listening" services as + * the existing one becomes connected - there is no need to specify the + * maximum number of clients up front. + * + Data transfer is reliable but packetized (messages have defined ends). + * + Messages can be either short (capable of fitting in a slot) and in-band, + * or copied between external buffers (bulk transfers). + */ +struct vchiq_service { + struct vchiq_service_base base; + unsigned int handle; + struct kref ref_count; + struct rcu_head rcu; + int srvstate; + void (*userdata_term)(void *userdata); + unsigned int localport; + unsigned int remoteport; + int public_fourcc; + int client_id; + char auto_close; + char sync; + char closing; + char trace; + atomic_t poll_flags; + short version; + short version_min; + short peer_version; + + struct vchiq_state *state; + struct vchiq_instance *instance; + + int service_use_count; + + struct vchiq_bulk_queue bulk_tx; + struct vchiq_bulk_queue bulk_rx; + + struct completion remove_event; + struct completion bulk_remove_event; + struct mutex bulk_mutex; + + struct service_stats_struct { + int quota_stalls; + int slot_stalls; + int bulk_stalls; + int error_count; + int ctrl_tx_count; + int ctrl_rx_count; + int bulk_tx_count; + int bulk_rx_count; + int bulk_aborted_count; + u64 ctrl_tx_bytes; + u64 ctrl_rx_bytes; + u64 bulk_tx_bytes; + u64 bulk_rx_bytes; + } stats; + + int msg_queue_read; + int msg_queue_write; + struct completion msg_queue_pop; + struct completion msg_queue_push; + struct vchiq_header *msg_queue[VCHIQ_MAX_SLOTS]; +}; + +/* + * The quota information is outside struct vchiq_service so that it can + * be statically allocated, since for accounting reasons a service's slot + * usage is carried over between users of the same port number. + */ +struct vchiq_service_quota { + unsigned short slot_quota; + unsigned short slot_use_count; + unsigned short message_quota; + unsigned short message_use_count; + struct completion quota_event; + int previous_tx_index; +}; + +struct vchiq_shared_state { + /* A non-zero value here indicates that the content is valid. */ + int initialised; + + /* The first and last (inclusive) slots allocated to the owner. */ + int slot_first; + int slot_last; + + /* The slot allocated to synchronous messages from the owner. */ + int slot_sync; + + /* + * Signalling this event indicates that owner's slot handler thread + * should run. + */ + struct remote_event trigger; + + /* + * Indicates the byte position within the stream where the next message + * will be written. The least significant bits are an index into the + * slot. The next bits are the index of the slot in slot_queue. + */ + int tx_pos; + + /* This event should be signalled when a slot is recycled. */ + struct remote_event recycle; + + /* The slot_queue index where the next recycled slot will be written. */ + int slot_queue_recycle; + + /* This event should be signalled when a synchronous message is sent. */ + struct remote_event sync_trigger; + + /* + * This event should be signalled when a synchronous message has been + * released. + */ + struct remote_event sync_release; + + /* A circular buffer of slot indexes. */ + int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; + + /* Debugging state */ + int debug[DEBUG_MAX]; +}; + +/* + * vchiq_slot_zero describes the memory shared between the ARM host and the + * VideoCore VPU. The "master" and "slave" states are owned by the respective + * sides but visible to the other; the slots are shared, and the remaining + * fields are read-only. + * + * In the configuration used by this implementation, the memory is allocated + * by the host, the VPU is the master (the side which controls the DMA for bulk + * transfers), and the host is the slave. + * + * The ownership of slots changes with use: + * + When empty they are owned by the sender. + * + When partially filled they are shared with the receiver. + * + When completely full they are owned by the receiver. + * + When the receiver has finished processing the contents, they are recycled + * back to the sender. + */ +struct vchiq_slot_zero { + int magic; + short version; + short version_min; + int slot_zero_size; + int slot_size; + int max_slots; + int max_slots_per_side; + int platform_data[2]; + struct vchiq_shared_state master; + struct vchiq_shared_state slave; + struct vchiq_slot_info slots[VCHIQ_MAX_SLOTS]; +}; + +/* + * This is the private runtime state used by each side. The same structure was + * originally used by both sides, but implementations have since diverged. + */ +struct vchiq_state { + struct device *dev; + int id; + int initialised; + enum vchiq_connstate conn_state; + short version_common; + + struct vchiq_shared_state *local; + struct vchiq_shared_state *remote; + struct vchiq_slot *slot_data; + + unsigned short default_slot_quota; + unsigned short default_message_quota; + + /* Event indicating connect message received */ + struct completion connect; + + /* Mutex protecting services */ + struct mutex mutex; + struct vchiq_instance **instance; + + /* Processes all incoming messages which aren't synchronous */ + struct task_struct *slot_handler_thread; + + /* + * Slots which have been fully processed and released by the (peer) + * receiver are added to the receiver queue, which is asynchronously + * processed by the recycle thread. + */ + struct task_struct *recycle_thread; + + /* + * Processes incoming synchronous messages + * + * The synchronous message channel is shared between all synchronous + * services, and provides a way for urgent messages to bypass + * potentially long queues of asynchronous messages in the normal slots. + * + * There can be only one outstanding synchronous message in + * each direction, and as a precious shared resource synchronous + * services should be used sparingly. + */ + struct task_struct *sync_thread; + + /* Local implementation of the trigger remote event */ + wait_queue_head_t trigger_event; + + /* Local implementation of the recycle remote event */ + wait_queue_head_t recycle_event; + + /* Local implementation of the sync trigger remote event */ + wait_queue_head_t sync_trigger_event; + + /* Local implementation of the sync release remote event */ + wait_queue_head_t sync_release_event; + + char *tx_data; + char *rx_data; + struct vchiq_slot_info *rx_info; + + struct mutex slot_mutex; + + struct mutex recycle_mutex; + + struct mutex sync_mutex; + + spinlock_t msg_queue_spinlock; + + spinlock_t bulk_waiter_spinlock; + + spinlock_t quota_spinlock; + + /* + * Indicates the byte position within the stream from where the next + * message will be read. The least significant bits are an index into + * the slot.The next bits are the index of the slot in + * remote->slot_queue. + */ + int rx_pos; + + /* + * A cached copy of local->tx_pos. Only write to local->tx_pos, and read + * from remote->tx_pos. + */ + int local_tx_pos; + + /* The slot_queue index of the slot to become available next. */ + int slot_queue_available; + + /* A flag to indicate if any poll has been requested */ + int poll_needed; + + /* Ths index of the previous slot used for data messages. */ + int previous_data_index; + + /* The number of slots occupied by data messages. */ + unsigned short data_use_count; + + /* The maximum number of slots to be occupied by data messages. */ + unsigned short data_quota; + + /* An array of bit sets indicating which services must be polled. */ + atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + + /* The number of the first unused service */ + int unused_service; + + /* Signalled when a free slot becomes available. */ + struct completion slot_available_event; + + /* Signalled when a free data slot becomes available. */ + struct completion data_quota_event; + + struct state_stats_struct { + int slot_stalls; + int data_stalls; + int ctrl_tx_count; + int ctrl_rx_count; + int error_count; + } stats; + + struct vchiq_service __rcu *services[VCHIQ_MAX_SERVICES]; + struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES]; + struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS]; + + struct opaque_platform_state *platform_state; +}; + +struct pagelist { + u32 length; + u16 type; + u16 offset; + u32 addrs[1]; /* N.B. 12 LSBs hold the number + * of following pages at consecutive + * addresses. + */ +}; + +struct vchiq_pagelist_info { + struct pagelist *pagelist; + size_t pagelist_buffer_size; + dma_addr_t dma_addr; + enum dma_data_direction dma_dir; + unsigned int num_pages; + unsigned int pages_need_release; + struct page **pages; + struct scatterlist *scatterlist; + unsigned int scatterlist_mapped; +}; + +static inline bool vchiq_remote_initialised(const struct vchiq_state *state) +{ + return state->remote && state->remote->initialised; +} + +struct bulk_waiter { + struct vchiq_bulk *bulk; + struct completion event; + int actual; +}; + +struct vchiq_config { + unsigned int max_msg_size; + unsigned int bulk_threshold; /* The message size above which it + * is better to use a bulk transfer + * (<= max_msg_size) + */ + unsigned int max_outstanding_bulks; + unsigned int max_services; + short version; /* The version of VCHIQ */ + short version_min; /* The minimum compatible version of VCHIQ */ +}; + +extern spinlock_t bulk_waiter_spinlock; + +extern const char * +get_conn_state_name(enum vchiq_connstate conn_state); + +extern struct vchiq_slot_zero * +vchiq_init_slots(struct device *dev, void *mem_base, int mem_size); + +extern int +vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, struct device *dev); + +extern int +vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance); + +struct vchiq_service * +vchiq_add_service_internal(struct vchiq_state *state, + const struct vchiq_service_params_kernel *params, + int srvstate, struct vchiq_instance *instance, + void (*userdata_term)(void *userdata)); + +extern int +vchiq_open_service_internal(struct vchiq_service *service, int client_id); + +extern int +vchiq_close_service_internal(struct vchiq_service *service, int close_recvd); + +extern void +vchiq_terminate_service_internal(struct vchiq_service *service); + +extern void +vchiq_free_service_internal(struct vchiq_service *service); + +extern void +vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance); + +extern void +remote_event_pollall(struct vchiq_state *state); + +extern int +vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle, + struct bulk_waiter *userdata); + +extern int +vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk); + +extern int +vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk); + +extern void +vchiq_dump_state(struct seq_file *f, struct vchiq_state *state); + +extern void +request_poll(struct vchiq_state *state, struct vchiq_service *service, + int poll_type); + +struct vchiq_service *handle_to_service(struct vchiq_instance *instance, unsigned int handle); + +extern struct vchiq_service * +find_service_by_handle(struct vchiq_instance *instance, unsigned int handle); + +extern struct vchiq_service * +find_service_by_port(struct vchiq_state *state, unsigned int localport); + +extern struct vchiq_service * +find_service_for_instance(struct vchiq_instance *instance, unsigned int handle); + +extern struct vchiq_service * +find_closed_service_for_instance(struct vchiq_instance *instance, unsigned int handle); + +extern struct vchiq_service * +__next_service_by_instance(struct vchiq_state *state, + struct vchiq_instance *instance, + int *pidx); + +extern struct vchiq_service * +next_service_by_instance(struct vchiq_state *state, + struct vchiq_instance *instance, + int *pidx); + +extern void +vchiq_service_get(struct vchiq_service *service); + +extern void +vchiq_service_put(struct vchiq_service *service); + +extern int +vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle, + ssize_t (*copy_callback)(void *context, void *dest, + size_t offset, size_t maxsize), + void *context, + size_t size); + +void vchiq_dump_platform_state(struct seq_file *f); + +void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f); + +void vchiq_dump_platform_service_state(struct seq_file *f, struct vchiq_service *service); + +int vchiq_use_service_internal(struct vchiq_service *service); + +int vchiq_release_service_internal(struct vchiq_service *service); + +void vchiq_on_remote_use(struct vchiq_state *state); + +void vchiq_on_remote_release(struct vchiq_state *state); + +int vchiq_platform_init_state(struct vchiq_state *state); + +int vchiq_check_service(struct vchiq_service *service); + +int vchiq_send_remote_use(struct vchiq_state *state); + +int vchiq_send_remote_use_active(struct vchiq_state *state); + +void vchiq_platform_conn_state_changed(struct vchiq_state *state, + enum vchiq_connstate oldstate, + enum vchiq_connstate newstate); + +void vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate); + +void vchiq_log_dump_mem(struct device *dev, const char *label, u32 addr, + const void *void_mem, size_t num_bytes); + +int vchiq_remove_service(struct vchiq_instance *instance, unsigned int service); + +int vchiq_get_client_id(struct vchiq_instance *instance, unsigned int service); + +void vchiq_get_config(struct vchiq_config *config); + +int vchiq_set_service_option(struct vchiq_instance *instance, unsigned int service, + enum vchiq_service_option option, int value); + +#endif diff --git a/include/linux/raspberrypi/vchiq_debugfs.h b/include/linux/raspberrypi/vchiq_debugfs.h new file mode 100644 index 000000000000..b29e6693c949 --- /dev/null +++ b/include/linux/raspberrypi/vchiq_debugfs.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. */ + +#ifndef VCHIQ_DEBUGFS_H +#define VCHIQ_DEBUGFS_H + +struct vchiq_state; +struct vchiq_instance; + +struct vchiq_debugfs_node { + struct dentry *dentry; +}; + +void vchiq_debugfs_init(struct vchiq_state *state); + +void vchiq_debugfs_deinit(void); + +void vchiq_debugfs_add_instance(struct vchiq_instance *instance); + +void vchiq_debugfs_remove_instance(struct vchiq_instance *instance); + +#endif /* VCHIQ_DEBUGFS_H */ -- cgit