root/arch/powerpc/platforms/pseries/nvram.c

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

DEFINITIONS

This source file includes following definitions.
  1. pSeries_nvram_read
  2. pSeries_nvram_write
  3. pSeries_nvram_get_size
  4. nvram_write_error_log
  5. nvram_read_error_log
  6. nvram_clear_error_log
  7. clobbering_unread_rtas_event
  8. pseries_nvram_init_log_partitions
  9. pSeries_nvram_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  c 2001 PPC 64 Team, IBM Corp
   4  *
   5  * /dev/nvram driver for PPC64
   6  */
   7 
   8 
   9 #include <linux/types.h>
  10 #include <linux/errno.h>
  11 #include <linux/init.h>
  12 #include <linux/spinlock.h>
  13 #include <linux/slab.h>
  14 #include <linux/ctype.h>
  15 #include <linux/uaccess.h>
  16 #include <asm/nvram.h>
  17 #include <asm/rtas.h>
  18 #include <asm/prom.h>
  19 #include <asm/machdep.h>
  20 
  21 /* Max bytes to read/write in one go */
  22 #define NVRW_CNT 0x20
  23 
  24 static unsigned int nvram_size;
  25 static int nvram_fetch, nvram_store;
  26 static char nvram_buf[NVRW_CNT];        /* assume this is in the first 4GB */
  27 static DEFINE_SPINLOCK(nvram_lock);
  28 
  29 /* See clobbering_unread_rtas_event() */
  30 #define NVRAM_RTAS_READ_TIMEOUT 5               /* seconds */
  31 static time64_t last_unread_rtas_event;         /* timestamp */
  32 
  33 #ifdef CONFIG_PSTORE
  34 time64_t last_rtas_event;
  35 #endif
  36 
  37 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
  38 {
  39         unsigned int i;
  40         unsigned long len;
  41         int done;
  42         unsigned long flags;
  43         char *p = buf;
  44 
  45 
  46         if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
  47                 return -ENODEV;
  48 
  49         if (*index >= nvram_size)
  50                 return 0;
  51 
  52         i = *index;
  53         if (i + count > nvram_size)
  54                 count = nvram_size - i;
  55 
  56         spin_lock_irqsave(&nvram_lock, flags);
  57 
  58         for (; count != 0; count -= len) {
  59                 len = count;
  60                 if (len > NVRW_CNT)
  61                         len = NVRW_CNT;
  62                 
  63                 if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
  64                                len) != 0) || len != done) {
  65                         spin_unlock_irqrestore(&nvram_lock, flags);
  66                         return -EIO;
  67                 }
  68                 
  69                 memcpy(p, nvram_buf, len);
  70 
  71                 p += len;
  72                 i += len;
  73         }
  74 
  75         spin_unlock_irqrestore(&nvram_lock, flags);
  76         
  77         *index = i;
  78         return p - buf;
  79 }
  80 
  81 static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index)
  82 {
  83         unsigned int i;
  84         unsigned long len;
  85         int done;
  86         unsigned long flags;
  87         const char *p = buf;
  88 
  89         if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE)
  90                 return -ENODEV;
  91 
  92         if (*index >= nvram_size)
  93                 return 0;
  94 
  95         i = *index;
  96         if (i + count > nvram_size)
  97                 count = nvram_size - i;
  98 
  99         spin_lock_irqsave(&nvram_lock, flags);
 100 
 101         for (; count != 0; count -= len) {
 102                 len = count;
 103                 if (len > NVRW_CNT)
 104                         len = NVRW_CNT;
 105 
 106                 memcpy(nvram_buf, p, len);
 107 
 108                 if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf),
 109                                len) != 0) || len != done) {
 110                         spin_unlock_irqrestore(&nvram_lock, flags);
 111                         return -EIO;
 112                 }
 113                 
 114                 p += len;
 115                 i += len;
 116         }
 117         spin_unlock_irqrestore(&nvram_lock, flags);
 118         
 119         *index = i;
 120         return p - buf;
 121 }
 122 
 123 static ssize_t pSeries_nvram_get_size(void)
 124 {
 125         return nvram_size ? nvram_size : -ENODEV;
 126 }
 127 
 128 /* nvram_write_error_log
 129  *
 130  * We need to buffer the error logs into nvram to ensure that we have
 131  * the failure information to decode.
 132  */
 133 int nvram_write_error_log(char * buff, int length,
 134                           unsigned int err_type, unsigned int error_log_cnt)
 135 {
 136         int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
 137                                                 err_type, error_log_cnt);
 138         if (!rc) {
 139                 last_unread_rtas_event = ktime_get_real_seconds();
 140 #ifdef CONFIG_PSTORE
 141                 last_rtas_event = ktime_get_real_seconds();
 142 #endif
 143         }
 144 
 145         return rc;
 146 }
 147 
 148 /* nvram_read_error_log
 149  *
 150  * Reads nvram for error log for at most 'length'
 151  */
 152 int nvram_read_error_log(char *buff, int length,
 153                         unsigned int *err_type, unsigned int *error_log_cnt)
 154 {
 155         return nvram_read_partition(&rtas_log_partition, buff, length,
 156                                                 err_type, error_log_cnt);
 157 }
 158 
 159 /* This doesn't actually zero anything, but it sets the event_logged
 160  * word to tell that this event is safely in syslog.
 161  */
 162 int nvram_clear_error_log(void)
 163 {
 164         loff_t tmp_index;
 165         int clear_word = ERR_FLAG_ALREADY_LOGGED;
 166         int rc;
 167 
 168         if (rtas_log_partition.index == -1)
 169                 return -1;
 170 
 171         tmp_index = rtas_log_partition.index;
 172         
 173         rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
 174         if (rc <= 0) {
 175                 printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
 176                 return rc;
 177         }
 178         last_unread_rtas_event = 0;
 179 
 180         return 0;
 181 }
 182 
 183 /*
 184  * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
 185  * would logging this oops/panic overwrite an RTAS event that rtas_errd
 186  * hasn't had a chance to read and process?  Return 1 if so, else 0.
 187  *
 188  * We assume that if rtas_errd hasn't read the RTAS event in
 189  * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
 190  */
 191 int clobbering_unread_rtas_event(void)
 192 {
 193         return (oops_log_partition.index == rtas_log_partition.index
 194                 && last_unread_rtas_event
 195                 && ktime_get_real_seconds() - last_unread_rtas_event <=
 196                                                 NVRAM_RTAS_READ_TIMEOUT);
 197 }
 198 
 199 static int __init pseries_nvram_init_log_partitions(void)
 200 {
 201         int rc;
 202 
 203         /* Scan nvram for partitions */
 204         nvram_scan_partitions();
 205 
 206         rc = nvram_init_os_partition(&rtas_log_partition);
 207         nvram_init_oops_partition(rc == 0);
 208         return 0;
 209 }
 210 machine_arch_initcall(pseries, pseries_nvram_init_log_partitions);
 211 
 212 int __init pSeries_nvram_init(void)
 213 {
 214         struct device_node *nvram;
 215         const __be32 *nbytes_p;
 216         unsigned int proplen;
 217 
 218         nvram = of_find_node_by_type(NULL, "nvram");
 219         if (nvram == NULL)
 220                 return -ENODEV;
 221 
 222         nbytes_p = of_get_property(nvram, "#bytes", &proplen);
 223         if (nbytes_p == NULL || proplen != sizeof(unsigned int)) {
 224                 of_node_put(nvram);
 225                 return -EIO;
 226         }
 227 
 228         nvram_size = be32_to_cpup(nbytes_p);
 229 
 230         nvram_fetch = rtas_token("nvram-fetch");
 231         nvram_store = rtas_token("nvram-store");
 232         printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size);
 233         of_node_put(nvram);
 234 
 235         ppc_md.nvram_read       = pSeries_nvram_read;
 236         ppc_md.nvram_write      = pSeries_nvram_write;
 237         ppc_md.nvram_size       = pSeries_nvram_get_size;
 238 
 239         return 0;
 240 }
 241 

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