aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c')
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c88
1 files changed, 58 insertions, 30 deletions
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 28ea8c3a4cba..d4d811884861 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -23,6 +23,8 @@
#include <linux/compat.h>
#include <linux/dma-mapping.h>
#include <linux/rcupdate.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#include "vchiq_core.h"
@@ -269,7 +271,7 @@ failed:
}
EXPORT_SYMBOL(vchiq_connect);
-enum vchiq_status vchiq_add_service(
+static enum vchiq_status vchiq_add_service(
struct vchiq_instance *instance,
const struct vchiq_service_params *params,
unsigned int *phandle)
@@ -306,7 +308,6 @@ enum vchiq_status vchiq_add_service(
return status;
}
-EXPORT_SYMBOL(vchiq_add_service);
enum vchiq_status vchiq_open_service(
struct vchiq_instance *instance,
@@ -354,43 +355,67 @@ vchiq_bulk_transmit(unsigned int handle, const void *data,
{
enum vchiq_status status;
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- status = vchiq_bulk_transfer(handle, (void *)data, size,
- userdata, mode,
- VCHIQ_BULK_TRANSMIT);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- status = vchiq_blocking_bulk_transfer(handle,
- (void *)data, size, VCHIQ_BULK_TRANSMIT);
- break;
- default:
- return VCHIQ_ERROR;
+ while (1) {
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+ status = vchiq_bulk_transfer(handle, (void *)data, size,
+ userdata, mode,
+ VCHIQ_BULK_TRANSMIT);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ status = vchiq_blocking_bulk_transfer(handle,
+ (void *)data, size, VCHIQ_BULK_TRANSMIT);
+ break;
+ default:
+ return VCHIQ_ERROR;
+ }
+
+ /*
+ * vchiq_*_bulk_transfer() may return VCHIQ_RETRY, so we need
+ * to implement a retry mechanism since this function is
+ * supposed to block until queued
+ */
+ if (status != VCHIQ_RETRY)
+ break;
+
+ msleep(1);
}
return status;
}
EXPORT_SYMBOL(vchiq_bulk_transmit);
-enum vchiq_status
-vchiq_bulk_receive(unsigned int handle, void *data,
- unsigned int size, void *userdata, enum vchiq_bulk_mode mode)
+enum vchiq_status vchiq_bulk_receive(unsigned int handle, void *data,
+ unsigned int size, void *userdata,
+ enum vchiq_bulk_mode mode)
{
enum vchiq_status status;
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- status = vchiq_bulk_transfer(handle, data, size, userdata,
- mode, VCHIQ_BULK_RECEIVE);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- status = vchiq_blocking_bulk_transfer(handle,
- (void *)data, size, VCHIQ_BULK_RECEIVE);
- break;
- default:
- return VCHIQ_ERROR;
+ while (1) {
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+ status = vchiq_bulk_transfer(handle, data, size, userdata,
+ mode, VCHIQ_BULK_RECEIVE);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ status = vchiq_blocking_bulk_transfer(handle,
+ (void *)data, size, VCHIQ_BULK_RECEIVE);
+ break;
+ default:
+ return VCHIQ_ERROR;
+ }
+
+ /*
+ * vchiq_*_bulk_transfer() may return VCHIQ_RETRY, so we need
+ * to implement a retry mechanism since this function is
+ * supposed to block until queued
+ */
+ if (status != VCHIQ_RETRY)
+ break;
+
+ msleep(1);
}
return status;
@@ -2547,6 +2572,7 @@ vchiq_use_service(unsigned int handle)
}
return ret;
}
+EXPORT_SYMBOL(vchiq_use_service);
enum vchiq_status
vchiq_release_service(unsigned int handle)
@@ -2560,6 +2586,7 @@ vchiq_release_service(unsigned int handle)
}
return ret;
}
+EXPORT_SYMBOL(vchiq_release_service);
struct service_data_struct {
int fourcc;
@@ -2805,6 +2832,7 @@ failed_platform_init:
static int vchiq_remove(struct platform_device *pdev)
{
+ platform_device_unregister(bcm2835_audio);
platform_device_unregister(bcm2835_camera);
vchiq_debugfs_deinit();
device_destroy(vchiq_class, vchiq_devid);