Commit 9a3c425c authored by Justin Ernst's avatar Justin Ernst Committed by Borislav Petkov
Browse files

x86/platform/uv: Add and export uv_bios_* functions



Add additional uv_bios_call() variant functions to expose information
needed by the new uv_sysfs driver. This includes the addition of several
new data types defined by UV BIOS and used in the new functions.

Signed-off-by: default avatarJustin Ernst <justin.ernst@hpe.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarSteve Wahl <steve.wahl@hpe.com>
Acked-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lkml.kernel.org/r/20201125175444.279074-3-justin.ernst@hpe.com
parent 8f061abb
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -28,6 +28,20 @@ enum uv_bios_cmd {
	UV_BIOS_SET_LEGACY_VGA_TARGET
};

#define UV_BIOS_EXTRA			    0x10000
#define UV_BIOS_GET_PCI_TOPOLOGY	    0x10001
#define UV_BIOS_GET_GEOINFO		    0x10003

#define UV_BIOS_EXTRA_OP_MEM_COPYIN	    0x1000
#define UV_BIOS_EXTRA_OP_MEM_COPYOUT	    0x2000
#define UV_BIOS_EXTRA_OP_MASK		    0x0fff
#define UV_BIOS_EXTRA_GET_HEAPSIZE	    1
#define UV_BIOS_EXTRA_INSTALL_HEAP	    2
#define UV_BIOS_EXTRA_MASTER_NASID	    3
#define UV_BIOS_EXTRA_OBJECT_COUNT	    (10|UV_BIOS_EXTRA_OP_MEM_COPYOUT)
#define UV_BIOS_EXTRA_ENUM_OBJECTS	    (12|UV_BIOS_EXTRA_OP_MEM_COPYOUT)
#define UV_BIOS_EXTRA_ENUM_PORTS	    (13|UV_BIOS_EXTRA_OP_MEM_COPYOUT)

/*
 * Status values returned from a BIOS call.
 */
@@ -109,6 +123,32 @@ struct uv_systab {
	} entry[1];		/* additional entries follow */
};
extern struct uv_systab *uv_systab;

#define UV_BIOS_MAXSTRING	      128
struct uv_bios_hub_info {
	unsigned int id;
	union {
		struct {
			unsigned long long this_part:1;
			unsigned long long is_shared:1;
			unsigned long long is_disabled:1;
		} fields;
		struct {
			unsigned long long flags;
			unsigned long long reserved;
		} b;
	} f;
	char name[UV_BIOS_MAXSTRING];
	char location[UV_BIOS_MAXSTRING];
	unsigned int ports;
};

struct uv_bios_port_info {
	unsigned int port;
	unsigned int conn_id;
	unsigned int conn_port;
};

/* (... end of definitions from UV BIOS ...) */

enum {
@@ -142,6 +182,15 @@ extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect);
extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *);
extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus);

extern s64 uv_bios_get_master_nasid(u64 sz, u64 *nasid);
extern s64 uv_bios_get_heapsize(u64 nasid, u64 sz, u64 *heap_sz);
extern s64 uv_bios_install_heap(u64 nasid, u64 sz, u64 *heap);
extern s64 uv_bios_obj_count(u64 nasid, u64 sz, u64 *objcnt);
extern s64 uv_bios_enum_objs(u64 nasid, u64 sz, u64 *objbuf);
extern s64 uv_bios_enum_ports(u64 nasid, u64 obj_id, u64 sz, u64 *portbuf);
extern s64 uv_bios_get_geoinfo(u64 nasid, u64 sz, u64 *geo);
extern s64 uv_bios_get_pci_topology(u64 sz, u64 *buf);

extern int uv_bios_init(void);
extern unsigned long get_uv_systab_phys(bool msg);

+103 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2020 Hewlett Packard Enterprise Development LP. All rights reserved.
 */

#ifndef _ASM_UV_GEO_H
#define _ASM_UV_GEO_H

/* Type declaractions */

/* Size of a geoid_s structure (must be before decl. of geoid_u) */
#define GEOID_SIZE	8

/* Fields common to all substructures */
struct geo_common_s {
	unsigned char type;		/* What type of h/w is named by this geoid_s */
	unsigned char blade;
	unsigned char slot;		/* slot is IRU */
	unsigned char upos;
	unsigned char rack;
};

/* Additional fields for particular types of hardware */
struct geo_node_s {
	struct geo_common_s common;		/* No additional fields needed */
};

struct geo_rtr_s {
	struct geo_common_s common;		/* No additional fields needed */
};

struct geo_iocntl_s {
	struct geo_common_s common;		/* No additional fields needed */
};

struct geo_pcicard_s {
	struct geo_iocntl_s common;
	char bus;				/* Bus/widget number */
	char slot;				/* PCI slot number */
};

/* Subcomponents of a node */
struct geo_cpu_s {
	struct geo_node_s node;
	unsigned char	socket:4,	/* Which CPU on the node */
			thread:4;
	unsigned char	core;
};

