119 lines
2.4 KiB
C
Executable File
119 lines
2.4 KiB
C
Executable File
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved
|
|
*
|
|
****************************************************************************/
|
|
|
|
/* uses */
|
|
#include <linux/kernel.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/mutex.h>
|
|
#include <scsc/scsc_logring.h>
|
|
#include "scsc_mif_abs.h"
|
|
|
|
/* Implements */
|
|
#include "mifmboxman.h"
|
|
|
|
int mifmboxman_init(struct mifmboxman *mbox)
|
|
{
|
|
if (mbox->in_use)
|
|
return -EBUSY;
|
|
|
|
mutex_init(&mbox->lock);
|
|
mbox->mbox_free = MIFMBOX_NUM;
|
|
mbox->in_use = true;
|
|
bitmap_zero(mbox->bitmap, MIFMBOX_NUM);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool mifmboxman_alloc_mboxes(struct mifmboxman *mbox, int n, int *first_mbox_index)
|
|
{
|
|
unsigned int index = 0;
|
|
unsigned int available;
|
|
u8 i;
|
|
|
|
mutex_lock(&mbox->lock);
|
|
|
|
if ((n > MIFMBOX_NUM) || (n == 0) || !mbox->in_use)
|
|
goto error;
|
|
|
|
while (index <= (MIFMBOX_NUM - n)) {
|
|
available = 0;
|
|
|
|
/* Search consecutive blocks */
|
|
for (i = 0; i < n; i++) {
|
|
if (test_bit((i + index), mbox->bitmap))
|
|
break;
|
|
available++;
|
|
}
|
|
|
|
if (available == n) {
|
|
*first_mbox_index = index;
|
|
|
|
for (i = 0; i < n; i++)
|
|
set_bit(index++, mbox->bitmap);
|
|
|
|
mbox->mbox_free -= n;
|
|
goto exit;
|
|
} else
|
|
index = index + available + 1;
|
|
}
|
|
error:
|
|
SCSC_TAG_ERR(MIF, "Error allocating mbox\n");
|
|
mutex_unlock(&mbox->lock);
|
|
return false;
|
|
exit:
|
|
mutex_unlock(&mbox->lock);
|
|
return true;
|
|
|
|
}
|
|
|
|
void mifmboxman_free_mboxes(struct mifmboxman *mbox, int first_mbox_index, int n)
|
|
{
|
|
int index = 0;
|
|
int total_free = 0;
|
|
|
|
mutex_lock(&mbox->lock);
|
|
if ((n > MIFMBOX_NUM) ||
|
|
((n + first_mbox_index) > MIFMBOX_NUM) ||
|
|
(n == 0) ||
|
|
!mbox->in_use)
|
|
goto error;
|
|
|
|
for (index = first_mbox_index; index < (first_mbox_index + n); index++)
|
|
if (test_bit(index, mbox->bitmap)) {
|
|
clear_bit(index, mbox->bitmap);
|
|
total_free++;
|
|
}
|
|
|
|
mbox->mbox_free += total_free;
|
|
mutex_unlock(&mbox->lock);
|
|
return;
|
|
error:
|
|
SCSC_TAG_ERR(MIF, "Error freeing mbox\n");
|
|
mutex_unlock(&mbox->lock);
|
|
}
|
|
|
|
u32 *mifmboxman_get_mbox_ptr(struct mifmboxman *mbox, struct scsc_mif_abs *mif_abs, int mbox_index)
|
|
{
|
|
/* Avoid unused parameter error */
|
|
(void)mbox;
|
|
|
|
return mif_abs->get_mbox_ptr(mif_abs, mbox_index);
|
|
}
|
|
|
|
|
|
int mifmboxman_deinit(struct mifmboxman *mbox)
|
|
{
|
|
mutex_lock(&mbox->lock);
|
|
if (!mbox->in_use) {
|
|
mutex_unlock(&mbox->lock);
|
|
return -ENODEV;
|
|
}
|
|
mbox->in_use = false;
|
|
mutex_unlock(&mbox->lock);
|
|
return 0;
|
|
}
|