interface/vchiq_arm/vchiq_arm.o \
interface/vchiq_arm/vchiq_2835_arm.o \
interface/vchiq_arm/vchiq_debugfs.o \
- interface/vchiq_arm/vchiq_shim.o \
interface/vchiq_arm/vchiq_connected.o \
obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
{
mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
}
static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
{
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
mutex_unlock(&instance->vchi_mutex);
}
int status;
/* Open the VCHI service connections */
- status = vchi_service_open(vchiq_instance, ¶ms,
- &instance->service_handle);
+ status = vchiq_open_service(vchiq_instance, ¶ms,
+ &instance->service_handle);
if (status) {
dev_err(instance->dev,
}
/* Finished with the service for now */
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
return 0;
}
int status;
mutex_lock(&instance->vchi_mutex);
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
/* Close all VCHI service connections */
- status = vchi_service_close(instance->service_handle);
+ status = vchiq_close_service(instance->service_handle);
if (status) {
dev_err(instance->dev,
"failed to close VCHI service connection (status=%d)\n",
int ret;
/* Initialize and create a VCHI connection */
- ret = vchi_initialise(&vchi_ctx->instance);
+ ret = vchiq_initialise(&vchi_ctx->instance);
if (ret) {
dev_err(dev, "failed to initialise VCHI instance (ret=%d)\n",
ret);
return -EIO;
}
- ret = vchi_connect(vchi_ctx->instance);
+ ret = vchiq_connect(vchi_ctx->instance);
if (ret) {
dev_dbg(dev, "failed to connect VCHI instance (ret=%d)\n",
ret);
void bcm2835_free_vchi_ctx(struct bcm2835_vchi_ctx *vchi_ctx)
{
/* Close the VCHI connection - it will also free vchi_ctx->instance */
- WARN_ON(vchi_disconnect(vchi_ctx->instance));
+ WARN_ON(vchiq_shutdown(vchi_ctx->instance));
vchi_ctx->instance = NULL;
}
goto deinit;
bcm2835_audio_lock(instance);
- vchi_get_peer_version(instance->service_handle,
- &instance->peer_version);
+ vchiq_get_peer_version(instance->service_handle,
+ &instance->peer_version);
bcm2835_audio_unlock(instance);
if (instance->peer_version < 2 || force_bulk)
instance->max_packet = 0; /* bulk transfer */
#include <sound/pcm.h>
#include <sound/pcm-indirect.h>
#include "interface/vchiq_arm/vchiq_if.h"
-#include "interface/vchi/vchi.h"
#define MAX_SUBSTREAMS (8)
#define AVAIL_SUBSTREAMS_MASK (0xff)
--- /dev/null
+1) Import drivers using VCHI.
+
+VCHI is just a tool to let drivers talk to the firmware. Here are
+some of the ones we want:
+
+ - vc_mem (https://github.com/raspberrypi/linux/blob/rpi-4.4.y/drivers/char/broadcom/vc_mem.c)
+
+ This driver is what the vcdbg userspace program uses to set up its
+ requests to the firmware, which are transmitted across VCHIQ. vcdbg
+ is really useful for debugging firmware interactions.
+
+ - VCSM (https://github.com/raspberrypi/linux/tree/rpi-4.4.y/drivers/char/broadcom/vc_sm)
+
+ This driver is used for talking about regions of VC memory across
+ firmware protocols including VCHI. We'll want to extend this driver
+ to manage these buffers as dmabufs so that we can zero-copy import
+ camera images into vc4 for rendering/display.
+
+2) Garbage-collect unused code
+
+One of the reasons this driver wasn't upstreamed previously was that
+there's a lot code that got built that's probably unnecessary these
+days. Once we have the set of VCHI-using drivers we want in tree, we
+should be able to do a sweep of the code to see what's left that's
+unused.
+
+3) Make driver more portable
+
+Building this driver with arm/multi_v7_defconfig or arm64/defconfig
+leads to data corruption during the following command:
+
+ vchiq_test -f 1
+
+This should be fixed.
+
+4) Fix kernel module support
+
+Even the VPU firmware doesn't support a VCHI re-connect, the driver
+should properly handle a module unload. This also includes that all
+resouces must be freed (kthreads, debugfs entries, ...) and global
+variables avoided.
+
+5) Cleanup logging mechanism
+
+The driver should probably be using the standard kernel logging mechanisms
+such as dev_info, dev_dbg, and friends.
+
+6) Documentation
+
+A short top-down description of this driver's architecture (function of
+kthreads, userspace, limitations) could be very helpful for reviewers.
+
+7) Review and comment memory barriers
+
+There is a heavy use of memory barriers in this driver, it would be very
+beneficial to go over all of them and, if correct, comment on their merits.
+Extra points to whomever confidently reviews the remote_event_*() family of
+functions.
+
+8) Get rid of custom function return values
+
+Most functions use a custom set of return values, we should force proper Linux
+error numbers. Special care is needed for VCHIQ_RETRY.
+
+9) Reformat core code with more sane indentations
+
+The code follows the 80 characters limitation yet tends to go 3 or 4 levels of
+indentation deep making it very unpleasant to read. This is specially relevant
+in the character driver ioctl code and in the core thread functions.
+
+10) Reorganize file structure: Move char driver to it's own file and join both
+platform files
+
+The cdev is defined alongside with the platform code in vchiq_arm.c. It would
+be nice to completely decouple it from the actual core code. For instance to be
+able to use bcm2835-audio without having /dev/vchiq created. One could argue
+it's better for security reasons or general cleanliness. It could even be
+interesting to create two different kernel modules, something the likes of
+vchiq-core.ko and vchiq-dev.ko. This would also ease the upstreaming process.
+
+The code in vchiq_bcm2835_arm.c should fit in the generic platform file.
+
+12) Get rid of all the struct typedefs
+
+Most structs are typedefd, it's not encouraged in the kernel.
+
+13) Get rid of all non essential global structures and create a proper per
+device structure
+
+The first thing one generally sees in a probe function is a memory allocation
+for all the device specific data. This structure is then passed all over the
+driver. This is good practice since it makes the driver work regardless of the
+number of devices probed.
+++ /dev/null
-1) Import drivers using VCHI.
-
-VCHI is just a tool to let drivers talk to the firmware. Here are
-some of the ones we want:
-
- - vc_mem (https://github.com/raspberrypi/linux/blob/rpi-4.4.y/drivers/char/broadcom/vc_mem.c)
-
- This driver is what the vcdbg userspace program uses to set up its
- requests to the firmware, which are transmitted across VCHIQ. vcdbg
- is really useful for debugging firmware interactions.
-
- - VCSM (https://github.com/raspberrypi/linux/tree/rpi-4.4.y/drivers/char/broadcom/vc_sm)
-
- This driver is used for talking about regions of VC memory across
- firmware protocols including VCHI. We'll want to extend this driver
- to manage these buffers as dmabufs so that we can zero-copy import
- camera images into vc4 for rendering/display.
-
-2) Garbage-collect unused code
-
-One of the reasons this driver wasn't upstreamed previously was that
-there's a lot code that got built that's probably unnecessary these
-days. Once we have the set of VCHI-using drivers we want in tree, we
-should be able to do a sweep of the code to see what's left that's
-unused.
-
-3) Make driver more portable
-
-Building this driver with arm/multi_v7_defconfig or arm64/defconfig
-leads to data corruption during the following command:
-
- vchiq_test -f 1
-
-This should be fixed.
-
-4) Fix kernel module support
-
-Even the VPU firmware doesn't support a VCHI re-connect, the driver
-should properly handle a module unload. This also includes that all
-resouces must be freed (kthreads, debugfs entries, ...) and global
-variables avoided.
-
-5) Cleanup logging mechanism
-
-The driver should probably be using the standard kernel logging mechanisms
-such as dev_info, dev_dbg, and friends.
-
-6) Documentation
-
-A short top-down description of this driver's architecture (function of
-kthreads, userspace, limitations) could be very helpful for reviewers.
-
-7) Review and comment memory barriers
-
-There is a heavy use of memory barriers in this driver, it would be very
-beneficial to go over all of them and, if correct, comment on their merits.
-Extra points to whomever confidently reviews the remote_event_*() family of
-functions.
-
-8) Get rid of custom function return values
-
-Most functions use a custom set of return values, we should force proper Linux
-error numbers. Special care is needed for VCHIQ_RETRY.
-
-9) Reformat core code with more sane indentations
-
-The code follows the 80 characters limitation yet tends to go 3 or 4 levels of
-indentation deep making it very unpleasant to read. This is specially relevant
-in the character driver ioctl code and in the core thread functions.
-
-10) Reorganize file structure: Move char driver to it's own file and join both
-platform files
-
-The cdev is defined alongside with the platform code in vchiq_arm.c. It would
-be nice to completely decouple it from the actual core code. For instance to be
-able to use bcm2835-audio without having /dev/vchiq created. One could argue
-it's better for security reasons or general cleanliness. It could even be
-interesting to create two different kernel modules, something the likes of
-vchiq-core.ko and vchiq-dev.ko. This would also ease the upstreaming process.
-
-The code in vchiq_bcm2835_arm.c should fit in the generic platform file.
-
-12) Get rid of all the struct typedefs
-
-Most structs are typedefd, it's not encouraged in the kernel.
-
-13) Get rid of all non essential global structures and create a proper per
-device structure
-
-The first thing one generally sees in a probe function is a memory allocation
-for all the device specific data. This structure is then passed all over the
-driver. This is good practice since it makes the driver work regardless of the
-number of devices probed.
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-
-#ifndef VCHI_H_
-#define VCHI_H_
-
-/******************************************************************************
- * Global funcs - implementation is specific to which side you are on
- * (local / remote)
- *****************************************************************************/
-
-// Routine used to initialise the vchi on both local + remote connections
-extern int32_t vchi_initialise(struct vchiq_instance **instance);
-
-extern int32_t vchi_connect(struct vchiq_instance *instance);
-
-//When this is called, ensure that all services have no data pending.
-//Bulk transfers can remain 'queued'
-extern int32_t vchi_disconnect(struct vchiq_instance *instance);
-
-/******************************************************************************
- * Global service API
- *****************************************************************************/
-// Routine to open a named service
-extern int vchi_service_open(struct vchiq_instance *instance,
- struct vchiq_service_params *params,
- unsigned *handle);
-
-extern int32_t vchi_get_peer_version(unsigned handle, short *peer_version);
-
-// Routine to close a named service
-extern int32_t vchi_service_close(unsigned handle);
-
-// Routine to increment ref count on a named service
-extern int32_t vchi_service_use(unsigned handle);
-
-// Routine to decrement ref count on a named service
-extern int32_t vchi_service_release(unsigned handle);
-
-// Routine to look at a message in place.
-// The message is dequeued, so the caller is left holding it; the descriptor is
-// filled in and must be released when the user has finished with the message.
-struct vchiq_header *vchi_msg_hold(unsigned handle);
-
-/*******************************************************************************
- * Global service support API - operations on held messages
- * and message iterators
- ******************************************************************************/
-
-// Routine to release a held message after it has been processed
-extern int32_t vchi_held_msg_release(unsigned handle, struct vchiq_header *message);
-
-/******************************************************************************
- * Configuration plumbing
- *****************************************************************************/
-
-#endif /* VCHI_H_ */
-
-/****************************** End of file **********************************/
}
return ret;
}
+EXPORT_SYMBOL(vchiq_use_service);
enum vchiq_status
vchiq_release_service(unsigned int handle)
}
return ret;
}
+EXPORT_SYMBOL(vchiq_release_service);
struct service_data_struct {
int fourcc;
return status;
}
+EXPORT_SYMBOL(vchiq_close_service);
enum vchiq_status
vchiq_remove_service(unsigned int handle)
unlock_service(service);
}
+EXPORT_SYMBOL(vchiq_release_message);
static void
release_message_sync(struct vchiq_state *state, struct vchiq_header *header)
unlock_service(service);
return status;
}
+EXPORT_SYMBOL(vchiq_get_peer_version);
void vchiq_get_config(struct vchiq_config *config)
{
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include "vchiq_if.h"
-#include "../vchi/vchi.h"
-#include "vchiq.h"
-
-/***********************************************************
- * Name: vchi_held_msg_release
- *
- * Arguments: unsgined handle
- * struct vchiq_header *message
- *
- * Description: Routine to release a held message (after it has been read with
- * vchi_msg_hold)
- *
- * Returns: int - success == 0
- *
- ***********************************************************/
-int vchi_held_msg_release(unsigned handle, struct vchiq_header *message)
-{
- /*
- * Convert the service field pointer back to an
- * unsigned int which is an int.
- * This pointer is opaque to everything except
- * vchi_msg_hold which simply upcasted the int
- * to a pointer.
- */
-
- vchiq_release_message(handle, message);
-
- return 0;
-}
-EXPORT_SYMBOL(vchi_held_msg_release);
-
-/***********************************************************
- * Name: vchi_msg_hold
- *
- * Arguments: struct vchi_service *service,
- * void **data,
- * unsigned *msg_size,
- * struct vchiq_header **message
- *
- * Description: Routine to return a pointer to the current message (to allow
- * in place processing). The message is dequeued - don't forget
- * to release the message using vchi_held_msg_release when you're
- * finished.
- *
- * Returns: int - success == 0
- *
- ***********************************************************/
-struct vchiq_header *vchi_msg_hold(unsigned handle)
-{
- return vchiq_msg_hold(handle);
-}
-EXPORT_SYMBOL(vchi_msg_hold);
-
-/***********************************************************
- * Name: vchi_initialise
- *
- * Arguments: struct vchiq_instance **instance
- *
- * Description: Initialises the hardware but does not transmit anything
- * When run as a Host App this will be called twice hence the need
- * to malloc the state information
- *
- * Returns: 0 if successful, failure otherwise
- *
- ***********************************************************/
-
-int vchi_initialise(struct vchiq_instance **instance)
-{
- return vchiq_initialise(instance);
-}
-EXPORT_SYMBOL(vchi_initialise);
-
-/***********************************************************
- * Name: vchi_connect
- *
- * Arguments: struct vchiq_instance *instance
- *
- * Description: Starts the command service on each connection,
- * causing INIT messages to be pinged back and forth
- *
- * Returns: 0 if successful, failure otherwise
- *
- ***********************************************************/
-int vchi_connect(struct vchiq_instance *instance)
-{
- return vchiq_connect(instance);
-}
-EXPORT_SYMBOL(vchi_connect);
-
-/***********************************************************
- * Name: vchi_disconnect
- *
- * Arguments: struct vchiq_instance *instance
- *
- * Description: Stops the command service on each connection,
- * causing DE-INIT messages to be pinged back and forth
- *
- * Returns: 0 if successful, failure otherwise
- *
- ***********************************************************/
-int vchi_disconnect(struct vchiq_instance *instance)
-{
- return vchiq_shutdown(instance);
-}
-EXPORT_SYMBOL(vchi_disconnect);
-
-/***********************************************************
- * Name: vchi_service_open
- * Name: vchi_service_create
- *
- * Arguments: struct vchiq_instance *instance
- * struct service_creation *setup,
- * unsigned *handle
- *
- * Description: Routine to open a service
- *
- * Returns: int - success == 0
- *
- ***********************************************************/
-
-int vchi_service_open(struct vchiq_instance *instance,
- struct vchiq_service_params *params,
- unsigned *handle)
-{
- return vchiq_open_service(instance, params, handle);
-}
-EXPORT_SYMBOL(vchi_service_open);
-
-int vchi_service_close(unsigned handle)
-{
- return vchiq_close_service(handle);
-}
-EXPORT_SYMBOL(vchi_service_close);
-
-int vchi_get_peer_version(unsigned handle, short *peer_version)
-{
- return vchiq_get_peer_version(handle, peer_version);
-}
-EXPORT_SYMBOL(vchi_get_peer_version);
-
-/***********************************************************
- * Name: vchi_service_use
- *
- * Arguments: unsigned handle
- *
- * Description: Routine to increment refcount on a service
- *
- * Returns: void
- *
- ***********************************************************/
-int vchi_service_use(unsigned handle)
-{
- return vchiq_use_service(handle);
-}
-EXPORT_SYMBOL(vchi_service_use);
-
-/***********************************************************
- * Name: vchi_service_release
- *
- * Arguments: unsigned handle
- *
- * Description: Routine to decrement refcount on a service
- *
- * Returns: void
- *
- ***********************************************************/
-int vchi_service_release(unsigned handle)
-{
- return vchiq_release_service(handle);
-}
-EXPORT_SYMBOL(vchi_service_release);
#include "mmal-msg.h"
#include "interface/vchiq_arm/vchiq_if.h"
-#include "interface/vchi/vchi.h"
/*
* maximum number of components supported.
/* Dummy receive to ensure the buffers remain in order */
len = 8;
/* queue the bulk submission */
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
ret = vchiq_bulk_receive(instance->service_handle,
msg_context->u.bulk.buffer->buffer,
/* Actual receive needs to be a multiple
msg_context,
VCHIQ_BULK_MODE_CALLBACK);
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
if (ret != 0)
pr_err("%s: ctx: %p, vchiq_bulk_receive failed %d\n",
/* no payload in message */
m.u.buffer_from_host.payload_in_message = 0;
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
ret = vchiq_queue_kernel_message(instance->service_handle, &m,
sizeof(struct mmal_msg_header) +
sizeof(m.u.buffer_from_host));
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
return ret;
}
DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
">>> sync message");
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
ret = vchiq_queue_kernel_message(instance->service_handle, msg,
sizeof(struct mmal_msg_header) +
payload_len);
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
if (ret) {
pr_err("error %d queuing message\n", ret);
if (mutex_lock_interruptible(&instance->vchiq_mutex))
return -EINTR;
- vchi_service_use(instance->service_handle);
+ vchiq_use_service(instance->service_handle);
- status = vchi_service_close(instance->service_handle);
+ status = vchiq_close_service(instance->service_handle);
if (status != 0)
pr_err("mmal-vchiq: VCHIQ close failed\n");
BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
/* create a vchi instance */
- status = vchi_initialise(&vchiq_instance);
+ status = vchiq_initialise(&vchiq_instance);
if (status) {
pr_err("Failed to initialise VCHI instance (status=%d)\n",
status);
return -EIO;
}
- status = vchi_connect(vchiq_instance);
+ status = vchiq_connect(vchiq_instance);
if (status) {
pr_err("Failed to connect VCHI instance (status=%d)\n", status);
return -EIO;
if (!instance->bulk_wq)
goto err_free;
- status = vchi_service_open(vchiq_instance, ¶ms,
- &instance->service_handle);
+ status = vchiq_open_service(vchiq_instance, ¶ms,
+ &instance->service_handle);
if (status) {
pr_err("Failed to open VCHI service connection (status=%d)\n",
status);
goto err_close_services;
}
- vchi_service_release(instance->service_handle);
+ vchiq_release_service(instance->service_handle);
*out_instance = instance;
return 0;
err_close_services:
- vchi_service_close(instance->service_handle);
+ vchiq_close_service(instance->service_handle);
destroy_workqueue(instance->bulk_wq);
err_free:
vfree(instance->bulk_scratch);