* osal_workqueue.c
*
* osal driver
*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "hdf_workqueue.h"
#include <linux/workqueue.h>
#include "hdf_log.h"
#include "osal_mem.h"
#define HDF_LOG_TAG hdf_workqueue
struct WorkWrapper {
struct delayed_work work;
HdfWorkFunc workFunc;
void *para;
};
int32_t HdfWorkQueueInit(HdfWorkQueue *queue, char *name)
{
HDF_LOGD("%s entry", __func__);
if (queue == NULL || name == NULL) {
HDF_LOGE("%s invalid para", __func__);
return HDF_ERR_INVALID_PARAM;
}
queue->realWorkQueue = create_singlethread_workqueue(name);
if (queue->realWorkQueue == NULL) {
HDF_LOGE("%s create queue fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
EXPORT_SYMBOL(HdfWorkQueueInit);
static void WorkEntry(struct work_struct *work)
{
struct WorkWrapper *wrapper = NULL;
if (work != NULL) {
wrapper = (struct WorkWrapper *)work;
if (wrapper->workFunc != NULL)
wrapper->workFunc(wrapper->para);
else
HDF_LOGE("%s routine null", __func__);
} else {
HDF_LOGE("%s work null", __func__);
}
}
int32_t HdfWorkInit(HdfWork *work, HdfWorkFunc func, void *para)
{
struct work_struct *realWork = NULL;
struct WorkWrapper *wrapper = NULL;
if (work == NULL || func == NULL) {
HDF_LOGE("%s invalid para", __func__);
return HDF_ERR_INVALID_PARAM;
}
work->realWork = NULL;
wrapper = (struct WorkWrapper *)OsalMemCalloc(sizeof(*wrapper));
if (wrapper == NULL) {
HDF_LOGE("%s malloc fail", __func__);
return HDF_ERR_MALLOC_FAIL;
}
realWork = &(wrapper->work.work);
wrapper->workFunc = func;
wrapper->para = para;
INIT_WORK(realWork, WorkEntry);
work->realWork = wrapper;
return HDF_SUCCESS;
}
EXPORT_SYMBOL(HdfWorkInit);
int32_t HdfDelayedWorkInit(HdfWork *work, HdfWorkFunc func, void *para)
{
struct delayed_work *realWork = NULL;
struct WorkWrapper *wrapper = NULL;
if (work == NULL || func == NULL) {
HDF_LOGE("%s invalid para", __func__);
return HDF_ERR_INVALID_PARAM;
}
work->realWork = NULL;
wrapper = (struct WorkWrapper *)OsalMemCalloc(sizeof(*wrapper));
if (wrapper == NULL) {
HDF_LOGE("%s malloc fail", __func__);
return HDF_ERR_MALLOC_FAIL;
}
realWork = &(wrapper->work);
wrapper->workFunc = func;
wrapper->para = para;
INIT_DELAYED_WORK(realWork, WorkEntry);
work->realWork = wrapper;
return HDF_SUCCESS;
}
EXPORT_SYMBOL(HdfDelayedWorkInit);
void HdfWorkDestroy(HdfWork *work)
{
if (work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return;
}
OsalMemFree(work->realWork);
work->realWork = NULL;
return;
}
EXPORT_SYMBOL(HdfWorkDestroy);
void HdfDelayedWorkDestroy(HdfWork *work)
{
if (work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return;
}
return HdfWorkDestroy(work);
}
EXPORT_SYMBOL(HdfDelayedWorkDestroy);
void HdfWorkQueueDestroy(HdfWorkQueue *queue)
{
if (queue == NULL || queue->realWorkQueue == NULL) {
HDF_LOGE("%s invalid para", __func__);
return;
}
destroy_workqueue(queue->realWorkQueue);
return;
}
EXPORT_SYMBOL(HdfWorkQueueDestroy);
bool HdfAddWork(HdfWorkQueue *queue, HdfWork *work)
{
if (queue == NULL || queue->realWorkQueue == NULL || work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return false;
}
return queue_work(queue->realWorkQueue, &((struct WorkWrapper *)work->realWork)->work.work);
}
EXPORT_SYMBOL(HdfAddWork);
bool HdfAddDelayedWork(HdfWorkQueue *queue, HdfWork *work, uint32_t ms)
{
if (queue == NULL || queue->realWorkQueue == NULL || work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return false;
}
return queue_delayed_work(queue->realWorkQueue, &((struct WorkWrapper *)work->realWork)->work,
msecs_to_jiffies((unsigned long)ms));
}
EXPORT_SYMBOL(HdfAddDelayedWork);
unsigned int HdfWorkBusy(HdfWork *work)
{
if (work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return 0;
}
return work_busy(&((struct WorkWrapper *)work->realWork)->work.work);
}
EXPORT_SYMBOL(HdfWorkBusy);
bool HdfCancelWorkSync(HdfWork *work)
{
if (work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return false;
}
return cancel_work_sync(&((struct WorkWrapper *)work->realWork)->work.work);
}
EXPORT_SYMBOL(HdfCancelWorkSync);
bool HdfCancelDelayedWorkSync(HdfWork *work)
{
if (work == NULL || work->realWork == NULL) {
HDF_LOGE("%s invalid para", __func__);
return false;
}
return cancel_delayed_work_sync(&((struct WorkWrapper *)work->realWork)->work);
}
EXPORT_SYMBOL(HdfCancelDelayedWorkSync);