root/arch/ia64/kernel/esi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. esi_init
  2. ia64_esi_call
  3. ia64_esi_call_phys
  4. esi_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   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 
  16 MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
  17 MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
  18 MODULE_LICENSE("GPL");
  19 
  20 #define MODULE_NAME     "esi"
  21 
  22 #define ESI_TABLE_GUID                                  \
  23     EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3,          \
  24              0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
  25 
  26 enum esi_systab_entry_type {
  27         ESI_DESC_ENTRY_POINT = 0
  28 };
  29 
  30 /*
  31  * Entry type:  Size:
  32  *      0       48
  33  */
  34 #define ESI_DESC_SIZE(type)     "\060"[(unsigned) (type)]
  35 
  36 typedef struct ia64_esi_desc_entry_point {
  37         u8 type;
  38         u8 reserved1[15];
  39         u64 esi_proc;
  40         u64 gp;
  41         efi_guid_t guid;
  42 } ia64_esi_desc_entry_point_t;
  43 
  44 struct pdesc {
  45         void *addr;
  46         void *gp;
  47 };
  48 
  49 static struct ia64_sal_systab *esi_systab;
  50 
  51 static int __init esi_init (void)
  52 {
  53         efi_config_table_t *config_tables;
  54         struct ia64_sal_systab *systab;
  55         unsigned long esi = 0;
  56         char *p;
  57         int i;
  58 
  59         config_tables = __va(efi.systab->tables);
  60 
  61         for (i = 0; i < (int) efi.systab->nr_tables; ++i) {
  62                 if (efi_guidcmp(config_tables[i].guid, ESI_TABLE_GUID) == 0) {
  63                         esi = config_tables[i].table;
  64                         break;
  65                 }
  66         }
  67 
  68         if (!esi)
  69                 return -ENODEV;
  70 
  71         systab = __va(esi);
  72 
  73         if (strncmp(systab->signature, "ESIT", 4) != 0) {
  74                 printk(KERN_ERR "bad signature in ESI system table!");
  75                 return -ENODEV;
  76         }
  77 
  78         p = (char *) (systab + 1);
  79         for (i = 0; i < systab->entry_count; i++) {
  80                 /*
  81                  * The first byte of each entry type contains the type
  82                  * descriptor.
  83                  */
  84                 switch (*p) {
  85                       case ESI_DESC_ENTRY_POINT:
  86                         break;
  87                       default:
  88                         printk(KERN_WARNING "Unknown table type %d found in "
  89                                "ESI table, ignoring rest of table\n", *p);
  90                         return -ENODEV;
  91                 }
  92 
  93                 p += ESI_DESC_SIZE(*p);
  94         }
  95 
  96         esi_systab = systab;
  97         return 0;
  98 }
  99 
 100 
 101 int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
 102                    enum esi_proc_type proc_type, u64 func,
 103                    u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
 104                    u64 arg7)
 105 {
 106         struct ia64_fpreg fr[6];
 107         unsigned long flags = 0;
 108         int i;
 109         char *p;
 110 
 111         if (!esi_systab)
 112                 return -1;
 113 
 114         p = (char *) (esi_systab + 1);
 115         for (i = 0; i < esi_systab->entry_count; i++) {
 116                 if (*p == ESI_DESC_ENTRY_POINT) {
 117                         ia64_esi_desc_entry_point_t *esi = (void *)p;
 118                         if (!efi_guidcmp(guid, esi->guid)) {
 119                                 ia64_sal_handler esi_proc;
 120                                 struct pdesc pdesc;
 121 
 122                                 pdesc.addr = __va(esi->esi_proc);
 123                                 pdesc.gp = __va(esi->gp);
 124 
 125                                 esi_proc = (ia64_sal_handler) &pdesc;
 126 
 127                                 ia64_save_scratch_fpregs(fr);
 128                                 if (proc_type == ESI_PROC_SERIALIZED)
 129                                         spin_lock_irqsave(&sal_lock, flags);
 130                                 else if (proc_type == ESI_PROC_MP_SAFE)
 131                                         local_irq_save(flags);
 132                                 else
 133                                         preempt_disable();
 134                                 *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
 135                                                      arg4, arg5, arg6, arg7);
 136                                 if (proc_type == ESI_PROC_SERIALIZED)
 137                                         spin_unlock_irqrestore(&sal_lock,
 138                                                                flags);
 139                                 else if (proc_type == ESI_PROC_MP_SAFE)
 140                                         local_irq_restore(flags);
 141                                 else
 142                                         preempt_enable();
 143                                 ia64_load_scratch_fpregs(fr);
 144                                 return 0;
 145                         }
 146                 }
 147                 p += ESI_DESC_SIZE(*p);
 148         }
 149         return -1;
 150 }
 151 EXPORT_SYMBOL_GPL(ia64_esi_call);
 152 
 153 int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
 154                         u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
 155                         u64 arg5, u64 arg6, u64 arg7)
 156 {
 157         struct ia64_fpreg fr[6];
 158         unsigned long flags;
 159         u64 esi_params[8];
 160         char *p;
 161         int i;
 162 
 163         if (!esi_systab)
 164                 return -1;
 165 
 166         p = (char *) (esi_systab + 1);
 167         for (i = 0; i < esi_systab->entry_count; i++) {
 168                 if (*p == ESI_DESC_ENTRY_POINT) {
 169                         ia64_esi_desc_entry_point_t *esi = (void *)p;
 170                         if (!efi_guidcmp(guid, esi->guid)) {
 171                                 ia64_sal_handler esi_proc;
 172                                 struct pdesc pdesc;
 173 
 174                                 pdesc.addr = (void *)esi->esi_proc;
 175                                 pdesc.gp = (void *)esi->gp;
 176 
 177                                 esi_proc = (ia64_sal_handler) &pdesc;
 178 
 179                                 esi_params[0] = func;
 180                                 esi_params[1] = arg1;
 181                                 esi_params[2] = arg2;
 182                                 esi_params[3] = arg3;
 183                                 esi_params[4] = arg4;
 184                                 esi_params[5] = arg5;
 185                                 esi_params[6] = arg6;
 186                                 esi_params[7] = arg7;
 187                                 ia64_save_scratch_fpregs(fr);
 188                                 spin_lock_irqsave(&sal_lock, flags);
 189                                 *isrvp = esi_call_phys(esi_proc, esi_params);
 190                                 spin_unlock_irqrestore(&sal_lock, flags);
 191                                 ia64_load_scratch_fpregs(fr);
 192                                 return 0;
 193                         }
 194                 }
 195                 p += ESI_DESC_SIZE(*p);
 196         }
 197         return -1;
 198 }
 199 EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
 200 
 201 static void __exit esi_exit (void)
 202 {
 203 }
 204 
 205 module_init(esi_init);
 206 module_exit(esi_exit);  /* makes module removable... */

/* [<][>][^][v][top][bottom][index][help] */