1 /*
2 * Copyright (c) 2014, Mentor Graphics Corporation
3 * All rights reserved.
4 * Copyright (c) 2015 Xilinx, Inc. All rights reserved.
5 * Copyright (c) 2016 NXP, Inc. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
32 /**************************************************************************
33 * FILE NAME
34 *
35 * rpmsg_core.c
36 *
37 * COMPONENT
38 *
39 * OpenAMP
40 *
41 * DESCRIPTION
42 *
43 * This file provides the core functionality of RPMSG messaging part like
44 * message parsing ,Rx/Tx callbacks handling , channel creation/deletion
45 * and address management.
46 *
47 *
48 **************************************************************************/
49 #include "openamp/rpmsg.h"
51 /* Internal functions */
52 static void rpmsg_rx_callback(struct virtqueue *vq);
53 static void rpmsg_tx_callback(struct virtqueue *vq);
55 /**
56 * rpmsg_start_ipc
57 *
58 * This function creates communication links(virtqueues) for remote device
59 * and notifies it to start IPC.
60 *
61 * @param rdev - remote device handle
62 *
63 * @return - status of function execution
64 *
65 */
66 int rpmsg_start_ipc(struct remote_device *rdev)
67 {
68 struct virtio_device *virt_dev;
69 struct rpmsg_endpoint *ns_ept;
70 void (*callback[2]) (struct virtqueue * vq);
71 const char *vq_names[2];
72 unsigned long dev_features;
73 int status;
74 struct virtqueue *vqs[2];
75 int i;
77 virt_dev = &rdev->virt_dev;
79 /* Initialize names and callbacks based on the device role */
80 if (rdev->role == RPMSG_MASTER) {
81 vq_names[0] = "tx_vq";
82 vq_names[1] = "rx_vq";
83 callback[0] = rpmsg_tx_callback;
84 callback[1] = rpmsg_rx_callback;
85 } else {
86 vq_names[0] = "rx_vq";
87 vq_names[1] = "tx_vq";
88 callback[0] = rpmsg_rx_callback;
89 callback[1] = rpmsg_tx_callback;
90 }
92 /* Create virtqueues for remote device */
93 status = virt_dev->func->create_virtqueues(virt_dev, 0,
94 RPMSG_MAX_VQ_PER_RDEV,
95 vq_names, callback,
96 RPMSG_NULL);
97 if (status != RPMSG_SUCCESS) {
98 return status;
99 }
101 dev_features = virt_dev->func->get_features(virt_dev);
103 /*
104 * Create name service announcement endpoint if device supports name
105 * service announcement feature.
106 */
107 if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) {
108 rdev->support_ns = RPMSG_TRUE;
109 ns_ept = _create_endpoint(rdev, rpmsg_ns_callback, rdev,
110 RPMSG_NS_EPT_ADDR);
111 if (!ns_ept) {
112 return RPMSG_ERR_NO_MEM;
113 }
114 }
116 /* Initialize notifications for vring. */
117 if (rdev->role == RPMSG_MASTER) {
118 vqs[0] = rdev->tvq;
119 vqs[1] = rdev->rvq;
120 } else {
121 vqs[0] = rdev->rvq;
122 vqs[1] = rdev->tvq;
123 }
124 for (i = 0; i <= 1; i++) {
125 status = hil_enable_vring_notifications(i, vqs[i]);
126 if (status != RPMSG_SUCCESS) {
127 return status;
128 }
129 }
131 status = rpmsg_rdev_notify(rdev);
133 return status;
134 }
136 /**
137 * _rpmsg_create_channel
138 *
139 * Creates new rpmsg channel with the given parameters.
140 *
141 * @param rdev - pointer to remote device which contains the channel
142 * @param name - name of the device
143 * @param src - source address for the rpmsg channel
144 * @param dst - destination address for the rpmsg channel
145 *
146 * @return - pointer to new rpmsg channel
147 *
148 */
149 struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev,
150 char *name, unsigned long src,
151 unsigned long dst)
152 {
153 struct rpmsg_channel *rp_chnl;
154 struct llist *node;
156 rp_chnl = env_allocate_memory(sizeof(struct rpmsg_channel));
157 if (rp_chnl) {
158 env_memset(rp_chnl, 0x00, sizeof(struct rpmsg_channel));
159 env_strncpy(rp_chnl->name, name, sizeof(rp_chnl->name));
160 rp_chnl->src = src;
161 rp_chnl->dst = dst;
162 rp_chnl->rdev = rdev;
163 /* Place channel on channels list */
164 node = env_allocate_memory(sizeof(struct llist));
165 if (!node) {
166 env_free_memory(rp_chnl);
167 return RPMSG_NULL;
168 }
169 node->data = rp_chnl;
170 env_lock_mutex(rdev->lock);
171 add_to_list(&rdev->rp_channels, node);
172 env_unlock_mutex(rdev->lock);
173 }
175 return rp_chnl;
176 }
178 /**
179 * _rpmsg_delete_channel
180 *
181 * Deletes given rpmsg channel.
182 *
183 * @param rp_chnl - pointer to rpmsg channel to delete
184 *
185 * return - none
186 */
187 void _rpmsg_delete_channel(struct rpmsg_channel *rp_chnl)
188 {
189 struct llist *node;
190 if (rp_chnl) {
191 node =
192 rpmsg_rdev_get_chnl_node_from_id(rp_chnl->rdev,
193 rp_chnl->name);
194 if (node) {
195 env_lock_mutex(rp_chnl->rdev->lock);
196 remove_from_list(&rp_chnl->rdev->rp_channels, node);
197 env_unlock_mutex(rp_chnl->rdev->lock);
198 env_free_memory(node);
199 }
200 env_free_memory(rp_chnl);
201 }
202 }
204 /**
205 * _create_endpoint
206 *
207 * This function creates rpmsg endpoint.
208 *
209 * @param rdev - pointer to remote device
210 * @param cb - Rx completion call back
211 * @param priv - private data
212 * @param addr - endpoint src address
213 *
214 * @return - pointer to endpoint control block
215 *
216 */
217 struct rpmsg_endpoint *_create_endpoint(struct remote_device *rdev,
218 rpmsg_rx_cb_t cb, void *priv,
219 unsigned long addr)
220 {
222 struct rpmsg_endpoint *rp_ept;
223 struct llist *node;
224 int status = RPMSG_SUCCESS;
226 rp_ept = env_allocate_memory(sizeof(struct rpmsg_endpoint));
227 if (!rp_ept) {
228 return RPMSG_NULL;
229 }
230 env_memset(rp_ept, 0x00, sizeof(struct rpmsg_endpoint));
232 node = env_allocate_memory(sizeof(struct llist));
233 if (!node) {
234 env_free_memory(rp_ept);
235 return RPMSG_NULL;
236 }
238 env_lock_mutex(rdev->lock);
240 if (addr != RPMSG_ADDR_ANY) {
241 /*
242 * Application has requested a particular src address for endpoint,
243 * first check if address is available.
244 */
245 if (!rpmsg_is_address_set
246 (rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr)) {
247 /* Mark the address as used in the address bitmap. */
248 rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
249 addr);
251 } else {
252 status = RPMSG_ERR_DEV_ADDR;
253 }
254 } else {
255 addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);
256 if ((int)addr < 0) {
257 status = RPMSG_ERR_DEV_ADDR;
258 }
259 }
261 /* Do cleanup in case of error and return */
262 if (RPMSG_SUCCESS != status) {
263 env_free_memory(node);
264 env_free_memory(rp_ept);
265 env_unlock_mutex(rdev->lock);
266 return RPMSG_NULL;
267 }
269 rp_ept->addr = addr;
270 rp_ept->cb = cb;
271 rp_ept->priv = priv;
273 node->data = rp_ept;
274 add_to_list(&rdev->rp_endpoints, node);
276 env_unlock_mutex(rdev->lock);
278 return rp_ept;
279 }
281 /**
282 * rpmsg_destroy_ept
283 *
284 * This function deletes rpmsg endpoint and performs cleanup.
285 *
286 * @param rdev - pointer to remote device
287 * @param rp_ept - pointer to endpoint to destroy
288 *
289 */
290 void _destroy_endpoint(struct remote_device *rdev,
291 struct rpmsg_endpoint *rp_ept)
292 {
293 struct llist *node;
294 node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_ept->addr);
295 if (node) {
296 env_lock_mutex(rdev->lock);
297 rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
298 rp_ept->addr);
299 remove_from_list(&rdev->rp_endpoints, node);
300 env_unlock_mutex(rdev->lock);
301 env_free_memory(node);
302 }
303 env_free_memory(rp_ept);
304 }
306 /**
307 * rpmsg_send_ns_message
308 *
309 * Sends name service announcement to remote device
310 *
311 * @param rdev - pointer to remote device
312 * @param rp_chnl - pointer to rpmsg channel
313 * @param flags - Channel creation/deletion flags
314 *
315 */
316 void rpmsg_send_ns_message(struct remote_device *rdev,
317 struct rpmsg_channel *rp_chnl, unsigned long flags)
318 {
320 struct rpmsg_hdr *rp_hdr;
321 struct rpmsg_ns_msg *ns_msg;
322 unsigned short idx;
323 unsigned long len;
325 env_lock_mutex(rdev->lock);
327 /* Get Tx buffer. */
328 rp_hdr = (struct rpmsg_hdr *)rpmsg_get_tx_buffer(rdev, &len, &idx);
329 if (!rp_hdr) {
330 env_unlock_mutex(rdev->lock);
331 return;
332 }
334 /* Fill out name service data. */
335 rp_hdr->dst = RPMSG_NS_EPT_ADDR;
336 rp_hdr->len = sizeof(struct rpmsg_ns_msg);
337 ns_msg = (struct rpmsg_ns_msg *) RPMSG_LOCATE_DATA(rp_hdr);
338 env_strncpy(ns_msg->name, rp_chnl->name, sizeof(rp_chnl->name));
339 ns_msg->flags = flags;
340 ns_msg->addr = rp_chnl->src;
342 /* Place the buffer on virtqueue. */
343 rpmsg_enqueue_buffer(rdev, rp_hdr, len, idx);
345 /* Notify the other side that it has data to process. */
346 virtqueue_kick(rdev->tvq);
348 env_unlock_mutex(rdev->lock);
349 }
351 /**
352 * rpmsg_enqueue_buffers
353 *
354 * Places buffer on the virtqueue for consumption by the other side.
355 *
356 * @param rdev - pointer to remote core
357 * @param buffer - buffer pointer
358 * @param len - buffer length
359 * @idx - buffer index
360 *
361 * @return - status of function execution
362 *
363 */
364 int rpmsg_enqueue_buffer(struct remote_device *rdev, void *buffer,
365 unsigned long len, unsigned short idx)
366 {
367 struct llist node;
368 int status;
370 /* Initialize buffer node */
371 node.data = buffer;
372 node.attr = len;
373 node.next = RPMSG_NULL;
374 node.prev = RPMSG_NULL;
376 if (rdev->role == RPMSG_REMOTE) {
377 status = virtqueue_add_buffer(rdev->tvq, &node, 0, 1, buffer);
378 } else {
379 status = virtqueue_add_consumed_buffer(rdev->tvq, idx, len);
380 }
382 return status;
383 }
385 /**
386 * rpmsg_return_buffer
387 *
388 * Places the used buffer back on the virtqueue.
389 *
390 * @param rdev - pointer to remote core
391 * @param buffer - buffer pointer
392 * @param len - buffer length
393 * @param idx - buffer index
394 *
395 */
396 void rpmsg_return_buffer(struct remote_device *rdev, void *buffer,
397 unsigned long len, unsigned short idx)
398 {
399 struct llist node;
401 /* Initialize buffer node */
402 node.data = buffer;
403 node.attr = len;
404 node.next = RPMSG_NULL;
405 node.prev = RPMSG_NULL;
407 if (rdev->role == RPMSG_REMOTE) {
408 virtqueue_add_buffer(rdev->rvq, &node, 0, 1, buffer);
409 } else {
410 virtqueue_add_consumed_buffer(rdev->rvq, idx, len);
411 }
412 }
414 /**
415 * rpmsg_get_tx_buffer
416 *
417 * Provides buffer to transmit messages.
418 *
419 * @param rdev - pointer to remote device
420 * @param len - length of returned buffer
421 * @param idx - buffer index
422 *
423 * return - pointer to buffer.
424 */
425 void *rpmsg_get_tx_buffer(struct remote_device *rdev, unsigned long *len,
426 unsigned short *idx)
427 {
428 void *data;
430 if (rdev->role == RPMSG_REMOTE) {
431 data = virtqueue_get_buffer(rdev->tvq, (uint32_t *) len);
432 if (data == RPMSG_NULL) {
433 data = sh_mem_get_buffer(rdev->mem_pool);
434 *len = RPMSG_BUFFER_SIZE;
435 }
436 } else {
437 data =
438 virtqueue_get_available_buffer(rdev->tvq, idx,
439 (uint32_t *) len);
440 }
441 return ((void *)env_map_vatopa(data));
442 }
444 /**
445 * rpmsg_get_rx_buffer
446 *
447 * Retrieves the received buffer from the virtqueue.
448 *
449 * @param rdev - pointer to remote device
450 * @param len - size of received buffer
451 * @param idx - index of buffer
452 *
453 * @return - pointer to received buffer
454 *
455 */
456 void *rpmsg_get_rx_buffer(struct remote_device *rdev, unsigned long *len,
457 unsigned short *idx)
458 {
460 void *data;
461 if (rdev->role == RPMSG_REMOTE) {
462 data = virtqueue_get_buffer(rdev->rvq, (uint32_t *) len);
463 } else {
464 data =
465 virtqueue_get_available_buffer(rdev->rvq, idx,
466 (uint32_t *) len);
467 }
468 return ((void *)env_map_vatopa(data));
469 }
471 /**
472 * rpmsg_free_buffer
473 *
474 * Frees the allocated buffers.
475 *
476 * @param rdev - pointer to remote device
477 * @param buffer - pointer to buffer to free
478 *
479 */
480 void rpmsg_free_buffer(struct remote_device *rdev, void *buffer)
481 {
482 if (rdev->role == RPMSG_REMOTE) {
483 sh_mem_free_buffer(buffer, rdev->mem_pool);
484 }
485 }
487 /**
488 * rpmsg_tx_callback
489 *
490 * Tx callback function.
491 *
492 * @param vq - pointer to virtqueue on which Tx is has been
493 * completed.
494 *
495 */
496 static void rpmsg_tx_callback(struct virtqueue *vq)
497 {
498 struct remote_device *rdev;
499 struct virtio_device *vdev;
500 struct rpmsg_channel *rp_chnl;
501 struct llist *chnl_hd;
503 vdev = (struct virtio_device *)vq->vq_dev;
504 rdev = (struct remote_device *)vdev;
505 chnl_hd = rdev->rp_channels;
507 /* Check if the remote device is master. */
508 if (rdev->role == RPMSG_MASTER) {
510 /* Notification is received from the master. Now the remote(us) can
511 * performs one of two operations;
512 *
513 * a. If name service announcement is supported then it will send NS message.
514 * else
515 * b. It will update the channel state to active so that further communication
516 * can take place.
517 */
518 while (chnl_hd != RPMSG_NULL) {
519 rp_chnl = (struct rpmsg_channel *)chnl_hd->data;
521 if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
523 if (rdev->support_ns) {
524 rp_chnl->state = RPMSG_CHNL_STATE_NS;
525 } else {
526 rp_chnl->state =
527 RPMSG_CHNL_STATE_ACTIVE;
528 }
530 if (rp_chnl->state == RPMSG_CHNL_STATE_NS) {
531 rpmsg_send_ns_message(rdev, rp_chnl,
532 RPMSG_NS_CREATE);
533 }
534 }
536 chnl_hd = chnl_hd->next;
537 }
538 }
539 }
541 /**
542 * rpmsg_rx_callback
543 *
544 * Rx callback function.
545 *
546 * @param vq - pointer to virtqueue on which messages is received
547 *
548 */
549 void rpmsg_rx_callback(struct virtqueue *vq)
550 {
551 struct remote_device *rdev;
552 struct virtio_device *vdev;
553 struct rpmsg_channel *rp_chnl;
554 struct rpmsg_endpoint *rp_ept;
555 struct rpmsg_hdr *rp_hdr;
556 struct llist *node;
557 unsigned long len;
558 unsigned short idx;
559 struct llist *chnl_hd;
561 vdev = (struct virtio_device *)vq->vq_dev;
562 rdev = (struct remote_device *)vdev;
564 chnl_hd = rdev->rp_channels;
565 if ((chnl_hd != RPMSG_NULL) && (rdev->role == RPMSG_MASTER)) {
566 rp_chnl = (struct rpmsg_channel *)chnl_hd->data;
567 if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
568 if (rdev->support_ns) {
569 rp_chnl->state = RPMSG_CHNL_STATE_NS;
570 rpmsg_send_ns_message(rdev, rp_chnl,
571 RPMSG_NS_CREATE);
572 } else {
573 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
574 }
575 return;
576 }
577 }
579 env_lock_mutex(rdev->lock);
581 /* Process the received data from remote node */
582 rp_hdr = (struct rpmsg_hdr *)rpmsg_get_rx_buffer(rdev, &len, &idx);
584 env_unlock_mutex(rdev->lock);
586 while (rp_hdr) {
588 /* Get the channel node from the remote device channels list. */
589 node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_hdr->dst);
591 if (!node)
592 /* Fatal error no endpoint for the given dst addr. */
593 return;
595 rp_ept = (struct rpmsg_endpoint *)node->data;
597 rp_chnl = rp_ept->rp_chnl;
599 if ((rp_chnl) && (rp_chnl->state == RPMSG_CHNL_STATE_NS)) {
600 /* First message from RPMSG Master, update channel
601 * destination address and state */
602 rp_chnl->dst = rp_hdr->src;
603 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
605 /* Notify channel creation to application */
606 if (rdev->channel_created) {
607 rdev->channel_created(rp_chnl);
608 }
609 } else {
610 rp_ept->cb(rp_chnl, (void *)RPMSG_LOCATE_DATA(rp_hdr), rp_hdr->len,
611 rp_ept->priv, rp_hdr->src);
612 }
614 env_lock_mutex(rdev->lock);
616 /* Return used buffers. */
617 rpmsg_return_buffer(rdev, rp_hdr, len, idx);
619 rp_hdr =
620 (struct rpmsg_hdr *)rpmsg_get_rx_buffer(rdev, &len, &idx);
621 env_unlock_mutex(rdev->lock);
622 }
623 }
625 /**
626 * rpmsg_ns_callback
627 *
628 * This callback handles name service announcement from the remote device
629 * and creates/deletes rpmsg channels.
630 *
631 * @param server_chnl - pointer to server channel control block.
632 * @param data - pointer to received messages
633 * @param len - length of received data
634 * @param priv - any private data
635 * @param src - source address
636 *
637 * @return - none
638 */
639 void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len,
640 void *priv, unsigned long src)
641 {
642 struct remote_device *rdev;
643 struct rpmsg_channel *rp_chnl;
644 struct rpmsg_ns_msg *ns_msg;
645 struct llist *node;
647 (void)server_chnl;
648 (void)src;
650 rdev = (struct remote_device *)priv;
652 //FIXME: This assumes same name string size for channel name both on master
653 //and remote. If this is not the case then we will have to parse the
654 //message contents.
656 ns_msg = (struct rpmsg_ns_msg *)data;
657 ns_msg->name[len - 1] = '\0';
659 if (ns_msg->flags & RPMSG_NS_DESTROY) {
660 node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name);
661 if (node) {
662 rp_chnl = (struct rpmsg_channel *)node->data;
663 if (rdev->channel_destroyed) {
664 rdev->channel_destroyed(rp_chnl);
665 }
666 rpmsg_destroy_ept(rp_chnl->rp_ept);
667 _rpmsg_delete_channel(rp_chnl);
668 }
669 } else {
670 rp_chnl =
671 _rpmsg_create_channel(rdev, ns_msg->name, 0x00,
672 ns_msg->addr);
673 if (rp_chnl) {
674 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
675 /* Create default endpoint for channel */
676 rp_chnl->rp_ept =
677 rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
678 RPMSG_ADDR_ANY);
679 if (rp_chnl->rp_ept) {
680 rp_chnl->src = rp_chnl->rp_ept->addr;
681 /*
682 * Echo back the NS message to remote in order to
683 * complete the connection stage. Remote will know the endpoint
684 * address from this point onward which will enable it to send
685 * message without waiting for any application level message from
686 * master.
687 */
688 rpmsg_send(rp_chnl, data, len);
689 if (rdev->channel_created) {
690 rdev->channel_created(rp_chnl);
691 }
692 }
693 }
694 }
695 }
697 /**
698 * rpmsg_get_address
699 *
700 * This function provides unique 32 bit address.
701 *
702 * @param bitmap - bit map for addresses
703 * @param size - size of bitmap
704 *
705 * return - a unique address
706 */
707 int rpmsg_get_address(unsigned long *bitmap, int size)
708 {
709 int addr = -1;
710 int i, tmp32;
712 /* Find first available buffer */
713 for (i = 0; i < size; i++) {
714 tmp32 = get_first_zero_bit(bitmap[i]);
716 if (tmp32 < 32) {
717 addr = tmp32 + (i*32);
718 bitmap[i] |= (1 << tmp32);
719 break;
720 }
721 }
723 return addr;
724 }
726 /**
727 * rpmsg_release_address
728 *
729 * Frees the given address.
730 *
731 * @param bitmap - bit map for addresses
732 * @param size - size of bitmap
733 * @param addr - address to free
734 *
735 * return - none
736 */
737 int rpmsg_release_address(unsigned long *bitmap, int size, int addr)
738 {
739 unsigned int i, j;
740 unsigned long mask = 1;
742 if (addr >= size * 32)
743 return -1;
745 /* Mark the addr as available */
746 i = addr / 32;
747 j = addr % 32;
749 mask = mask << j;
750 bitmap[i] = bitmap[i] & (~mask);
752 return RPMSG_SUCCESS;
753 }
755 /**
756 * rpmsg_is_address_set
757 *
758 * Checks whether address is used or free.
759 *
760 * @param bitmap - bit map for addresses
761 * @param size - size of bitmap
762 * @param addr - address to free
763 *
764 * return - TRUE/FALSE
765 */
766 int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr)
767 {
768 int i, j;
769 unsigned long mask = 1;
771 if (addr >= size * 32)
772 return -1;
774 /* Mark the id as available */
775 i = addr / 32;
776 j = addr % 32;
777 mask = mask << j;
779 return (bitmap[i] & mask);
780 }
782 /**
783 * rpmsg_set_address
784 *
785 * Marks the address as consumed.
786 *
787 * @param bitmap - bit map for addresses
788 * @param size - size of bitmap
789 * @param addr - address to free
790 *
791 * return - none
792 */
793 int rpmsg_set_address(unsigned long *bitmap, int size, int addr)
794 {
795 int i, j;
796 unsigned long mask = 1;
798 if (addr >= size * 32)
799 return -1;
801 /* Mark the id as available */
802 i = addr / 32;
803 j = addr % 32;
804 mask = mask << j;
805 bitmap[i] |= mask;
807 return RPMSG_SUCCESS;
808 }