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

irq_service.c (4183B)


      1/*
      2 * Copyright 2012-15 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include <linux/slab.h>
     27
     28#include "dm_services.h"
     29
     30#include "include/irq_service_interface.h"
     31#include "include/logger_interface.h"
     32
     33#include "dce110/irq_service_dce110.h"
     34
     35#if defined(CONFIG_DRM_AMD_DC_SI)
     36#include "dce60/irq_service_dce60.h"
     37#endif
     38
     39#include "dce80/irq_service_dce80.h"
     40#include "dce120/irq_service_dce120.h"
     41#include "dcn10/irq_service_dcn10.h"
     42
     43#include "reg_helper.h"
     44#include "irq_service.h"
     45
     46
     47
     48#define CTX \
     49		irq_service->ctx
     50#define DC_LOGGER \
     51	irq_service->ctx->logger
     52
     53void dal_irq_service_construct(
     54	struct irq_service *irq_service,
     55	struct irq_service_init_data *init_data)
     56{
     57	if (!init_data || !init_data->ctx) {
     58		BREAK_TO_DEBUGGER();
     59		return;
     60	}
     61
     62	irq_service->ctx = init_data->ctx;
     63}
     64
     65void dal_irq_service_destroy(struct irq_service **irq_service)
     66{
     67	if (!irq_service || !*irq_service) {
     68		BREAK_TO_DEBUGGER();
     69		return;
     70	}
     71
     72	kfree(*irq_service);
     73
     74	*irq_service = NULL;
     75}
     76
     77static const struct irq_source_info *find_irq_source_info(
     78	struct irq_service *irq_service,
     79	enum dc_irq_source source)
     80{
     81	if (source >= DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
     82		return NULL;
     83
     84	return &irq_service->info[source];
     85}
     86
     87void dal_irq_service_set_generic(
     88	struct irq_service *irq_service,
     89	const struct irq_source_info *info,
     90	bool enable)
     91{
     92	uint32_t addr = info->enable_reg;
     93	uint32_t value = dm_read_reg(irq_service->ctx, addr);
     94
     95	value = (value & ~info->enable_mask) |
     96		(info->enable_value[enable ? 0 : 1] & info->enable_mask);
     97	dm_write_reg(irq_service->ctx, addr, value);
     98}
     99
    100bool dal_irq_service_set(
    101	struct irq_service *irq_service,
    102	enum dc_irq_source source,
    103	bool enable)
    104{
    105	const struct irq_source_info *info =
    106		find_irq_source_info(irq_service, source);
    107
    108	if (!info) {
    109		DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
    110			__func__,
    111			source);
    112		return false;
    113	}
    114
    115	dal_irq_service_ack(irq_service, source);
    116
    117	if (info->funcs && info->funcs->set)
    118		return info->funcs->set(irq_service, info, enable);
    119
    120	dal_irq_service_set_generic(irq_service, info, enable);
    121
    122	return true;
    123}
    124
    125void dal_irq_service_ack_generic(
    126	struct irq_service *irq_service,
    127	const struct irq_source_info *info)
    128{
    129	uint32_t addr = info->ack_reg;
    130	uint32_t value = dm_read_reg(irq_service->ctx, addr);
    131
    132	value = (value & ~info->ack_mask) |
    133		(info->ack_value & info->ack_mask);
    134	dm_write_reg(irq_service->ctx, addr, value);
    135}
    136
    137bool dal_irq_service_ack(
    138	struct irq_service *irq_service,
    139	enum dc_irq_source source)
    140{
    141	const struct irq_source_info *info =
    142		find_irq_source_info(irq_service, source);
    143
    144	if (!info) {
    145		DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
    146			__func__,
    147			source);
    148		return false;
    149	}
    150
    151	if (info->funcs && info->funcs->ack)
    152		return info->funcs->ack(irq_service, info);
    153
    154	dal_irq_service_ack_generic(irq_service, info);
    155
    156	return true;
    157}
    158
    159enum dc_irq_source dal_irq_service_to_irq_source(
    160		struct irq_service *irq_service,
    161		uint32_t src_id,
    162		uint32_t ext_id)
    163{
    164	return irq_service->funcs->to_dal_irq_source(
    165		irq_service,
    166		src_id,
    167		ext_id);
    168}