[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / misc / samsung / scsc / mifmboxman.c
1 /****************************************************************************
2 *
3 * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 ****************************************************************************/
6
7 /* uses */
8 #include <linux/kernel.h>
9 #include <linux/printk.h>
10 #include <linux/slab.h>
11 #include <linux/mutex.h>
12 #include <scsc/scsc_logring.h>
13 #include "scsc_mif_abs.h"
14
15 /* Implements */
16 #include "mifmboxman.h"
17
18 int mifmboxman_init(struct mifmboxman *mbox)
19 {
20 if (mbox->in_use)
21 return -EBUSY;
22
23 mutex_init(&mbox->lock);
24 mbox->mbox_free = MIFMBOX_NUM;
25 mbox->in_use = true;
26 bitmap_zero(mbox->bitmap, MIFMBOX_NUM);
27
28 return 0;
29 }
30
31 bool mifmboxman_alloc_mboxes(struct mifmboxman *mbox, int n, int *first_mbox_index)
32 {
33 unsigned int index = 0;
34 unsigned int available;
35 u8 i;
36
37 mutex_lock(&mbox->lock);
38
39 if ((n > MIFMBOX_NUM) || (n == 0) || !mbox->in_use)
40 goto error;
41
42 while (index <= (MIFMBOX_NUM - n)) {
43 available = 0;
44
45 /* Search consecutive blocks */
46 for (i = 0; i < n; i++) {
47 if (test_bit((i + index), mbox->bitmap))
48 break;
49 available++;
50 }
51
52 if (available == n) {
53 *first_mbox_index = index;
54
55 for (i = 0; i < n; i++)
56 set_bit(index++, mbox->bitmap);
57
58 mbox->mbox_free -= n;
59 goto exit;
60 } else
61 index = index + available + 1;
62 }
63 error:
64 SCSC_TAG_ERR(MIF, "Error allocating mbox\n");
65 mutex_unlock(&mbox->lock);
66 return false;
67 exit:
68 mutex_unlock(&mbox->lock);
69 return true;
70
71 }
72
73 void mifmboxman_free_mboxes(struct mifmboxman *mbox, int first_mbox_index, int n)
74 {
75 int index = 0;
76 int total_free = 0;
77
78 mutex_lock(&mbox->lock);
79 if ((n > MIFMBOX_NUM) ||
80 ((n + first_mbox_index) > MIFMBOX_NUM) ||
81 (n == 0) ||
82 !mbox->in_use)
83 goto error;
84
85 for (index = first_mbox_index; index < (first_mbox_index + n); index++)
86 if (test_bit(index, mbox->bitmap)) {
87 clear_bit(index, mbox->bitmap);
88 total_free++;
89 }
90
91 mbox->mbox_free += total_free;
92 mutex_unlock(&mbox->lock);
93 return;
94 error:
95 SCSC_TAG_ERR(MIF, "Error freeing mbox\n");
96 mutex_unlock(&mbox->lock);
97 }
98
99 u32 *mifmboxman_get_mbox_ptr(struct mifmboxman *mbox, struct scsc_mif_abs *mif_abs, int mbox_index)
100 {
101 /* Avoid unused parameter error */
102 (void)mbox;
103
104 return mif_abs->get_mbox_ptr(mif_abs, mbox_index);
105 }
106
107
108 int mifmboxman_deinit(struct mifmboxman *mbox)
109 {
110 mutex_lock(&mbox->lock);
111 if (!mbox->in_use)
112 return -ENODEV;
113 mbox->in_use = false;
114 mutex_unlock(&mbox->lock);
115 return 0;
116 }