]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/ia64/kernel/esi.c
Merge tag 'drm-next-2020-10-23' of git://anongit.freedesktop.org/drm/drm
[mirror_ubuntu-hirsute-kernel.git] / arch / ia64 / kernel / esi.c
CommitLineData
09c434b8 1// SPDX-License-Identifier: GPL-2.0-only
2ab561a1
DMT
2/*
3 * Extensible SAL Interface (ESI) support routines.
4 *
5 * Copyright (C) 2006 Hewlett-Packard Co
6 * Alex Williamson <alex.williamson@hp.com>
7 */
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/string.h>
12
13#include <asm/esi.h>
14#include <asm/sal.h>
15
16MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
17MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
18MODULE_LICENSE("GPL");
19
20#define MODULE_NAME "esi"
21
2ab561a1
DMT
22enum esi_systab_entry_type {
23 ESI_DESC_ENTRY_POINT = 0
24};
25
26/*
27 * Entry type: Size:
28 * 0 48
29 */
30#define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
31
32typedef struct ia64_esi_desc_entry_point {
33 u8 type;
34 u8 reserved1[15];
35 u64 esi_proc;
36 u64 gp;
37 efi_guid_t guid;
38} ia64_esi_desc_entry_point_t;
39
40struct pdesc {
41 void *addr;
42 void *gp;
43};
44
45static struct ia64_sal_systab *esi_systab;
46
c0019f57
AB
47extern unsigned long esi_phys;
48
2ab561a1
DMT
49static int __init esi_init (void)
50{
2ab561a1 51 struct ia64_sal_systab *systab;
2ab561a1
DMT
52 char *p;
53 int i;
54
c0019f57 55 if (esi_phys == EFI_INVALID_TABLE_ADDR)
58782b34 56 return -ENODEV;
2ab561a1 57
c0019f57 58 systab = __va(esi_phys);
2ab561a1
DMT
59
60 if (strncmp(systab->signature, "ESIT", 4) != 0) {
61 printk(KERN_ERR "bad signature in ESI system table!");
62 return -ENODEV;
63 }
64
65 p = (char *) (systab + 1);
66 for (i = 0; i < systab->entry_count; i++) {
67 /*
68 * The first byte of each entry type contains the type
69 * descriptor.
70 */
71 switch (*p) {
72 case ESI_DESC_ENTRY_POINT:
73 break;
74 default:
af901ca1 75 printk(KERN_WARNING "Unknown table type %d found in "
2ab561a1
DMT
76 "ESI table, ignoring rest of table\n", *p);
77 return -ENODEV;
78 }
79
80 p += ESI_DESC_SIZE(*p);
81 }
82
83 esi_systab = systab;
84 return 0;
85}
86
87
88int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
89 enum esi_proc_type proc_type, u64 func,
90 u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
91 u64 arg7)
92{
93 struct ia64_fpreg fr[6];
94 unsigned long flags = 0;
95 int i;
96 char *p;
97
98 if (!esi_systab)
99 return -1;
100
101 p = (char *) (esi_systab + 1);
102 for (i = 0; i < esi_systab->entry_count; i++) {
103 if (*p == ESI_DESC_ENTRY_POINT) {
104 ia64_esi_desc_entry_point_t *esi = (void *)p;
105 if (!efi_guidcmp(guid, esi->guid)) {
106 ia64_sal_handler esi_proc;
107 struct pdesc pdesc;
108
109 pdesc.addr = __va(esi->esi_proc);
110 pdesc.gp = __va(esi->gp);
111
112 esi_proc = (ia64_sal_handler) &pdesc;
113
114 ia64_save_scratch_fpregs(fr);
115 if (proc_type == ESI_PROC_SERIALIZED)
116 spin_lock_irqsave(&sal_lock, flags);
117 else if (proc_type == ESI_PROC_MP_SAFE)
118 local_irq_save(flags);
119 else
120 preempt_disable();
121 *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
122 arg4, arg5, arg6, arg7);
123 if (proc_type == ESI_PROC_SERIALIZED)
124 spin_unlock_irqrestore(&sal_lock,
125 flags);
126 else if (proc_type == ESI_PROC_MP_SAFE)
127 local_irq_restore(flags);
128 else
129 preempt_enable();
130 ia64_load_scratch_fpregs(fr);
131 return 0;
132 }
133 }
134 p += ESI_DESC_SIZE(*p);
135 }
136 return -1;
137}
138EXPORT_SYMBOL_GPL(ia64_esi_call);
139
140int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
141 u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
142 u64 arg5, u64 arg6, u64 arg7)
143{
144 struct ia64_fpreg fr[6];
145 unsigned long flags;
146 u64 esi_params[8];
147 char *p;
148 int i;
149
150 if (!esi_systab)
151 return -1;
152
153 p = (char *) (esi_systab + 1);
154 for (i = 0; i < esi_systab->entry_count; i++) {
155 if (*p == ESI_DESC_ENTRY_POINT) {
156 ia64_esi_desc_entry_point_t *esi = (void *)p;
157 if (!efi_guidcmp(guid, esi->guid)) {
158 ia64_sal_handler esi_proc;
159 struct pdesc pdesc;
160
161 pdesc.addr = (void *)esi->esi_proc;
162 pdesc.gp = (void *)esi->gp;
163
164 esi_proc = (ia64_sal_handler) &pdesc;
165
166 esi_params[0] = func;
167 esi_params[1] = arg1;
168 esi_params[2] = arg2;
169 esi_params[3] = arg3;
170 esi_params[4] = arg4;
171 esi_params[5] = arg5;
172 esi_params[6] = arg6;
173 esi_params[7] = arg7;
174 ia64_save_scratch_fpregs(fr);
175 spin_lock_irqsave(&sal_lock, flags);
176 *isrvp = esi_call_phys(esi_proc, esi_params);
177 spin_unlock_irqrestore(&sal_lock, flags);
178 ia64_load_scratch_fpregs(fr);
179 return 0;
180 }
181 }
182 p += ESI_DESC_SIZE(*p);
183 }
184 return -1;
185}
186EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
187
188static void __exit esi_exit (void)
189{
190}
191
192module_init(esi_init);
193module_exit(esi_exit); /* makes module removable... */