nvram.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * c 2001 PPC 64 Team, IBM Corp
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. *
  9. * /dev/nvram driver for PPC64
  10. *
  11. * This perhaps should live in drivers/char
  12. */
  13. #include <linux/types.h>
  14. #include <linux/errno.h>
  15. #include <linux/init.h>
  16. #include <linux/spinlock.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/nvram.h>
  19. #include <asm/rtas.h>
  20. #include <asm/prom.h>
  21. #include <asm/machdep.h>
  22. /* Max bytes to read/write in one go */
  23. #define NVRW_CNT 0x20
  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. static long nvram_error_log_index = -1;
  29. static long nvram_error_log_size = 0;
  30. struct err_log_info {
  31. int error_type;
  32. unsigned int seq_num;
  33. };
  34. #define NVRAM_MAX_REQ 2079
  35. #define NVRAM_MIN_REQ 1055
  36. #define NVRAM_LOG_PART_NAME "ibm,rtas-log"
  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. if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
  45. return -ENODEV;
  46. if (*index >= nvram_size)
  47. return 0;
  48. i = *index;
  49. if (i + count > nvram_size)
  50. count = nvram_size - i;
  51. spin_lock_irqsave(&nvram_lock, flags);
  52. for (; count != 0; count -= len) {
  53. len = count;
  54. if (len > NVRW_CNT)
  55. len = NVRW_CNT;
  56. if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
  57. len) != 0) || len != done) {
  58. spin_unlock_irqrestore(&nvram_lock, flags);
  59. return -EIO;
  60. }
  61. memcpy(p, nvram_buf, len);
  62. p += len;
  63. i += len;
  64. }
  65. spin_unlock_irqrestore(&nvram_lock, flags);
  66. *index = i;
  67. return p - buf;
  68. }
  69. static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index)
  70. {
  71. unsigned int i;
  72. unsigned long len;
  73. int done;
  74. unsigned long flags;
  75. const char *p = buf;
  76. if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE)
  77. return -ENODEV;
  78. if (*index >= nvram_size)
  79. return 0;
  80. i = *index;
  81. if (i + count > nvram_size)
  82. count = nvram_size - i;
  83. spin_lock_irqsave(&nvram_lock, flags);
  84. for (; count != 0; count -= len) {
  85. len = count;
  86. if (len > NVRW_CNT)
  87. len = NVRW_CNT;
  88. memcpy(nvram_buf, p, len);
  89. if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf),
  90. len) != 0) || len != done) {
  91. spin_unlock_irqrestore(&nvram_lock, flags);
  92. return -EIO;
  93. }
  94. p += len;
  95. i += len;
  96. }
  97. spin_unlock_irqrestore(&nvram_lock, flags);
  98. *index = i;
  99. return p - buf;
  100. }
  101. static ssize_t pSeries_nvram_get_size(void)
  102. {
  103. return nvram_size ? nvram_size : -ENODEV;
  104. }
  105. /* nvram_write_error_log
  106. *
  107. * We need to buffer the error logs into nvram to ensure that we have
  108. * the failure information to decode. If we have a severe error there
  109. * is no way to guarantee that the OS or the machine is in a state to
  110. * get back to user land and write the error to disk. For example if
  111. * the SCSI device driver causes a Machine Check by writing to a bad
  112. * IO address, there is no way of guaranteeing that the device driver
  113. * is in any state that is would also be able to write the error data
  114. * captured to disk, thus we buffer it in NVRAM for analysis on the
  115. * next boot.
  116. *
  117. * In NVRAM the partition containing the error log buffer will looks like:
  118. * Header (in bytes):
  119. * +-----------+----------+--------+------------+------------------+
  120. * | signature | checksum | length | name | data |
  121. * |0 |1 |2 3|4 15|16 length-1|
  122. * +-----------+----------+--------+------------+------------------+
  123. *
  124. * The 'data' section would look like (in bytes):
  125. * +--------------+------------+-----------------------------------+
  126. * | event_logged | sequence # | error log |
  127. * |0 3|4 7|8 nvram_error_log_size-1|
  128. * +--------------+------------+-----------------------------------+
  129. *
  130. * event_logged: 0 if event has not been logged to syslog, 1 if it has
  131. * sequence #: The unique sequence # for each event. (until it wraps)
  132. * error log: The error log from event_scan
  133. */
  134. int nvram_write_error_log(char * buff, int length,
  135. unsigned int err_type, unsigned int error_log_cnt)
  136. {
  137. int rc;
  138. loff_t tmp_index;
  139. struct err_log_info info;
  140. if (nvram_error_log_index == -1) {
  141. return -ESPIPE;
  142. }
  143. if (length > nvram_error_log_size) {
  144. length = nvram_error_log_size;
  145. }
  146. info.error_type = err_type;
  147. info.seq_num = error_log_cnt;
  148. tmp_index = nvram_error_log_index;
  149. rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
  150. if (rc <= 0) {
  151. printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
  152. return rc;
  153. }
  154. rc = ppc_md.nvram_write(buff, length, &tmp_index);
  155. if (rc <= 0) {
  156. printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
  157. return rc;
  158. }
  159. return 0;
  160. }
  161. /* nvram_read_error_log
  162. *
  163. * Reads nvram for error log for at most 'length'
  164. */
  165. int nvram_read_error_log(char * buff, int length,
  166. unsigned int * err_type, unsigned int * error_log_cnt)
  167. {
  168. int rc;
  169. loff_t tmp_index;
  170. struct err_log_info info;
  171. if (nvram_error_log_index == -1)
  172. return -1;
  173. if (length > nvram_error_log_size)
  174. length = nvram_error_log_size;
  175. tmp_index = nvram_error_log_index;
  176. rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
  177. if (rc <= 0) {
  178. printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
  179. return rc;
  180. }
  181. rc = ppc_md.nvram_read(buff, length, &tmp_index);
  182. if (rc <= 0) {
  183. printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
  184. return rc;
  185. }
  186. *error_log_cnt = info.seq_num;
  187. *err_type = info.error_type;
  188. return 0;
  189. }
  190. /* This doesn't actually zero anything, but it sets the event_logged
  191. * word to tell that this event is safely in syslog.
  192. */
  193. int nvram_clear_error_log(void)
  194. {
  195. loff_t tmp_index;
  196. int clear_word = ERR_FLAG_ALREADY_LOGGED;
  197. int rc;
  198. if (nvram_error_log_index == -1)
  199. return -1;
  200. tmp_index = nvram_error_log_index;
  201. rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
  202. if (rc <= 0) {
  203. printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
  204. return rc;
  205. }
  206. return 0;
  207. }
  208. /* pseries_nvram_init_log_partition
  209. *
  210. * This will setup the partition we need for buffering the
  211. * error logs and cleanup partitions if needed.
  212. *
  213. * The general strategy is the following:
  214. * 1.) If there is log partition large enough then use it.
  215. * 2.) If there is none large enough, search
  216. * for a free partition that is large enough.
  217. * 3.) If there is not a free partition large enough remove
  218. * _all_ OS partitions and consolidate the space.
  219. * 4.) Will first try getting a chunk that will satisfy the maximum
  220. * error log size (NVRAM_MAX_REQ).
  221. * 5.) If the max chunk cannot be allocated then try finding a chunk
  222. * that will satisfy the minum needed (NVRAM_MIN_REQ).
  223. */
  224. static int __init pseries_nvram_init_log_partition(void)
  225. {
  226. loff_t p;
  227. int size;
  228. /* Scan nvram for partitions */
  229. nvram_scan_partitions();
  230. /* Lookg for ours */
  231. p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
  232. /* Found one but too small, remove it */
  233. if (p && size < NVRAM_MIN_REQ) {
  234. pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
  235. ",removing it...");
  236. nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
  237. p = 0;
  238. }
  239. /* Create one if we didn't find */
  240. if (!p) {
  241. p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
  242. NVRAM_MAX_REQ, NVRAM_MIN_REQ);
  243. /* No room for it, try to get rid of any OS partition
  244. * and try again
  245. */
  246. if (p == -ENOSPC) {
  247. pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
  248. " partition, deleting all OS partitions...");
  249. nvram_remove_partition(NULL, NVRAM_SIG_OS);
  250. p = nvram_create_partition(NVRAM_LOG_PART_NAME,
  251. NVRAM_SIG_OS, NVRAM_MAX_REQ,
  252. NVRAM_MIN_REQ);
  253. }
  254. }
  255. if (p <= 0) {
  256. pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
  257. " partition, err %d\n", (int)p);
  258. return 0;
  259. }
  260. nvram_error_log_index = p;
  261. nvram_error_log_size = nvram_get_partition_size(p) -
  262. sizeof(struct err_log_info);
  263. return 0;
  264. }
  265. machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
  266. int __init pSeries_nvram_init(void)
  267. {
  268. struct device_node *nvram;
  269. const unsigned int *nbytes_p;
  270. unsigned int proplen;
  271. nvram = of_find_node_by_type(NULL, "nvram");
  272. if (nvram == NULL)
  273. return -ENODEV;
  274. nbytes_p = of_get_property(nvram, "#bytes", &proplen);
  275. if (nbytes_p == NULL || proplen != sizeof(unsigned int)) {
  276. of_node_put(nvram);
  277. return -EIO;
  278. }
  279. nvram_size = *nbytes_p;
  280. nvram_fetch = rtas_token("nvram-fetch");
  281. nvram_store = rtas_token("nvram-store");
  282. printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size);
  283. of_node_put(nvram);
  284. ppc_md.nvram_read = pSeries_nvram_read;
  285. ppc_md.nvram_write = pSeries_nvram_write;
  286. ppc_md.nvram_size = pSeries_nvram_get_size;
  287. return 0;
  288. }