diff options
author | Anton Blanchard <anton@samba.org> | 2012-03-21 11:47:07 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-03-27 20:31:58 -0400 |
commit | 6431f20879e338306b997cd75a36824cf9d6e687 (patch) | |
tree | 3ae6dd6a4347861b1834ea6b612ae686d23e0c1e /arch/powerpc | |
parent | 1a5c2e63f497bdb5912138888053a02870ed1153 (diff) |
powerpc: Make function that parses RTAS error logs global
The IO event interrupt code has a function that finds specific
sections in an RTAS error log. We want to use it in the EPOW
code so make it global.
Rename things to make it less cryptic:
find_xelog_section() -> get_pseries_errorlog()
struct pseries_elog_section -> struct pseries_errorlog
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/rtas.h | 33 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 34 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/io_event_irq.c | 68 |
3 files changed, 69 insertions, 66 deletions
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 01c143bb77ae..a01fa3eee6bd 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
@@ -204,6 +204,39 @@ struct rtas_ext_event_log_v6 { | |||
204 | /* Variable length. */ | 204 | /* Variable length. */ |
205 | }; | 205 | }; |
206 | 206 | ||
207 | /* pSeries event log format */ | ||
208 | |||
209 | /* Two bytes ASCII section IDs */ | ||
210 | #define PSERIES_ELOG_SECT_ID_PRIV_HDR (('P' << 8) | 'H') | ||
211 | #define PSERIES_ELOG_SECT_ID_USER_HDR (('U' << 8) | 'H') | ||
212 | #define PSERIES_ELOG_SECT_ID_PRIMARY_SRC (('P' << 8) | 'S') | ||
213 | #define PSERIES_ELOG_SECT_ID_EXTENDED_UH (('E' << 8) | 'H') | ||
214 | #define PSERIES_ELOG_SECT_ID_FAILING_MTMS (('M' << 8) | 'T') | ||
215 | #define PSERIES_ELOG_SECT_ID_SECONDARY_SRC (('S' << 8) | 'S') | ||
216 | #define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR (('D' << 8) | 'H') | ||
217 | #define PSERIES_ELOG_SECT_ID_FW_ERROR (('S' << 8) | 'W') | ||
218 | #define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID (('L' << 8) | 'P') | ||
219 | #define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R') | ||
220 | #define PSERIES_ELOG_SECT_ID_HMC_ID (('H' << 8) | 'M') | ||
221 | #define PSERIES_ELOG_SECT_ID_EPOW (('E' << 8) | 'P') | ||
222 | #define PSERIES_ELOG_SECT_ID_IO_EVENT (('I' << 8) | 'E') | ||
223 | #define PSERIES_ELOG_SECT_ID_MANUFACT_INFO (('M' << 8) | 'I') | ||
224 | #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') | ||
225 | #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') | ||
226 | |||
227 | /* Vendor specific Platform Event Log Format, Version 6, section header */ | ||
228 | struct pseries_errorlog { | ||
229 | uint16_t id; /* 0x00 2-byte ASCII section ID */ | ||
230 | uint16_t length; /* 0x02 Section length in bytes */ | ||
231 | uint8_t version; /* 0x04 Section version */ | ||
232 | uint8_t subtype; /* 0x05 Section subtype */ | ||
233 | uint16_t creator_component; /* 0x06 Creator component ID */ | ||
234 | uint8_t data[]; /* 0x08 Start of section data */ | ||
235 | }; | ||
236 | |||
237 | struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, | ||
238 | uint16_t section_id); | ||
239 | |||
207 | /* | 240 | /* |
208 | * This can be set by the rtas_flash module so that it can get called | 241 | * This can be set by the rtas_flash module so that it can get called |
209 | * as the absolutely last thing before the kernel terminates. | 242 | * as the absolutely last thing before the kernel terminates. |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9f843cdfee9e..4d1a7babe342 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -868,6 +868,40 @@ int rtas_ibm_suspend_me(struct rtas_args *args) | |||
868 | } | 868 | } |
869 | #endif | 869 | #endif |
870 | 870 | ||
871 | /** | ||
872 | * Find a specific pseries error log in an RTAS extended event log. | ||
873 | * @log: RTAS error/event log | ||
874 | * @section_id: two character section identifier | ||
875 | * | ||
876 | * Returns a pointer to the specified errorlog or NULL if not found. | ||
877 | */ | ||
878 | struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, | ||
879 | uint16_t section_id) | ||
880 | { | ||
881 | struct rtas_ext_event_log_v6 *ext_log = | ||
882 | (struct rtas_ext_event_log_v6 *)log->buffer; | ||
883 | struct pseries_errorlog *sect; | ||
884 | unsigned char *p, *log_end; | ||
885 | |||
886 | /* Check that we understand the format */ | ||
887 | if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) || | ||
888 | ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG || | ||
889 | ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM) | ||
890 | return NULL; | ||
891 | |||
892 | log_end = log->buffer + log->extended_log_length; | ||
893 | p = ext_log->vendor_log; | ||
894 | |||
895 | while (p < log_end) { | ||
896 | sect = (struct pseries_errorlog *)p; | ||
897 | if (sect->id == section_id) | ||
898 | return sect; | ||
899 | p += sect->length; | ||
900 | } | ||
901 | |||
902 | return NULL; | ||
903 | } | ||
904 | |||
871 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 905 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) |
872 | { | 906 | { |
873 | struct rtas_args args; | 907 | struct rtas_args args; |
diff --git a/arch/powerpc/platforms/pseries/io_event_irq.c b/arch/powerpc/platforms/pseries/io_event_irq.c index 1a709bc48ce1..ef9d9d84c7d5 100644 --- a/arch/powerpc/platforms/pseries/io_event_irq.c +++ b/arch/powerpc/platforms/pseries/io_event_irq.c | |||
@@ -63,73 +63,9 @@ EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list); | |||
63 | 63 | ||
64 | static int ioei_check_exception_token; | 64 | static int ioei_check_exception_token; |
65 | 65 | ||
66 | /* pSeries event log format */ | ||
67 | |||
68 | /* Two bytes ASCII section IDs */ | ||
69 | #define PSERIES_ELOG_SECT_ID_PRIV_HDR (('P' << 8) | 'H') | ||
70 | #define PSERIES_ELOG_SECT_ID_USER_HDR (('U' << 8) | 'H') | ||
71 | #define PSERIES_ELOG_SECT_ID_PRIMARY_SRC (('P' << 8) | 'S') | ||
72 | #define PSERIES_ELOG_SECT_ID_EXTENDED_UH (('E' << 8) | 'H') | ||
73 | #define PSERIES_ELOG_SECT_ID_FAILING_MTMS (('M' << 8) | 'T') | ||
74 | #define PSERIES_ELOG_SECT_ID_SECONDARY_SRC (('S' << 8) | 'S') | ||
75 | #define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR (('D' << 8) | 'H') | ||
76 | #define PSERIES_ELOG_SECT_ID_FW_ERROR (('S' << 8) | 'W') | ||
77 | #define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID (('L' << 8) | 'P') | ||
78 | #define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R') | ||
79 | #define PSERIES_ELOG_SECT_ID_HMC_ID (('H' << 8) | 'M') | ||
80 | #define PSERIES_ELOG_SECT_ID_EPOW (('E' << 8) | 'P') | ||
81 | #define PSERIES_ELOG_SECT_ID_IO_EVENT (('I' << 8) | 'E') | ||
82 | #define PSERIES_ELOG_SECT_ID_MANUFACT_INFO (('M' << 8) | 'I') | ||
83 | #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') | ||
84 | #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') | ||
85 | |||
86 | /* Vendor specific Platform Event Log Format, Version 6, section header */ | ||
87 | struct pseries_elog_section { | ||
88 | uint16_t id; /* 0x00 2-byte ASCII section ID */ | ||
89 | uint16_t length; /* 0x02 Section length in bytes */ | ||
90 | uint8_t version; /* 0x04 Section version */ | ||
91 | uint8_t subtype; /* 0x05 Section subtype */ | ||
92 | uint16_t creator_component; /* 0x06 Creator component ID */ | ||
93 | uint8_t data[]; /* 0x08 Start of section data */ | ||
94 | }; | ||
95 | |||
96 | static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; | 66 | static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; |
97 | 67 | ||
98 | /** | 68 | /** |
99 | * Find data portion of a specific section in RTAS extended event log. | ||
100 | * @elog: RTAS error/event log. | ||
101 | * @sect_id: secsion ID. | ||
102 | * | ||
103 | * Return: | ||
104 | * pointer to the section data of the specified section | ||
105 | * NULL if not found | ||
106 | */ | ||
107 | static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *elog, | ||
108 | uint16_t sect_id) | ||
109 | { | ||
110 | struct rtas_ext_event_log_v6 *xelog = | ||
111 | (struct rtas_ext_event_log_v6 *) elog->buffer; | ||
112 | struct pseries_elog_section *sect; | ||
113 | unsigned char *p, *log_end; | ||
114 | |||
115 | /* Check that we understand the format */ | ||
116 | if (elog->extended_log_length < sizeof(struct rtas_ext_event_log_v6) || | ||
117 | xelog->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG || | ||
118 | xelog->company_id != RTAS_V6EXT_COMPANY_ID_IBM) | ||
119 | return NULL; | ||
120 | |||
121 | log_end = elog->buffer + elog->extended_log_length; | ||
122 | p = xelog->vendor_log; | ||
123 | while (p < log_end) { | ||
124 | sect = (struct pseries_elog_section *)p; | ||
125 | if (sect->id == sect_id) | ||
126 | return sect; | ||
127 | p += sect->length; | ||
128 | } | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Find the data portion of an IO Event section from event log. | 69 | * Find the data portion of an IO Event section from event log. |
134 | * @elog: RTAS error/event log. | 70 | * @elog: RTAS error/event log. |
135 | * | 71 | * |
@@ -138,7 +74,7 @@ static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *el | |||
138 | */ | 74 | */ |
139 | static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog) | 75 | static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog) |
140 | { | 76 | { |
141 | struct pseries_elog_section *sect; | 77 | struct pseries_errorlog *sect; |
142 | 78 | ||
143 | /* We should only ever get called for io-event interrupts, but if | 79 | /* We should only ever get called for io-event interrupts, but if |
144 | * we do get called for another type then something went wrong so | 80 | * we do get called for another type then something went wrong so |
@@ -152,7 +88,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog) | |||
152 | return NULL; | 88 | return NULL; |
153 | } | 89 | } |
154 | 90 | ||
155 | sect = find_xelog_section(elog, PSERIES_ELOG_SECT_ID_IO_EVENT); | 91 | sect = get_pseries_errorlog(elog, PSERIES_ELOG_SECT_ID_IO_EVENT); |
156 | if (unlikely(!sect)) { | 92 | if (unlikely(!sect)) { |
157 | printk_once(KERN_WARNING "io_event_irq: RTAS extended event " | 93 | printk_once(KERN_WARNING "io_event_irq: RTAS extended event " |
158 | "log does not contain an IO Event section. " | 94 | "log does not contain an IO Event section. " |