1b7cb133eSJeenu Viswambharan /* 2*fb1198b1SAntonio Nino Diaz * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 3b7cb133eSJeenu Viswambharan * 4b7cb133eSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 5b7cb133eSJeenu Viswambharan */ 6b7cb133eSJeenu Viswambharan 7b7cb133eSJeenu Viswambharan #include <assert.h> 8b7cb133eSJeenu Viswambharan #include <cassert.h> 9b7cb133eSJeenu Viswambharan #include <stdbool.h> 10b7cb133eSJeenu Viswambharan #include "sdei_private.h" 11b7cb133eSJeenu Viswambharan 12b7cb133eSJeenu Viswambharan /* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */ 13b7cb133eSJeenu Viswambharan #define r_ 0 14b7cb133eSJeenu Viswambharan #define R_ (1u << SDEI_STATF_RUNNING) 15b7cb133eSJeenu Viswambharan 16b7cb133eSJeenu Viswambharan #define e_ 0 17b7cb133eSJeenu Viswambharan #define E_ (1u << SDEI_STATF_ENABLED) 18b7cb133eSJeenu Viswambharan 19b7cb133eSJeenu Viswambharan #define g_ 0 20b7cb133eSJeenu Viswambharan #define G_ (1u << SDEI_STATF_REGISTERED) 21b7cb133eSJeenu Viswambharan 22b7cb133eSJeenu Viswambharan /* All possible composite handler states */ 23b7cb133eSJeenu Viswambharan #define reg_ (r_ | e_ | g_) 24b7cb133eSJeenu Viswambharan #define reG_ (r_ | e_ | G_) 25b7cb133eSJeenu Viswambharan #define rEg_ (r_ | E_ | g_) 26b7cb133eSJeenu Viswambharan #define rEG_ (r_ | E_ | G_) 27b7cb133eSJeenu Viswambharan #define Reg_ (R_ | e_ | g_) 28b7cb133eSJeenu Viswambharan #define ReG_ (R_ | e_ | G_) 29b7cb133eSJeenu Viswambharan #define REg_ (R_ | E_ | g_) 30b7cb133eSJeenu Viswambharan #define REG_ (R_ | E_ | G_) 31b7cb133eSJeenu Viswambharan 32b7cb133eSJeenu Viswambharan #define MAX_STATES (REG_ + 1) 33b7cb133eSJeenu Viswambharan 34b7cb133eSJeenu Viswambharan /* Invalid state */ 35b7cb133eSJeenu Viswambharan #define SDEI_STATE_INVALID ((sdei_state_t) (-1)) 36b7cb133eSJeenu Viswambharan 37b7cb133eSJeenu Viswambharan /* No change in state */ 38b7cb133eSJeenu Viswambharan #define SDEI_STATE_NOP ((sdei_state_t) (-2)) 39b7cb133eSJeenu Viswambharan 40b7cb133eSJeenu Viswambharan #define X___ SDEI_STATE_INVALID 41b7cb133eSJeenu Viswambharan #define NOP_ SDEI_STATE_NOP 42b7cb133eSJeenu Viswambharan 43b7cb133eSJeenu Viswambharan /* Ensure special states don't overlap with valid ones */ 44b7cb133eSJeenu Viswambharan CASSERT(X___ > REG_, sdei_state_overlap_invalid); 45b7cb133eSJeenu Viswambharan CASSERT(NOP_ > REG_, sdei_state_overlap_nop); 46b7cb133eSJeenu Viswambharan 47b7cb133eSJeenu Viswambharan /* 48b7cb133eSJeenu Viswambharan * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0 49*fb1198b1SAntonio Nino Diaz * specification (ARM DEN0054A). 50b7cb133eSJeenu Viswambharan * 51b7cb133eSJeenu Viswambharan * Not all calls contribute to handler state transition. This table is also used 52b7cb133eSJeenu Viswambharan * to validate whether a call is permissible at a given handler state: 53b7cb133eSJeenu Viswambharan * 54b7cb133eSJeenu Viswambharan * - X___ denotes a forbidden transition; 55b7cb133eSJeenu Viswambharan * - NOP_ denotes a permitted transition, but there's no change in state; 56b7cb133eSJeenu Viswambharan * - Otherwise, XXX_ gives the new state. 57b7cb133eSJeenu Viswambharan * 58b7cb133eSJeenu Viswambharan * DISP[atch] is a transition added for the implementation, but is not mentioned 59b7cb133eSJeenu Viswambharan * in the spec. 60b7cb133eSJeenu Viswambharan * 61b7cb133eSJeenu Viswambharan * Those calls that the spec mentions as can be made any time don't picture in 62b7cb133eSJeenu Viswambharan * this table. 63b7cb133eSJeenu Viswambharan */ 64b7cb133eSJeenu Viswambharan 65b7cb133eSJeenu Viswambharan static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = { 66b7cb133eSJeenu Viswambharan /* 67b7cb133eSJeenu Viswambharan * Action: REG REL ENA DISA UREG ROUT CTX COMP COMPR DISP 68b7cb133eSJeenu Viswambharan * Notes: [3] [1] [3] [3][4] [2] 69b7cb133eSJeenu Viswambharan */ 70b7cb133eSJeenu Viswambharan /* Handler unregistered, disabled, and not running. This is the default state. */ 71b7cb133eSJeenu Viswambharan /* 0 */ [reg_] = { reG_, NOP_, X___, X___, X___, X___, X___, X___, X___, X___, }, 72b7cb133eSJeenu Viswambharan 73b7cb133eSJeenu Viswambharan /* Handler unregistered and running */ 74b7cb133eSJeenu Viswambharan /* 4 */ [Reg_] = { X___, X___, X___, X___, X___, X___, NOP_, reg_, reg_, X___, }, 75b7cb133eSJeenu Viswambharan 76b7cb133eSJeenu Viswambharan /* Handler registered */ 77b7cb133eSJeenu Viswambharan /* 1 */ [reG_] = { X___, X___, rEG_, NOP_, reg_, NOP_, X___, X___, X___, X___, }, 78b7cb133eSJeenu Viswambharan 79b7cb133eSJeenu Viswambharan /* Handler registered and running */ 80b7cb133eSJeenu Viswambharan /* 5 */ [ReG_] = { X___, X___, REG_, NOP_, Reg_, X___, NOP_, reG_, reG_, X___, }, 81b7cb133eSJeenu Viswambharan 82b7cb133eSJeenu Viswambharan /* Handler registered and enabled */ 83b7cb133eSJeenu Viswambharan /* 3 */ [rEG_] = { X___, X___, NOP_, reG_, reg_, X___, X___, X___, X___, REG_, }, 84b7cb133eSJeenu Viswambharan 85b7cb133eSJeenu Viswambharan /* Handler registered, enabled, and running */ 86b7cb133eSJeenu Viswambharan /* 7 */ [REG_] = { X___, X___, NOP_, ReG_, Reg_, X___, NOP_, rEG_, rEG_, X___, }, 87b7cb133eSJeenu Viswambharan 88b7cb133eSJeenu Viswambharan /* 89b7cb133eSJeenu Viswambharan * Invalid states: no valid transition would leave the handler in these 90b7cb133eSJeenu Viswambharan * states; and no transition from these states is possible either. 91b7cb133eSJeenu Viswambharan */ 92b7cb133eSJeenu Viswambharan 93b7cb133eSJeenu Viswambharan /* 94b7cb133eSJeenu Viswambharan * Handler can't be enabled without being registered. I.e., XEg is 95b7cb133eSJeenu Viswambharan * impossible. 96b7cb133eSJeenu Viswambharan */ 97b7cb133eSJeenu Viswambharan /* 2 */ [rEg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, 98b7cb133eSJeenu Viswambharan /* 6 */ [REg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, 99b7cb133eSJeenu Viswambharan }; 100b7cb133eSJeenu Viswambharan 101b7cb133eSJeenu Viswambharan /* 102b7cb133eSJeenu Viswambharan * [1] Unregister will always also disable the event, so the new state will have 103b7cb133eSJeenu Viswambharan * Xeg. 104b7cb133eSJeenu Viswambharan * [2] Event is considered for dispatch only when it's both registered and 105b7cb133eSJeenu Viswambharan * enabled. 106b7cb133eSJeenu Viswambharan * [3] Never causes change in state. 107b7cb133eSJeenu Viswambharan * [4] Only allowed when running. 108b7cb133eSJeenu Viswambharan */ 109b7cb133eSJeenu Viswambharan 110b7cb133eSJeenu Viswambharan /* 111b7cb133eSJeenu Viswambharan * Given an action, transition the state of an event by looking up the state 112b7cb133eSJeenu Viswambharan * table above: 113b7cb133eSJeenu Viswambharan * 114b7cb133eSJeenu Viswambharan * - Return false for invalid transition; 115b7cb133eSJeenu Viswambharan * - Return true for valid transition that causes no change in state; 116b7cb133eSJeenu Viswambharan * - Otherwise, update state and return true. 117b7cb133eSJeenu Viswambharan * 118b7cb133eSJeenu Viswambharan * This function assumes that the caller holds necessary locks. If the 119b7cb133eSJeenu Viswambharan * transition has constrains other than the state table describes, the caller is 120b7cb133eSJeenu Viswambharan * expected to restore the previous state. See sdei_event_register() for 121b7cb133eSJeenu Viswambharan * example. 122b7cb133eSJeenu Viswambharan */ 123b7cb133eSJeenu Viswambharan bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act) 124b7cb133eSJeenu Viswambharan { 125b7cb133eSJeenu Viswambharan sdei_state_t next; 126b7cb133eSJeenu Viswambharan 127b7cb133eSJeenu Viswambharan assert(act < DO_MAX); 128b7cb133eSJeenu Viswambharan if (se->state >= MAX_STATES) { 129b7cb133eSJeenu Viswambharan WARN(" event state invalid: %x\n", se->state); 130b7cb133eSJeenu Viswambharan return false; 131b7cb133eSJeenu Viswambharan } 132b7cb133eSJeenu Viswambharan 133b7cb133eSJeenu Viswambharan next = sdei_state_table[se->state][act]; 134b7cb133eSJeenu Viswambharan switch (next) { 135b7cb133eSJeenu Viswambharan case SDEI_STATE_INVALID: 136b7cb133eSJeenu Viswambharan return false; 137b7cb133eSJeenu Viswambharan 138b7cb133eSJeenu Viswambharan case SDEI_STATE_NOP: 139b7cb133eSJeenu Viswambharan return true; 140b7cb133eSJeenu Viswambharan 141b7cb133eSJeenu Viswambharan default: 142b7cb133eSJeenu Viswambharan /* Valid transition. Update state. */ 143b7cb133eSJeenu Viswambharan SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next); 144b7cb133eSJeenu Viswambharan se->state = next; 145b7cb133eSJeenu Viswambharan 146b7cb133eSJeenu Viswambharan return true; 147b7cb133eSJeenu Viswambharan } 148b7cb133eSJeenu Viswambharan } 149