blob: 3fdd7a980dd6ce9e8d7e0fe75974e16d2a4e99ed [file] [log] [blame]
/*
* Samsung Exynos SoC series NPU driver
*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "npu-util-statekeeper.h"
#include "npu-log.h"
/*
* Sample state
*
* typedef enum {
* PROTO_DRV_STATE_UNLOADED = 0,
* PROTO_DRV_STATE_PROBED,
* PROTO_DRV_STATE_OPENED,
* PROTO_DRV_STATE_INVALID,
* } proto_drv_state_e;
* const char* PROTO_DRV_STATE_NAME[PROTO_DRV_STATE_INVALID + 1]
* = {"UNLOADED", "PROBED", "OPENED", "INVALID"};
*
* static const u8 proto_drv_thread_state_transition[][PROTO_DRV_STATE_INVALID+1] = {
* From - To UNLOADED PROBED OPENED INVALID
* UNLOADED { 0, 1, 0, 0},
* PROBED { 1, 0, 1, 0},
* OPENED { 1, 1, 0, 0},
* INVALID { 0, 0, 0, 0},
* };
*/
/*
* Make transition to new_state.
* If the transition is not allowed in transition_map, BUG_ON(1) is fired.
* Otherwise, old state is returned.
*/
int npu_statekeeper_transition(struct npu_statekeeper *keeper_ptr, int new_state)
{
int old_state;
BUG_ON(!keeper_ptr);
BUG_ON(new_state < 0);
BUG_ON(new_state >= keeper_ptr->state_num);
old_state = atomic_xchg(&keeper_ptr->state, new_state);
/* Check after transition is made - To ensure atomicity */
if (!keeper_ptr->transition_map[old_state][new_state]) {
npu_err("Invalid transition [%s] -> [%s]\n",
keeper_ptr->state_names[old_state],
keeper_ptr->state_names[new_state]);
BUG_ON(1);
}
return old_state;
}
/*
* Initialize npu_statekeeper object and
* set its state to '0'
*/
void npu_statekeeper_initialize(struct npu_statekeeper *keeper_ptr,
int param_state_num, const char *param_state_names[],
const u8 param_transition_map[][STATE_KEEPER_MAX_STATE])
{
BUG_ON(!keeper_ptr);
BUG_ON(!param_state_names);
BUG_ON(param_state_num <= 1);
BUG_ON(!param_transition_map);
atomic_set(&keeper_ptr->state, 0);
keeper_ptr->state_num = param_state_num;
keeper_ptr->state_names = param_state_names;
keeper_ptr->transition_map = param_transition_map;
}
/* Return constant reference of current state name */
const char *npu_statekeeper_state_name(struct npu_statekeeper *keeper_ptr)
{
int state;
BUG_ON(!keeper_ptr);
state = atomic_read(&keeper_ptr->state);
BUG_ON(state < 0);
BUG_ON(state >= keeper_ptr->state_num);
return keeper_ptr->state_names[atomic_read(&keeper_ptr->state)];
}