drivers/ras/amd/atl/system.c

Source file repositories/reference/linux-study-clean/drivers/ras/amd/atl/system.c

File Facts

System
Linux kernel
Corpus path
drivers/ras/amd/atl/system.c
Extension
.c
Size
8085 bytes
Lines
322
Domain
Driver Families
Bucket
drivers/ras
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * AMD Address Translation Library
 *
 * system.c : Functions to read and save system-wide data
 *
 * Copyright (c) 2023, Advanced Micro Devices, Inc.
 * All Rights Reserved.
 *
 * Author: Yazen Ghannam <Yazen.Ghannam@amd.com>
 */

#include "internal.h"

#include <linux/prmt.h>

const guid_t norm_to_sys_guid = GUID_INIT(0xE7180659, 0xA65D, 0x451D,
					  0x92, 0xCD, 0x2B, 0x56, 0xF1,
					  0x2B, 0xEB, 0xA6);

int determine_node_id(struct addr_ctx *ctx, u8 socket_id, u8 die_id)
{
	u16 socket_id_bits, die_id_bits;

	if (socket_id > 0 && df_cfg.socket_id_mask == 0) {
		atl_debug(ctx, "Invalid socket inputs: socket_id=%u socket_id_mask=0x%x",
			  socket_id, df_cfg.socket_id_mask);
		return -EINVAL;
	}

	/* Do each step independently to avoid shift out-of-bounds issues. */
	socket_id_bits =	socket_id;
	socket_id_bits <<=	df_cfg.socket_id_shift;
	socket_id_bits &=	df_cfg.socket_id_mask;

	if (die_id > 0 && df_cfg.die_id_mask == 0) {
		atl_debug(ctx, "Invalid die inputs: die_id=%u die_id_mask=0x%x",
			  die_id, df_cfg.die_id_mask);
		return -EINVAL;
	}

	/* Do each step independently to avoid shift out-of-bounds issues. */
	die_id_bits =		die_id;
	die_id_bits <<=		df_cfg.die_id_shift;
	die_id_bits &=		df_cfg.die_id_mask;

	ctx->node_id = (socket_id_bits | die_id_bits) >> df_cfg.node_id_shift;
	return 0;
}

static void df2_get_masks_shifts(u32 mask0)
{
	df_cfg.socket_id_shift		= FIELD_GET(DF2_SOCKET_ID_SHIFT, mask0);
	df_cfg.socket_id_mask		= FIELD_GET(DF2_SOCKET_ID_MASK, mask0);
	df_cfg.die_id_shift		= FIELD_GET(DF2_DIE_ID_SHIFT, mask0);
	df_cfg.die_id_mask		= FIELD_GET(DF2_DIE_ID_MASK, mask0);
	df_cfg.node_id_shift		= df_cfg.die_id_shift;
	df_cfg.node_id_mask		= df_cfg.socket_id_mask | df_cfg.die_id_mask;
	df_cfg.component_id_mask	= ~df_cfg.node_id_mask;
}

static void df3_get_masks_shifts(u32 mask0, u32 mask1)
{
	df_cfg.component_id_mask	= FIELD_GET(DF3_COMPONENT_ID_MASK, mask0);
	df_cfg.node_id_mask		= FIELD_GET(DF3_NODE_ID_MASK, mask0);

	df_cfg.node_id_shift		= FIELD_GET(DF3_NODE_ID_SHIFT, mask1);
	df_cfg.socket_id_shift		= FIELD_GET(DF3_SOCKET_ID_SHIFT, mask1);
	df_cfg.socket_id_mask		= FIELD_GET(DF3_SOCKET_ID_MASK, mask1);
	df_cfg.die_id_mask		= FIELD_GET(DF3_DIE_ID_MASK, mask1);
}

static void df3p5_get_masks_shifts(u32 mask0, u32 mask1, u32 mask2)
{
	df_cfg.component_id_mask	= FIELD_GET(DF4_COMPONENT_ID_MASK, mask0);
	df_cfg.node_id_mask		= FIELD_GET(DF4_NODE_ID_MASK, mask0);

	df_cfg.node_id_shift		= FIELD_GET(DF3_NODE_ID_SHIFT, mask1);
	df_cfg.socket_id_shift		= FIELD_GET(DF4_SOCKET_ID_SHIFT, mask1);

	df_cfg.socket_id_mask		= FIELD_GET(DF4_SOCKET_ID_MASK, mask2);
	df_cfg.die_id_mask		= FIELD_GET(DF4_DIE_ID_MASK, mask2);
}

static void df4_get_masks_shifts(u32 mask0, u32 mask1, u32 mask2)
{
	df3p5_get_masks_shifts(mask0, mask1, mask2);

	if (!(df_cfg.flags.socket_id_shift_quirk && df_cfg.socket_id_shift == 1))
		return;

Annotation

Implementation Notes