cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sm.c (3943B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2022 Linaro Ltd.
      4 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
      5 */
      6
      7#include <linux/errno.h>
      8#include <linux/mhi_ep.h>
      9#include "internal.h"
     10
     11bool __must_check mhi_ep_check_mhi_state(struct mhi_ep_cntrl *mhi_cntrl,
     12					 enum mhi_state cur_mhi_state,
     13					 enum mhi_state mhi_state)
     14{
     15	if (mhi_state == MHI_STATE_SYS_ERR)
     16		return true;    /* Allowed in any state */
     17
     18	if (mhi_state == MHI_STATE_READY)
     19		return cur_mhi_state == MHI_STATE_RESET;
     20
     21	if (mhi_state == MHI_STATE_M0)
     22		return cur_mhi_state == MHI_STATE_M3 || cur_mhi_state == MHI_STATE_READY;
     23
     24	if (mhi_state == MHI_STATE_M3)
     25		return cur_mhi_state == MHI_STATE_M0;
     26
     27	return false;
     28}
     29
     30int mhi_ep_set_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state mhi_state)
     31{
     32	struct device *dev = &mhi_cntrl->mhi_dev->dev;
     33
     34	if (!mhi_ep_check_mhi_state(mhi_cntrl, mhi_cntrl->mhi_state, mhi_state)) {
     35		dev_err(dev, "MHI state change to %s from %s is not allowed!\n",
     36			mhi_state_str(mhi_state),
     37			mhi_state_str(mhi_cntrl->mhi_state));
     38		return -EACCES;
     39	}
     40
     41	/* TODO: Add support for M1 and M2 states */
     42	if (mhi_state == MHI_STATE_M1 || mhi_state == MHI_STATE_M2) {
     43		dev_err(dev, "MHI state (%s) not supported\n", mhi_state_str(mhi_state));
     44		return -EOPNOTSUPP;
     45	}
     46
     47	mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_MHISTATE_MASK, mhi_state);
     48	mhi_cntrl->mhi_state = mhi_state;
     49
     50	if (mhi_state == MHI_STATE_READY)
     51		mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_READY_MASK, 1);
     52
     53	if (mhi_state == MHI_STATE_SYS_ERR)
     54		mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_SYSERR_MASK, 1);
     55
     56	return 0;
     57}
     58
     59int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl)
     60{
     61	struct device *dev = &mhi_cntrl->mhi_dev->dev;
     62	enum mhi_state old_state;
     63	int ret;
     64
     65	/* If MHI is in M3, resume suspended channels */
     66	spin_lock_bh(&mhi_cntrl->state_lock);
     67	old_state = mhi_cntrl->mhi_state;
     68	if (old_state == MHI_STATE_M3)
     69		mhi_ep_resume_channels(mhi_cntrl);
     70
     71	ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M0);
     72	spin_unlock_bh(&mhi_cntrl->state_lock);
     73
     74	if (ret) {
     75		mhi_ep_handle_syserr(mhi_cntrl);
     76		return ret;
     77	}
     78
     79	/* Signal host that the device moved to M0 */
     80	ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M0);
     81	if (ret) {
     82		dev_err(dev, "Failed sending M0 state change event\n");
     83		return ret;
     84	}
     85
     86	if (old_state == MHI_STATE_READY) {
     87		/* Send AMSS EE event to host */
     88		ret = mhi_ep_send_ee_event(mhi_cntrl, MHI_EE_AMSS);
     89		if (ret) {
     90			dev_err(dev, "Failed sending AMSS EE event\n");
     91			return ret;
     92		}
     93	}
     94
     95	return 0;
     96}
     97
     98int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl)
     99{
    100	struct device *dev = &mhi_cntrl->mhi_dev->dev;
    101	int ret;
    102
    103	spin_lock_bh(&mhi_cntrl->state_lock);
    104	ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M3);
    105	spin_unlock_bh(&mhi_cntrl->state_lock);
    106
    107	if (ret) {
    108		mhi_ep_handle_syserr(mhi_cntrl);
    109		return ret;
    110	}
    111
    112	mhi_ep_suspend_channels(mhi_cntrl);
    113
    114	/* Signal host that the device moved to M3 */
    115	ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M3);
    116	if (ret) {
    117		dev_err(dev, "Failed sending M3 state change event\n");
    118		return ret;
    119	}
    120
    121	return 0;
    122}
    123
    124int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl)
    125{
    126	struct device *dev = &mhi_cntrl->mhi_dev->dev;
    127	enum mhi_state mhi_state;
    128	int ret, is_ready;
    129
    130	spin_lock_bh(&mhi_cntrl->state_lock);
    131	/* Ensure that the MHISTATUS is set to RESET by host */
    132	mhi_state = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_MHISTATE_MASK);
    133	is_ready = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_READY_MASK);
    134
    135	if (mhi_state != MHI_STATE_RESET || is_ready) {
    136		dev_err(dev, "READY state transition failed. MHI host not in RESET state\n");
    137		spin_unlock_bh(&mhi_cntrl->state_lock);
    138		return -EIO;
    139	}
    140
    141	ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_READY);
    142	spin_unlock_bh(&mhi_cntrl->state_lock);
    143
    144	if (ret)
    145		mhi_ep_handle_syserr(mhi_cntrl);
    146
    147	return ret;
    148}