^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* mdesc.c: Sun4V machine description handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/refcount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/cpudata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/hypervisor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/mdesc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/adi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Unlike the OBP device tree, the machine description is a full-on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * DAG. An arbitrary number of ARCs are possible from one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * node to other nodes and thus we can't use the OBP device_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * data structure to represent these nodes inside of the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Actually, it isn't even a DAG, because there are back pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * which create cycles in the graph.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * mdesc_hdr and mdesc_elem describe the layout of the data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * we get from the Hypervisor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct mdesc_hdr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 version; /* Transport version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 node_sz; /* node block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 name_sz; /* name block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 data_sz; /* data block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) char data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } __attribute__((aligned(16)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct mdesc_elem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u8 tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MD_LIST_END 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MD_NODE 0x4e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MD_NODE_END 0x45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MD_NOOP 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MD_PROP_ARC 0x61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MD_PROP_VAL 0x76
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MD_PROP_STR 0x73
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MD_PROP_DATA 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u16 resv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 name_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) } data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct mdesc_mem_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void (*free)(struct mdesc_handle *handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct mdesc_handle {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct mdesc_mem_ops *mops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void *self_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) refcount_t refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned int handle_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct mdesc_hdr mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) typedef int (*mdesc_node_info_get_f)(struct mdesc_handle *, u64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) union md_node_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) typedef void (*mdesc_node_info_rel_f)(union md_node_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) typedef bool (*mdesc_node_match_f)(union md_node_info *, union md_node_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct md_node_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) mdesc_node_info_get_f get_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mdesc_node_info_rel_f rel_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mdesc_node_match_f node_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) union md_node_info *node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void rel_vdev_port_node_info(union md_node_info *node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static bool vdev_port_node_match(union md_node_info *a_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) union md_node_info *b_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int get_ds_port_node_info(struct mdesc_handle *md, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) union md_node_info *node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void rel_ds_port_node_info(union md_node_info *node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static bool ds_port_node_match(union md_node_info *a_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) union md_node_info *b_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* supported node types which can be registered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static struct md_node_ops md_node_ops_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {"virtual-device-port", get_vdev_port_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) rel_vdev_port_node_info, vdev_port_node_match},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {"domain-services-port", get_ds_port_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) rel_ds_port_node_info, ds_port_node_match},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {NULL, NULL, NULL, NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void mdesc_get_node_ops(const char *node_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mdesc_node_info_get_f *get_info_f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mdesc_node_info_rel_f *rel_info_f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mdesc_node_match_f *match_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (get_info_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *get_info_f = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (rel_info_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *rel_info_f = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (match_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *match_f = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!node_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for (i = 0; md_node_ops_table[i].name != NULL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (strcmp(md_node_ops_table[i].name, node_name) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (get_info_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *get_info_f = md_node_ops_table[i].get_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (rel_info_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *rel_info_f = md_node_ops_table[i].rel_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (match_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) *match_f = md_node_ops_table[i].node_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void mdesc_handle_init(struct mdesc_handle *hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int handle_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) memset(hp, 0, handle_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) INIT_LIST_HEAD(&hp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) hp->self_base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) refcount_set(&hp->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) hp->handle_size = handle_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static struct mdesc_handle * __init mdesc_memblock_alloc(unsigned int mdesc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int handle_size, alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned long paddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) handle_size = (sizeof(struct mdesc_handle) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sizeof(struct mdesc_hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mdesc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) alloc_size = PAGE_ALIGN(handle_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) paddr = memblock_phys_alloc(alloc_size, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) hp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (paddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) hp = __va(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mdesc_handle_init(hp, handle_size, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void __init mdesc_memblock_free(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) BUG_ON(refcount_read(&hp->refcnt) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) BUG_ON(!list_empty(&hp->list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) alloc_size = PAGE_ALIGN(hp->handle_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) start = __pa(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) memblock_free_late(start, alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static struct mdesc_mem_ops memblock_mdesc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .alloc = mdesc_memblock_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .free = mdesc_memblock_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned int handle_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) void *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) handle_size = (sizeof(struct mdesc_handle) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) sizeof(struct mdesc_hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mdesc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) addr = (unsigned long)base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) addr = (addr + 15UL) & ~15UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) hp = (struct mdesc_handle *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) mdesc_handle_init(hp, handle_size, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static void mdesc_kfree(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) BUG_ON(refcount_read(&hp->refcnt) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) BUG_ON(!list_empty(&hp->list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) kfree(hp->self_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct mdesc_mem_ops kmalloc_mdesc_memops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .alloc = mdesc_kmalloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .free = mdesc_kfree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct mdesc_mem_ops *mops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct mdesc_handle *hp = mops->alloc(mdesc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) hp->mops = mops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static void mdesc_free(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) hp->mops->free(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static struct mdesc_handle *cur_mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static LIST_HEAD(mdesc_zombie_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static DEFINE_SPINLOCK(mdesc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct mdesc_handle *mdesc_grab(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) spin_lock_irqsave(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) hp = cur_mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) refcount_inc(&hp->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) spin_unlock_irqrestore(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) EXPORT_SYMBOL(mdesc_grab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) void mdesc_release(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) spin_lock_irqsave(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (refcount_dec_and_test(&hp->refcnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) list_del_init(&hp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) hp->mops->free(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) spin_unlock_irqrestore(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) EXPORT_SYMBOL(mdesc_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static DEFINE_MUTEX(mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static struct mdesc_notifier_client *client_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void mdesc_register_notifier(struct mdesc_notifier_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) bool supported = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u64 node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mutex_lock(&mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* check to see if the node is supported for registration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) for (i = 0; md_node_ops_table[i].name != NULL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (strcmp(md_node_ops_table[i].name, client->node_name) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) supported = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pr_err("MD: %s node not supported\n", client->node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mutex_unlock(&mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) client->next = client_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) client_list = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) client->add(cur_mdesc, node, client->node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mutex_unlock(&mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const u64 *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u64 a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) id = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u64 target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) target = mdesc_arc_target(hp, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) id = mdesc_get_property(hp, target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) "cfg-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) const u64 *parent_cfg_hdlp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) const u64 *idp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * Virtual device nodes are distinguished by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * 1. "id" property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * 2. "name" property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * 3. parent node "cfg-handle" property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) idp = mdesc_get_property(md, node, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) name = mdesc_get_property(md, node, "name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) parent_cfg_hdlp = parent_cfg_handle(md, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!idp || !name || !parent_cfg_hdlp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) node_info->vdev_port.id = *idp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) node_info->vdev_port.name = kstrdup_const(name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!node_info->vdev_port.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) node_info->vdev_port.parent_cfg_hdl = *parent_cfg_hdlp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void rel_vdev_port_node_info(union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (node_info && node_info->vdev_port.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kfree_const(node_info->vdev_port.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) node_info->vdev_port.name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static bool vdev_port_node_match(union md_node_info *a_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) union md_node_info *b_node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (a_node_info->vdev_port.id != b_node_info->vdev_port.id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (a_node_info->vdev_port.parent_cfg_hdl !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) b_node_info->vdev_port.parent_cfg_hdl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (strncmp(a_node_info->vdev_port.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) b_node_info->vdev_port.name, MDESC_MAX_STR_LEN) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int get_ds_port_node_info(struct mdesc_handle *md, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) const u64 *idp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* DS port nodes use the "id" property to distinguish them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) idp = mdesc_get_property(md, node, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!idp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) node_info->ds_port.id = *idp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void rel_ds_port_node_info(union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static bool ds_port_node_match(union md_node_info *a_node_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) union md_node_info *b_node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (a_node_info->ds_port.id != b_node_info->ds_port.id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /* Run 'func' on nodes which are in A but not in B. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static void invoke_on_missing(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct mdesc_handle *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct mdesc_handle *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) void (*func)(struct mdesc_handle *, u64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) const char *node_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) mdesc_node_info_get_f get_info_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mdesc_node_info_rel_f rel_info_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) mdesc_node_match_f node_match_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) union md_node_info a_node_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) union md_node_info b_node_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) bool found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u64 a_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) u64 b_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Find the get_info, rel_info and node_match ops for the given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * node name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) mdesc_get_node_ops(name, &get_info_func, &rel_info_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) &node_match_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* If we didn't find a match, the node type is not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!get_info_func || !rel_info_func || !node_match_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) pr_err("MD: %s node type is not supported\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) mdesc_for_each_node_by_name(a, a_node, name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) rv = get_info_func(a, a_node, &a_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (rv != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) pr_err("MD: Cannot find 1 or more required match properties for %s node.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Check each node in B for node matching a_node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) mdesc_for_each_node_by_name(b, b_node, name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) rv = get_info_func(b, b_node, &b_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (rv != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (node_match_func(&a_node_info, &b_node_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) rel_info_func(&b_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rel_info_func(&b_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rel_info_func(&a_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) func(a, a_node, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static void notify_one(struct mdesc_notifier_client *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct mdesc_handle *old_hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct mdesc_handle *new_hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static void mdesc_notify_clients(struct mdesc_handle *old_hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct mdesc_handle *new_hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct mdesc_notifier_client *p = client_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) notify_one(p, old_hp, new_hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) void mdesc_update(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) unsigned long len, real_len, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct mdesc_handle *hp, *orig_hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) mutex_lock(&mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) (void) sun4v_mach_desc(0UL, 0UL, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!hp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) printk(KERN_ERR "MD: mdesc alloc fails\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (status != HV_EOK || real_len > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) refcount_dec(&hp->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mdesc_free(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) spin_lock_irqsave(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) orig_hp = cur_mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) cur_mdesc = hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) spin_unlock_irqrestore(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) mdesc_notify_clients(orig_hp, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) spin_lock_irqsave(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (refcount_dec_and_test(&orig_hp->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) mdesc_free(orig_hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) list_add(&orig_hp->list, &mdesc_zombie_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) spin_unlock_irqrestore(&mdesc_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) mutex_unlock(&mdesc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) mdesc_node_info_get_f get_info_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mdesc_node_info_rel_f rel_info_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mdesc_node_match_f node_match_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) union md_node_info hp_node_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u64 hp_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (hp == NULL || node_name == NULL || node_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Find the ops for the given node name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mdesc_get_node_ops(node_name, &get_info_func, &rel_info_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) &node_match_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* If we didn't find ops for the given node name, it is not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!get_info_func || !rel_info_func || !node_match_func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) pr_err("MD: %s node is not supported\n", node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) mdesc_for_each_node_by_name(hp, hp_node, node_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) rv = get_info_func(hp, hp_node, &hp_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (rv != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (node_match_func(node_info, &hp_node_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) rel_info_func(&hp_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) rel_info_func(&hp_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return hp_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) EXPORT_SYMBOL(mdesc_get_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int mdesc_get_node_info(struct mdesc_handle *hp, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) const char *node_name, union md_node_info *node_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mdesc_node_info_get_f get_info_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (hp == NULL || node == MDESC_NODE_NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) node_name == NULL || node_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* Find the get_info op for the given node name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mdesc_get_node_ops(node_name, &get_info_func, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* If we didn't find a get_info_func, the node name is not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (get_info_func == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pr_err("MD: %s node is not supported\n", node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) rv = get_info_func(hp, node, node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (rv != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) pr_err("MD: Cannot find 1 or more required match properties for %s node.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) EXPORT_SYMBOL(mdesc_get_node_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return (struct mdesc_elem *) mdesc->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static void *name_block(struct mdesc_hdr *mdesc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return ((void *) node_block(mdesc)) + mdesc->node_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static void *data_block(struct mdesc_hdr *mdesc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ((void *) name_block(mdesc)) + mdesc->name_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) u64 mdesc_node_by_name(struct mdesc_handle *hp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) u64 from_node, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct mdesc_elem *ep = node_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) const char *names = name_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) u64 last_node = hp->mdesc.node_sz / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) u64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (from_node == MDESC_NODE_NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = from_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) } else if (from_node >= last_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ret = ep[from_node].d.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) while (ret < last_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ep[ret].tag != MD_NODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (!strcmp(names + ep[ret].name_offset, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = ep[ret].d.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (ret >= last_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) EXPORT_SYMBOL(mdesc_node_by_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) const char *name, int *lenp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) const char *names = name_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) u64 last_node = hp->mdesc.node_sz / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) void *data = data_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct mdesc_elem *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (node == MDESC_NODE_NULL || node >= last_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ep = node_block(&hp->mdesc) + node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ep++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) for (; ep->tag != MD_NODE_END; ep++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) void *val = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) switch (ep->tag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) case MD_PROP_VAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) val = &ep->d.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) case MD_PROP_STR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) case MD_PROP_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) val = data + ep->d.data.data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) len = ep->d.data.data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!strcmp(names + ep->name_offset, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (lenp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) *lenp = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) EXPORT_SYMBOL(mdesc_get_property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) const char *names = name_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) u64 last_node = hp->mdesc.node_sz / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (from == MDESC_NODE_NULL || from >= last_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ep = base + from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ep++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) for (; ep->tag != MD_NODE_END; ep++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (ep->tag != MD_PROP_ARC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (strcmp(names + ep->name_offset, arc_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return ep - base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return MDESC_NODE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) EXPORT_SYMBOL(mdesc_next_arc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ep = base + arc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ep->d.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) EXPORT_SYMBOL(mdesc_arc_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) const char *names = name_block(&hp->mdesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) u64 last_node = hp->mdesc.node_sz / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (node == MDESC_NODE_NULL || node >= last_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ep = base + node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (ep->tag != MD_NODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return names + ep->name_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) EXPORT_SYMBOL(mdesc_node_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static u64 max_cpus = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static void __init report_platform_properties(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct mdesc_handle *hp = mdesc_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) const char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) const u64 *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (pn == MDESC_NODE_NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) prom_printf("No platform node in machine-description.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) prom_halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) s = mdesc_get_property(hp, pn, "banner-name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) printk("PLATFORM: banner-name [%s]\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) s = mdesc_get_property(hp, pn, "name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) printk("PLATFORM: name [%s]\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) v = mdesc_get_property(hp, pn, "hostid", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) printk("PLATFORM: hostid [%08llx]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) v = mdesc_get_property(hp, pn, "serial#", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) printk("PLATFORM: serial# [%08llx]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) printk("PLATFORM: stick-frequency [%08llx]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) v = mdesc_get_property(hp, pn, "mac-address", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) printk("PLATFORM: mac-address [%llx]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) printk("PLATFORM: watchdog-resolution [%llu ms]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) v = mdesc_get_property(hp, pn, "max-cpus", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) max_cpus = *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) int max_cpu, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) max_cpu = *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (max_cpu > NR_CPUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) max_cpu = NR_CPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) max_cpu = NR_CPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) for (i = 0; i < max_cpu; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) set_cpu_possible(i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mdesc_release(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int type_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) type = mdesc_get_property(hp, mp, "type", &type_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) switch (*level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (of_find_in_proplist(type, "instn", type_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) c->icache_size = *size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) c->icache_line_size = *line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) } else if (of_find_in_proplist(type, "data", type_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) c->dcache_size = *size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) c->dcache_line_size = *line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) c->ecache_size = *size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) c->ecache_line_size = *line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (*level == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) u64 a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u64 target = mdesc_arc_target(hp, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) const char *name = mdesc_node_name(hp, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (!strcmp(name, "cache"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) fill_in_one_cache(c, hp, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static void find_back_node_value(struct mdesc_handle *hp, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) char *srch_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) void (*func)(struct mdesc_handle *, u64, int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) u64 val, int depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) u64 arc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* Since we have an estimate of recursion depth, do a sanity check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (depth == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) u64 n = mdesc_arc_target(hp, arc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) const char *name = mdesc_node_name(hp, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!strcmp(srch_val, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) (*func)(hp, n, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) find_back_node_value(hp, n, srch_val, func, val, depth-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static void __mark_core_id(struct mdesc_handle *hp, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int core_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) const u64 *id = mdesc_get_property(hp, node, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (*id < num_possible_cpus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) cpu_data(*id).core_id = core_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static void __mark_max_cache_id(struct mdesc_handle *hp, u64 node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int max_cache_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) const u64 *id = mdesc_get_property(hp, node, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (*id < num_possible_cpus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) cpu_data(*id).max_cache_id = max_cache_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * On systems without explicit socket descriptions socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * is max_cache_id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) cpu_data(*id).sock_id = max_cache_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) int core_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static void mark_max_cache_ids(struct mdesc_handle *hp, u64 mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) int max_cache_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) find_back_node_value(hp, mp, "cpu", __mark_max_cache_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) max_cache_id, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static void set_core_ids(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) u64 mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /* Identify unique cores by looking for cpus backpointed to by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * level 1 instruction caches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) mdesc_for_each_node_by_name(hp, mp, "cache") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) const u64 *level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) level = mdesc_get_property(hp, mp, "level", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (*level != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) type = mdesc_get_property(hp, mp, "type", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (!of_find_in_proplist(type, "instn", len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) mark_core_ids(hp, mp, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static int set_max_cache_ids_by_cache(struct mdesc_handle *hp, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) u64 mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int fnd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * Identify unique highest level of shared cache by looking for cpus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * backpointed to by shared level N caches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) mdesc_for_each_node_by_name(hp, mp, "cache") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) const u64 *cur_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (*cur_lvl != level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) mark_max_cache_ids(hp, mp, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) fnd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return fnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) int idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mdesc_for_each_node_by_name(hp, mp, "socket") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) u64 a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) u64 t = mdesc_arc_target(hp, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) const u64 *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) name = mdesc_node_name(hp, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (strcmp(name, "cpu"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) id = mdesc_get_property(hp, t, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (*id < num_possible_cpus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) cpu_data(*id).sock_id = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) static void set_sock_ids(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) u64 mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * Find the highest level of shared cache which pre-T7 is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * the socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (!set_max_cache_ids_by_cache(hp, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) set_max_cache_ids_by_cache(hp, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* If machine description exposes sockets data use it.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (mp != MDESC_NODE_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) set_sock_ids_by_socket(hp, mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) u64 a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) u64 t = mdesc_arc_target(hp, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) const u64 *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) name = mdesc_node_name(hp, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (strcmp(name, "cpu"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) id = mdesc_get_property(hp, t, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (*id < NR_CPUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) cpu_data(*id).proc_id = proc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) u64 mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) type = mdesc_get_property(hp, mp, "type", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (!of_find_in_proplist(type, "int", len) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) !of_find_in_proplist(type, "integer", len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) mark_proc_ids(hp, mp, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static void set_proc_ids(struct mdesc_handle *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) __set_proc_ids(hp, "exec_unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) __set_proc_ids(hp, "exec-unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static void get_one_mondo_bits(const u64 *p, unsigned int *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) unsigned long def, unsigned long max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) goto use_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) val = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!val || val >= 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) goto use_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (val > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) val = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) *mask = ((1U << val) * 64U) - 1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) use_default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) *mask = ((1U << def) * 64U) - 1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static void get_mondo_data(struct mdesc_handle *hp, u64 mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct trap_per_cpu *tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) static int printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) const u64 *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!printed++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) pr_info("SUN4V: Mondo queue sizes "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) "[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) tb->cpu_mondo_qmask + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) tb->dev_mondo_qmask + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) tb->resum_qmask + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) tb->nonresum_qmask + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static void *mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct mdesc_handle *hp = mdesc_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) void *ret = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) u64 mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) mdesc_for_each_node_by_name(hp, mp, "cpu") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) int cpuid = *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (cpuid >= NR_CPUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) printk(KERN_WARNING "Ignoring CPU %d which is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) ">= NR_CPUS (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) cpuid, NR_CPUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!cpumask_test_cpu(cpuid, mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ret = func(hp, mp, cpuid, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) mdesc_release(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static void *record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ncpus_probed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) set_cpu_present(cpuid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) void mdesc_populate_present_mask(cpumask_t *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (tlb_type != hypervisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) ncpus_probed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) unsigned long *pgsz_mask = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (pgsz_prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) val = *pgsz_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (!*pgsz_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) *pgsz_mask = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) *pgsz_mask &= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) *pgsz_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) static void *fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct trap_per_cpu *tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) cpuinfo_sparc *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) u64 a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) #ifndef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) /* On uniprocessor we only want the values for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * real physical cpu the kernel booted onto, however
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * cpu_data() only has one entry at index 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (cpuid != real_hard_smp_processor_id())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) cpuid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) c = &cpu_data(cpuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) c->clock_tick = *cfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) tb = &trap_block[cpuid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) get_mondo_data(hp, mp, tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) u64 j, t = mdesc_arc_target(hp, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) const char *t_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) t_name = mdesc_node_name(hp, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (!strcmp(t_name, "cache")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) fill_in_one_cache(c, hp, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) u64 n = mdesc_arc_target(hp, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) const char *n_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) n_name = mdesc_node_name(hp, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (!strcmp(n_name, "cache"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) fill_in_one_cache(c, hp, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) c->core_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) c->proc_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) void mdesc_fill_in_cpu_data(cpumask_t *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) hp = mdesc_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) set_core_ids(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) set_proc_ids(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) set_sock_ids(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) mdesc_release(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) smp_fill_in_sib_core_maps();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) /* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * opened. Hold this reference until /dev/mdesc is closed to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * mdesc data structure is not released underneath us. Store the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * pointer to mdesc structure in private_data for read and seek to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static int mdesc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct mdesc_handle *hp = mdesc_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (!hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) file->private_data = hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static ssize_t mdesc_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) size_t len, loff_t *offp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) struct mdesc_handle *hp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) unsigned char *mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) int bytes_left, count = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (*offp >= hp->handle_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) bytes_left = hp->handle_size - *offp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (count > bytes_left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) count = bytes_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) mdesc = (unsigned char *)&hp->mdesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) mdesc += *offp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (!copy_to_user(buf, mdesc, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) *offp += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct mdesc_handle *hp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return no_seek_end_llseek_size(file, offset, whence, hp->handle_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /* mdesc_close() - /dev/mdesc is being closed, release the reference to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * mdesc structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static int mdesc_close(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) mdesc_release(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static const struct file_operations mdesc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .open = mdesc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .read = mdesc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .llseek = mdesc_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .release = mdesc_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static struct miscdevice mdesc_misc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .minor = MISC_DYNAMIC_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) .name = "mdesc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) .fops = &mdesc_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int __init mdesc_misc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return misc_register(&mdesc_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) __initcall(mdesc_misc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) void __init sun4v_mdesc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) unsigned long len, real_len, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) (void) sun4v_mach_desc(0UL, 0UL, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) printk("MDESC: Size is %lu bytes.\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) hp = mdesc_alloc(len, &memblock_mdesc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (hp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) prom_halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (status != HV_EOK || real_len > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) prom_printf("sun4v_mach_desc fails, err(%lu), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) "len(%lu), real_len(%lu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) status, len, real_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) mdesc_free(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) prom_halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) cur_mdesc = hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) mdesc_adi_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) report_platform_properties();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }