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

ctresource.c (5467B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
      4 *
      5 * @File	ctresource.c
      6 *
      7 * @Brief
      8 * This file contains the implementation of some generic helper functions.
      9 *
     10 * @Author	Liu Chun
     11 * @Date 	May 15 2008
     12 */
     13
     14#include "ctresource.h"
     15#include "cthardware.h"
     16#include <linux/err.h>
     17#include <linux/slab.h>
     18
     19#define AUDIO_SLOT_BLOCK_NUM 	256
     20
     21/* Resource allocation based on bit-map management mechanism */
     22static int
     23get_resource(u8 *rscs, unsigned int amount,
     24	     unsigned int multi, unsigned int *ridx)
     25{
     26	int i, j, k, n;
     27
     28	/* Check whether there are sufficient resources to meet request. */
     29	for (i = 0, n = multi; i < amount; i++) {
     30		j = i / 8;
     31		k = i % 8;
     32		if (rscs[j] & ((u8)1 << k)) {
     33			n = multi;
     34			continue;
     35		}
     36		if (!(--n))
     37			break; /* found sufficient contiguous resources */
     38	}
     39
     40	if (i >= amount) {
     41		/* Can not find sufficient contiguous resources */
     42		return -ENOENT;
     43	}
     44
     45	/* Mark the contiguous bits in resource bit-map as used */
     46	for (n = multi; n > 0; n--) {
     47		j = i / 8;
     48		k = i % 8;
     49		rscs[j] |= ((u8)1 << k);
     50		i--;
     51	}
     52
     53	*ridx = i + 1;
     54
     55	return 0;
     56}
     57
     58static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
     59{
     60	unsigned int i, j, k, n;
     61
     62	/* Mark the contiguous bits in resource bit-map as used */
     63	for (n = multi, i = idx; n > 0; n--) {
     64		j = i / 8;
     65		k = i % 8;
     66		rscs[j] &= ~((u8)1 << k);
     67		i++;
     68	}
     69
     70	return 0;
     71}
     72
     73int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
     74{
     75	int err;
     76
     77	if (n > mgr->avail)
     78		return -ENOENT;
     79
     80	err = get_resource(mgr->rscs, mgr->amount, n, ridx);
     81	if (!err)
     82		mgr->avail -= n;
     83
     84	return err;
     85}
     86
     87int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
     88{
     89	put_resource(mgr->rscs, n, idx);
     90	mgr->avail += n;
     91
     92	return 0;
     93}
     94
     95static const unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
     96	/* SRC channel is at Audio Ring slot 1 every 16 slots. */
     97	[SRC]		= 0x1,
     98	[AMIXER]	= 0x4,
     99	[SUM]		= 0xc,
    100};
    101
    102static int rsc_index(const struct rsc *rsc)
    103{
    104    return rsc->conj;
    105}
    106
    107static int audio_ring_slot(const struct rsc *rsc)
    108{
    109    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
    110}
    111
    112static void rsc_next_conj(struct rsc *rsc)
    113{
    114	unsigned int i;
    115	for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
    116		i++;
    117	rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
    118}
    119
    120static void rsc_master(struct rsc *rsc)
    121{
    122	rsc->conj = rsc->idx;
    123}
    124
    125static const struct rsc_ops rsc_generic_ops = {
    126	.index		= rsc_index,
    127	.output_slot	= audio_ring_slot,
    128	.master		= rsc_master,
    129	.next_conj	= rsc_next_conj,
    130};
    131
    132int
    133rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
    134{
    135	int err = 0;
    136
    137	rsc->idx = idx;
    138	rsc->conj = idx;
    139	rsc->type = type;
    140	rsc->msr = msr;
    141	rsc->hw = hw;
    142	rsc->ops = &rsc_generic_ops;
    143	if (!hw) {
    144		rsc->ctrl_blk = NULL;
    145		return 0;
    146	}
    147
    148	switch (type) {
    149	case SRC:
    150		err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
    151		break;
    152	case AMIXER:
    153		err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
    154		break;
    155	case SRCIMP:
    156	case SUM:
    157	case DAIO:
    158		break;
    159	default:
    160		dev_err(((struct hw *)hw)->card->dev,
    161			"Invalid resource type value %d!\n", type);
    162		return -EINVAL;
    163	}
    164
    165	if (err) {
    166		dev_err(((struct hw *)hw)->card->dev,
    167			"Failed to get resource control block!\n");
    168		return err;
    169	}
    170
    171	return 0;
    172}
    173
    174int rsc_uninit(struct rsc *rsc)
    175{
    176	if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
    177		switch (rsc->type) {
    178		case SRC:
    179			rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
    180			break;
    181		case AMIXER:
    182			rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
    183			break;
    184		case SUM:
    185		case DAIO:
    186			break;
    187		default:
    188			dev_err(((struct hw *)rsc->hw)->card->dev,
    189				"Invalid resource type value %d!\n",
    190				rsc->type);
    191			break;
    192		}
    193
    194		rsc->hw = rsc->ctrl_blk = NULL;
    195	}
    196
    197	rsc->idx = rsc->conj = 0;
    198	rsc->type = NUM_RSCTYP;
    199	rsc->msr = 0;
    200
    201	return 0;
    202}
    203
    204int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
    205		 unsigned int amount, struct hw *hw)
    206{
    207	int err = 0;
    208
    209	mgr->type = NUM_RSCTYP;
    210
    211	mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);
    212	if (!mgr->rscs)
    213		return -ENOMEM;
    214
    215	switch (type) {
    216	case SRC:
    217		err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
    218		break;
    219	case SRCIMP:
    220		err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
    221		break;
    222	case AMIXER:
    223		err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
    224		break;
    225	case DAIO:
    226		err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
    227		break;
    228	case SUM:
    229		break;
    230	default:
    231		dev_err(hw->card->dev,
    232			"Invalid resource type value %d!\n", type);
    233		err = -EINVAL;
    234		goto error;
    235	}
    236
    237	if (err) {
    238		dev_err(hw->card->dev,
    239			"Failed to get manager control block!\n");
    240		goto error;
    241	}
    242
    243	mgr->type = type;
    244	mgr->avail = mgr->amount = amount;
    245	mgr->hw = hw;
    246
    247	return 0;
    248
    249error:
    250	kfree(mgr->rscs);
    251	return err;
    252}
    253
    254int rsc_mgr_uninit(struct rsc_mgr *mgr)
    255{
    256	kfree(mgr->rscs);
    257	mgr->rscs = NULL;
    258
    259	if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
    260		switch (mgr->type) {
    261		case SRC:
    262			mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
    263			break;
    264		case SRCIMP:
    265			mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
    266			break;
    267		case AMIXER:
    268			mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
    269			break;
    270		case DAIO:
    271			mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
    272			break;
    273		case SUM:
    274			break;
    275		default:
    276			dev_err(((struct hw *)mgr->hw)->card->dev,
    277				"Invalid resource type value %d!\n",
    278				mgr->type);
    279			break;
    280		}
    281
    282		mgr->hw = mgr->ctrl_blk = NULL;
    283	}
    284
    285	mgr->type = NUM_RSCTYP;
    286	mgr->avail = mgr->amount = 0;
    287
    288	return 0;
    289}