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

sched.c (3266B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2011-2017, The Linux Foundation
      4 */
      5
      6#include <linux/errno.h>
      7#include "slimbus.h"
      8
      9/**
     10 * slim_ctrl_clk_pause() - Called by slimbus controller to enter/exit
     11 *			   'clock pause'
     12 * @ctrl: controller requesting bus to be paused or woken up
     13 * @wakeup: Wakeup this controller from clock pause.
     14 * @restart: Restart time value per spec used for clock pause. This value
     15 *	isn't used when controller is to be woken up.
     16 *
     17 * Slimbus specification needs this sequence to turn-off clocks for the bus.
     18 * The sequence involves sending 3 broadcast messages (reconfiguration
     19 * sequence) to inform all devices on the bus.
     20 * To exit clock-pause, controller typically wakes up active framer device.
     21 * This API executes clock pause reconfiguration sequence if wakeup is false.
     22 * If wakeup is true, controller's wakeup is called.
     23 * For entering clock-pause, -EBUSY is returned if a message txn in pending.
     24 */
     25int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart)
     26{
     27	int i, ret = 0;
     28	unsigned long flags;
     29	struct slim_sched *sched = &ctrl->sched;
     30	struct slim_val_inf msg = {0, 0, NULL, NULL};
     31
     32	DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION,
     33				3, SLIM_LA_MANAGER, &msg);
     34
     35	if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED)
     36		return -EINVAL;
     37
     38	mutex_lock(&sched->m_reconf);
     39	if (wakeup) {
     40		if (sched->clk_state == SLIM_CLK_ACTIVE) {
     41			mutex_unlock(&sched->m_reconf);
     42			return 0;
     43		}
     44
     45		/*
     46		 * Fine-tune calculation based on clock gear,
     47		 * message-bandwidth after bandwidth management
     48		 */
     49		ret = wait_for_completion_timeout(&sched->pause_comp,
     50				msecs_to_jiffies(100));
     51		if (!ret) {
     52			mutex_unlock(&sched->m_reconf);
     53			pr_err("Previous clock pause did not finish");
     54			return -ETIMEDOUT;
     55		}
     56		ret = 0;
     57
     58		/*
     59		 * Slimbus framework will call controller wakeup
     60		 * Controller should make sure that it sets active framer
     61		 * out of clock pause
     62		 */
     63		if (sched->clk_state == SLIM_CLK_PAUSED && ctrl->wakeup)
     64			ret = ctrl->wakeup(ctrl);
     65		if (!ret)
     66			sched->clk_state = SLIM_CLK_ACTIVE;
     67		mutex_unlock(&sched->m_reconf);
     68
     69		return ret;
     70	}
     71
     72	/* already paused */
     73	if (ctrl->sched.clk_state == SLIM_CLK_PAUSED) {
     74		mutex_unlock(&sched->m_reconf);
     75		return 0;
     76	}
     77
     78	spin_lock_irqsave(&ctrl->txn_lock, flags);
     79	for (i = 0; i < SLIM_MAX_TIDS; i++) {
     80		/* Pending response for a message */
     81		if (idr_find(&ctrl->tid_idr, i)) {
     82			spin_unlock_irqrestore(&ctrl->txn_lock, flags);
     83			mutex_unlock(&sched->m_reconf);
     84			return -EBUSY;
     85		}
     86	}
     87	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
     88
     89	sched->clk_state = SLIM_CLK_ENTERING_PAUSE;
     90
     91	/* clock pause sequence */
     92	ret = slim_do_transfer(ctrl, &txn);
     93	if (ret)
     94		goto clk_pause_ret;
     95
     96	txn.mc = SLIM_MSG_MC_NEXT_PAUSE_CLOCK;
     97	txn.rl = 4;
     98	msg.num_bytes = 1;
     99	msg.wbuf = &restart;
    100	ret = slim_do_transfer(ctrl, &txn);
    101	if (ret)
    102		goto clk_pause_ret;
    103
    104	txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW;
    105	txn.rl = 3;
    106	msg.num_bytes = 1;
    107	msg.wbuf = NULL;
    108	ret = slim_do_transfer(ctrl, &txn);
    109
    110clk_pause_ret:
    111	if (ret) {
    112		sched->clk_state = SLIM_CLK_ACTIVE;
    113	} else {
    114		sched->clk_state = SLIM_CLK_PAUSED;
    115		complete(&sched->pause_comp);
    116	}
    117	mutex_unlock(&sched->m_reconf);
    118
    119	return ret;
    120}
    121EXPORT_SYMBOL_GPL(slim_ctrl_clk_pause);