]> Git Repo - linux.git/blob - arch/x86/platform/uv/bios_uv.c
enetc: Migrate to PHYLINK and PCS_LYNX
[linux.git] / arch / x86 / platform / uv / bios_uv.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * BIOS run time interface routines.
4  *
5  *  Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
6  *  Copyright (c) Russ Anderson <[email protected]>
7  */
8
9 #include <linux/efi.h>
10 #include <linux/export.h>
11 #include <linux/slab.h>
12 #include <asm/efi.h>
13 #include <linux/io.h>
14 #include <asm/pgalloc.h>
15 #include <asm/uv/bios.h>
16 #include <asm/uv/uv_hub.h>
17
18 unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR;
19
20 struct uv_systab *uv_systab;
21
22 static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
23                         u64 a4, u64 a5)
24 {
25         struct uv_systab *tab = uv_systab;
26         s64 ret;
27
28         if (!tab || !tab->function)
29                 /*
30                  * BIOS does not support UV systab
31                  */
32                 return BIOS_STATUS_UNIMPLEMENTED;
33
34         ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5);
35
36         return ret;
37 }
38
39 static s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4,
40                 u64 a5)
41 {
42         s64 ret;
43
44         if (down_interruptible(&__efi_uv_runtime_lock))
45                 return BIOS_STATUS_ABORT;
46
47         ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
48         up(&__efi_uv_runtime_lock);
49
50         return ret;
51 }
52
53 static s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
54                 u64 a4, u64 a5)
55 {
56         unsigned long bios_flags;
57         s64 ret;
58
59         if (down_interruptible(&__efi_uv_runtime_lock))
60                 return BIOS_STATUS_ABORT;
61
62         local_irq_save(bios_flags);
63         ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
64         local_irq_restore(bios_flags);
65
66         up(&__efi_uv_runtime_lock);
67
68         return ret;
69 }
70
71 long sn_partition_id;
72 EXPORT_SYMBOL_GPL(sn_partition_id);
73 long sn_coherency_id;
74 long sn_region_size;
75 EXPORT_SYMBOL_GPL(sn_region_size);
76 long system_serial_number;
77 int uv_type;
78
79 s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher,
80                 long *region, long *ssn)
81 {
82         s64 ret;
83         u64 v0, v1;
84         union partition_info_u part;
85
86         ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc,
87                                 (u64)(&v0), (u64)(&v1), 0, 0);
88         if (ret != BIOS_STATUS_SUCCESS)
89                 return ret;
90
91         part.val = v0;
92         if (uvtype)
93                 *uvtype = part.hub_version;
94         if (partid)
95                 *partid = part.partition_id;
96         if (coher)
97                 *coher = part.coherence_id;
98         if (region)
99                 *region = part.region_size;
100         if (ssn)
101                 *ssn = v1;
102         return ret;
103 }
104
105 int
106 uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size,
107                            unsigned long *intr_mmr_offset)
108 {
109         u64 watchlist;
110         s64 ret;
111
112         /*
113          * bios returns watchlist number or negative error number.
114          */
115         ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr,
116                         mq_size, (u64)intr_mmr_offset,
117                         (u64)&watchlist, 0);
118         if (ret < BIOS_STATUS_SUCCESS)
119                 return ret;
120
121         return watchlist;
122 }
123 EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_alloc);
124
125 int
126 uv_bios_mq_watchlist_free(int blade, int watchlist_num)
127 {
128         return (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_FREE,
129                                 blade, watchlist_num, 0, 0, 0);
130 }
131 EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_free);
132
133 s64
134 uv_bios_change_memprotect(u64 paddr, u64 len, enum uv_memprotect perms)
135 {
136         return uv_bios_call_irqsave(UV_BIOS_MEMPROTECT, paddr, len,
137                                         perms, 0, 0);
138 }
139 EXPORT_SYMBOL_GPL(uv_bios_change_memprotect);
140
141 s64
142 uv_bios_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
143 {
144         return uv_bios_call_irqsave(UV_BIOS_GET_PARTITION_ADDR, (u64)cookie,
145                                     (u64)addr, buf, (u64)len, 0);
146 }
147 EXPORT_SYMBOL_GPL(uv_bios_reserved_page_pa);
148
149 s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second)
150 {
151         return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type,
152                            (u64)ticks_per_second, 0, 0, 0);
153 }
154
155 /*
156  * uv_bios_set_legacy_vga_target - Set Legacy VGA I/O Target
157  * @decode: true to enable target, false to disable target
158  * @domain: PCI domain number
159  * @bus: PCI bus number
160  *
161  * Returns:
162  *    0: Success
163  *    -EINVAL: Invalid domain or bus number
164  *    -ENOSYS: Capability not available
165  *    -EBUSY: Legacy VGA I/O cannot be retargeted at this time
166  */
167 int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
168 {
169         return uv_bios_call(UV_BIOS_SET_LEGACY_VGA_TARGET,
170                                 (u64)decode, (u64)domain, (u64)bus, 0, 0);
171 }
172
173 int uv_bios_init(void)
174 {
175         uv_systab = NULL;
176         if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||
177             !uv_systab_phys || efi_runtime_disabled()) {
178                 pr_crit("UV: UVsystab: missing\n");
179                 return -EEXIST;
180         }
181
182         uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab));
183         if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
184                 pr_err("UV: UVsystab: bad signature!\n");
185                 iounmap(uv_systab);
186                 return -EINVAL;
187         }
188
189         /* Starting with UV4 the UV systab size is variable */
190         if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) {
191                 int size = uv_systab->size;
192
193                 iounmap(uv_systab);
194                 uv_systab = ioremap(uv_systab_phys, size);
195                 if (!uv_systab) {
196                         pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
197                         return -EFAULT;
198                 }
199         }
200         pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision);
201         return 0;
202 }
This page took 0.045995 seconds and 4 git commands to generate.