struct geo_mem_s {
	struct geo_node_s node;
	char membus;			/* The memory bus on the node */
	char memslot;			/* The memory slot on the bus */
};

union geoid_u {
	struct geo_common_s common;
	struct geo_node_s node;
	struct geo_iocntl_s iocntl;
	struct geo_pcicard_s pcicard;
	struct geo_rtr_s rtr;
	struct geo_cpu_s cpu;
	struct geo_mem_s mem;
	char padsize[GEOID_SIZE];
};

/* Defined constants */

#define GEO_MAX_LEN	48

#define GEO_TYPE_INVALID	0
#define GEO_TYPE_MODULE		1
#define GEO_TYPE_NODE		2
#define GEO_TYPE_RTR		3
#define GEO_TYPE_IOCNTL		4
#define GEO_TYPE_IOCARD		5
#define GEO_TYPE_CPU		6
#define GEO_TYPE_MEM		7
#define GEO_TYPE_MAX		(GEO_TYPE_MEM+1)

static inline int geo_rack(union geoid_u g)
{
	return (g.common.type == GEO_TYPE_INVALID) ?
		-1 : g.common.rack;
}

static inline int geo_slot(union geoid_u g)
{
	return (g.common.type == GEO_TYPE_INVALID) ?
		-1 : g.common.upos;
}

static inline int geo_blade(union geoid_u g)
{
	return (g.common.type == GEO_TYPE_INVALID) ?
		-1 : g.common.blade * 2 + g.common.slot;
}

#endif /* _ASM_UV_GEO_H */
+55 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ static s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
long sn_partition_id;
EXPORT_SYMBOL_GPL(sn_partition_id);
long sn_coherency_id;
EXPORT_SYMBOL_GPL(sn_coherency_id);
long sn_region_size;
EXPORT_SYMBOL_GPL(sn_region_size);
long system_serial_number;
@@ -171,6 +172,60 @@ int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
				(u64)decode, (u64)domain, (u64)bus, 0, 0);
}

extern s64 uv_bios_get_master_nasid(u64 size, u64 *master_nasid)
{
	return uv_bios_call(UV_BIOS_EXTRA, 0, UV_BIOS_EXTRA_MASTER_NASID, 0,
				size, (u64)master_nasid);
}
EXPORT_SYMBOL_GPL(uv_bios_get_master_nasid);

extern s64 uv_bios_get_heapsize(u64 nasid, u64 size, u64 *heap_size)
{
	return uv_bios_call(UV_BIOS_EXTRA, nasid, UV_BIOS_EXTRA_GET_HEAPSIZE,
				0, size, (u64)heap_size);
}
EXPORT_SYMBOL_GPL(uv_bios_get_heapsize);

extern s64 uv_bios_install_heap(u64 nasid, u64 heap_size, u64 *bios_heap)
{
	return uv_bios_call(UV_BIOS_EXTRA, nasid, UV_BIOS_EXTRA_INSTALL_HEAP,
				0, heap_size, (u64)bios_heap);
}
EXPORT_SYMBOL_GPL(uv_bios_install_heap);

extern s64 uv_bios_obj_count(u64 nasid, u64 size, u64 *objcnt)
{
	return uv_bios_call(UV_BIOS_EXTRA, nasid, UV_BIOS_EXTRA_OBJECT_COUNT,
				0, size, (u64)objcnt);
}
EXPORT_SYMBOL_GPL(uv_bios_obj_count);

extern s64 uv_bios_enum_objs(u64 nasid, u64 size, u64 *objbuf)
{
	return uv_bios_call(UV_BIOS_EXTRA, nasid, UV_BIOS_EXTRA_ENUM_OBJECTS,
				0, size, (u64)objbuf);
}
EXPORT_SYMBOL_GPL(uv_bios_enum_objs);

extern s64 uv_bios_enum_ports(u64 nasid, u64 obj_id, u64 size, u64 *portbuf)
{
	return uv_bios_call(UV_BIOS_EXTRA, nasid, UV_BIOS_EXTRA_ENUM_PORTS,
				obj_id, size, (u64)portbuf);
}
EXPORT_SYMBOL_GPL(uv_bios_enum_ports);

extern s64 uv_bios_get_geoinfo(u64 nasid, u64 size, u64 *buf)
{
	return uv_bios_call(UV_BIOS_GET_GEOINFO, nasid, (u64)buf, size, 0, 0);
}
EXPORT_SYMBOL_GPL(uv_bios_get_geoinfo);

extern s64 uv_bios_get_pci_topology(u64 size, u64 *buf)
{
	return uv_bios_call(UV_BIOS_GET_PCI_TOPOLOGY, (u64)buf, size, 0, 0, 0);
}
EXPORT_SYMBOL_GPL(uv_bios_get_pci_topology);

unsigned long get_uv_systab_phys(bool msg)
{
	if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||