1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
3 #include <linux/module.h>
4 #include <linux/types.h>
5 #include <linux/slab.h>
6 #include <linux/delay.h>
9 #include "../vchi/vchi.h"
11 #include "vchiq_core.h"
13 int vchi_queue_kernel_message(struct vchi_service *service, void *data,
16 enum vchiq_status status;
19 status = vchiq_queue_kernel_message(service->handle, data,
23 * vchiq_queue_message() may return VCHIQ_RETRY, so we need to
24 * implement a retry mechanism since this function is supposed
25 * to block until queued
27 if (status != VCHIQ_RETRY)
35 EXPORT_SYMBOL(vchi_queue_kernel_message);
37 /***********************************************************
38 * Name: vchi_bulk_queue_receive
40 * Arguments: VCHI_BULK_HANDLE_T handle,
42 * const uint32_t data_size,
43 * enum vchi_flags flags
46 * Description: Routine to setup a rcv buffer
48 * Returns: int32_t - success == 0
50 ***********************************************************/
51 int32_t vchi_bulk_queue_receive(struct vchi_service *service, void *data_dst,
52 uint32_t data_size, enum vchiq_bulk_mode mode,
55 enum vchiq_status status;
58 status = vchiq_bulk_receive(service->handle, data_dst,
59 data_size, bulk_handle, mode);
61 * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
62 * implement a retry mechanism since this function is supposed
63 * to block until queued
65 if (status != VCHIQ_RETRY)
73 EXPORT_SYMBOL(vchi_bulk_queue_receive);
75 /***********************************************************
76 * Name: vchi_bulk_queue_transmit
78 * Arguments: VCHI_BULK_HANDLE_T handle,
79 * const void *data_src,
81 * enum vchi_flags flags,
84 * Description: Routine to transmit some data
86 * Returns: int32_t - success == 0
88 ***********************************************************/
89 int32_t vchi_bulk_queue_transmit(struct vchi_service *service,
92 enum vchiq_bulk_mode mode,
95 enum vchiq_status status;
98 status = vchiq_bulk_transmit(service->handle, data_src,
99 data_size, bulk_handle, mode);
102 * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
103 * implement a retry mechanism since this function is supposed
104 * to block until queued
106 if (status != VCHIQ_RETRY)
114 EXPORT_SYMBOL(vchi_bulk_queue_transmit);
117 /***********************************************************
118 * Name: vchi_held_msg_release
120 * Arguments: struct vchi_held_msg *message
122 * Description: Routine to release a held message (after it has been read with
125 * Returns: int32_t - success == 0
127 ***********************************************************/
128 int32_t vchi_held_msg_release(struct vchi_held_msg *message)
131 * Convert the service field pointer back to an
132 * unsigned int which is an int.
133 * This pointer is opaque to everything except
134 * vchi_msg_hold which simply upcasted the int
138 vchiq_release_message((unsigned int)(long)message->service,
139 (struct vchiq_header *)message->message);
143 EXPORT_SYMBOL(vchi_held_msg_release);
145 /***********************************************************
146 * Name: vchi_msg_hold
148 * Arguments: struct vchi_service *service,
150 * uint32_t *msg_size,
151 * struct vchi_held_msg *message_handle
153 * Description: Routine to return a pointer to the current message (to allow
154 * in place processing). The message is dequeued - don't forget
155 * to release the message using vchi_held_msg_release when you're
158 * Returns: int32_t - success == 0
160 ***********************************************************/
161 int32_t vchi_msg_hold(unsigned handle, void **data, uint32_t *msg_size,
162 struct vchi_held_msg *message_handle)
164 struct vchiq_header *header;
166 header = vchiq_msg_hold(handle);
170 *data = header->data;
171 *msg_size = header->size;
174 * upcast the unsigned int which is an int
175 * to a pointer and stuff it in the held message.
176 * This pointer is opaque to everything except
177 * vchi_held_msg_release which simply downcasts it back
181 message_handle->service =
182 (struct opaque_vchi_service_t *)(long)handle;
183 message_handle->message = header;
187 EXPORT_SYMBOL(vchi_msg_hold);
189 /***********************************************************
190 * Name: vchi_initialise
192 * Arguments: struct vchiq_instance **instance
194 * Description: Initialises the hardware but does not transmit anything
195 * When run as a Host App this will be called twice hence the need
196 * to malloc the state information
198 * Returns: 0 if successful, failure otherwise
200 ***********************************************************/
202 int32_t vchi_initialise(struct vchiq_instance **instance)
204 return vchiq_initialise(instance);
206 EXPORT_SYMBOL(vchi_initialise);
208 /***********************************************************
211 * Arguments: struct vchiq_instance *instance
213 * Description: Starts the command service on each connection,
214 * causing INIT messages to be pinged back and forth
216 * Returns: 0 if successful, failure otherwise
218 ***********************************************************/
219 int32_t vchi_connect(struct vchiq_instance *instance)
221 return vchiq_connect(instance);
223 EXPORT_SYMBOL(vchi_connect);
225 /***********************************************************
226 * Name: vchi_disconnect
228 * Arguments: struct vchiq_instance *instance
230 * Description: Stops the command service on each connection,
231 * causing DE-INIT messages to be pinged back and forth
233 * Returns: 0 if successful, failure otherwise
235 ***********************************************************/
236 int32_t vchi_disconnect(struct vchiq_instance *instance)
238 return vchiq_shutdown(instance);
240 EXPORT_SYMBOL(vchi_disconnect);
242 /***********************************************************
243 * Name: vchi_service_open
244 * Name: vchi_service_create
246 * Arguments: struct vchiq_instance *instance
247 * struct service_creation *setup,
248 * struct vchi_service **service
250 * Description: Routine to open a service
252 * Returns: int32_t - success == 0
254 ***********************************************************/
256 static struct vchi_service *service_alloc(void)
258 return kzalloc(sizeof(struct vchi_service), GFP_KERNEL);
261 static void service_free(struct vchi_service *service)
267 int32_t vchi_service_open(struct vchiq_instance *instance,
268 struct vchiq_service_params *params,
269 struct vchi_service **service)
272 *service = service_alloc();
274 enum vchiq_status status;
276 status = vchiq_open_service(instance, params,
277 &((*service)->handle));
278 if (status != VCHIQ_SUCCESS) {
279 service_free(*service);
284 return *service ? 0 : -1;
286 EXPORT_SYMBOL(vchi_service_open);
288 int32_t vchi_service_close(struct vchi_service *service)
293 enum vchiq_status status = vchiq_close_service(service->handle);
294 if (status == VCHIQ_SUCCESS)
295 service_free(service);
301 EXPORT_SYMBOL(vchi_service_close);
303 int32_t vchi_get_peer_version(struct vchi_service *service, short *peer_version)
308 enum vchiq_status status;
310 status = vchiq_get_peer_version(service->handle, peer_version);
315 EXPORT_SYMBOL(vchi_get_peer_version);
317 /***********************************************************
318 * Name: vchi_service_use
320 * Arguments: struct vchi_service *service
322 * Description: Routine to increment refcount on a service
326 ***********************************************************/
327 int32_t vchi_service_use(struct vchi_service *service)
332 ret = vchiq_use_service(service->handle);
335 EXPORT_SYMBOL(vchi_service_use);
337 /***********************************************************
338 * Name: vchi_service_release
340 * Arguments: struct vchi_service *service
342 * Description: Routine to decrement refcount on a service
346 ***********************************************************/
347 int32_t vchi_service_release(struct vchi_service *service)
352 ret = vchiq_release_service(service->handle);
355 EXPORT_SYMBOL(vchi_service_release);