blob: 112b25fb815c6e1b015ec160c7538b777abe310a [file] [log] [blame]
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "qdf_status.h"
#include "hif_main.h"
#include "hif_unit_test_suspend.h"
#include "hif_unit_test_suspend_i.h"
enum hif_ut_suspend_state_bits {
UT_SUSPENDED_BIT = 0
};
/**
* hif_ut_fw_resume_work() - Work handler for firmware-triggered resume
* @work: The work struct being passed from the linux kernel
*
* Return: None
*/
static void hif_ut_fw_resume_work(struct work_struct *work)
{
struct hif_ut_suspend_context *ctx =
container_of(work, struct hif_ut_suspend_context, resume_work);
QDF_BUG(ctx);
if (!ctx)
return;
QDF_BUG(ctx->resume_callback);
if (!ctx->resume_callback)
return;
ctx->resume_callback();
ctx->resume_callback = NULL;
}
void hif_ut_suspend_init(struct hif_softc *scn)
{
INIT_WORK(&scn->ut_suspend_ctx.resume_work, hif_ut_fw_resume_work);
}
bool hif_is_ut_suspended(struct hif_softc *scn)
{
QDF_BUG(scn);
if (!scn)
return false;
return test_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state);
}
QDF_STATUS hif_ut_apps_suspend(struct hif_opaque_softc *opaque_scn,
hif_ut_resume_callback callback)
{
struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn);
QDF_BUG(scn);
if (!scn)
return QDF_STATUS_E_INVAL;
QDF_BUG(callback);
if (!callback)
return QDF_STATUS_E_INVAL;
if (test_and_set_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state))
return QDF_STATUS_E_INVAL;
scn->ut_suspend_ctx.resume_callback = callback;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS hif_ut_apps_resume(struct hif_opaque_softc *opaque_scn)
{
struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn);
QDF_BUG(scn);
if (!scn)
return QDF_STATUS_E_INVAL;
if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state))
return QDF_STATUS_E_INVAL;
scn->ut_suspend_ctx.resume_callback = NULL;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn)
{
QDF_BUG(scn);
if (!scn)
return QDF_STATUS_E_INVAL;
if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state))
return QDF_STATUS_E_INVAL;
schedule_work(&scn->ut_suspend_ctx.resume_work);
return QDF_STATUS_SUCCESS;
}
bool hif_irq_trigger_ut_resume(struct hif_softc *scn)
{
if (!hif_is_ut_suspended(scn))
return false;
return true;
}