aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2013-11-18 05:05:58 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-12-05 00:08:15 -0500
commit24366360035a9e0a9870ed7208aa2ba1948f844d (patch)
tree912c5a24bc542ed7aef1a5b89531f2103c0c0668
parent8bb61fe1d03123a625265d599a22fb12af79e1ae (diff)
powerpc/powernv: Infrastructure to read opal messages in generic format.
Opal now has a new messaging infrastructure to push the messages to linux in a generic format for different type of messages using only one event bit. The format of the opal message is as below: struct opal_msg { uint32_t msg_type; uint32_t reserved; uint64_t params[8]; }; This patch allows clients to subscribe for notification for specific message type. It is upto the subscriber to decipher the messages who showed interested in receiving specific message type. The interface to subscribe for notification is: int opal_message_notifier_register(enum OpalMessageType msg_type, struct notifier_block *nb) The notifier will fetch the opal message when available and notify the subscriber with message type and the opal message. It is subscribers responsibility to copy the message data before returning from notifier callback. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/opal.h24
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c90
3 files changed, 115 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 033c06be1d84..ffb2036fcfb2 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -132,6 +132,8 @@ extern int opal_enter_rtas(struct rtas_args *args,
132#define OPAL_FLASH_VALIDATE 76 132#define OPAL_FLASH_VALIDATE 76
133#define OPAL_FLASH_MANAGE 77 133#define OPAL_FLASH_MANAGE 77
134#define OPAL_FLASH_UPDATE 78 134#define OPAL_FLASH_UPDATE 78
135#define OPAL_GET_MSG 85
136#define OPAL_CHECK_ASYNC_COMPLETION 86
135 137
136#ifndef __ASSEMBLY__ 138#ifndef __ASSEMBLY__
137 139
@@ -211,7 +213,16 @@ enum OpalPendingState {
211 OPAL_EVENT_ERROR_LOG = 0x40, 213 OPAL_EVENT_ERROR_LOG = 0x40,
212 OPAL_EVENT_EPOW = 0x80, 214 OPAL_EVENT_EPOW = 0x80,
213 OPAL_EVENT_LED_STATUS = 0x100, 215 OPAL_EVENT_LED_STATUS = 0x100,
214 OPAL_EVENT_PCI_ERROR = 0x200 216 OPAL_EVENT_PCI_ERROR = 0x200,
217 OPAL_EVENT_MSG_PENDING = 0x800,
218};
219
220enum OpalMessageType {
221 OPAL_MSG_ASYNC_COMP = 0,
222 OPAL_MSG_MEM_ERR,
223 OPAL_MSG_EPOW,
224 OPAL_MSG_SHUTDOWN,
225 OPAL_MSG_TYPE_MAX,
215}; 226};
216 227
217/* Machine check related definitions */ 228/* Machine check related definitions */
@@ -356,6 +367,12 @@ enum OpalLPCAddressType {
356 OPAL_LPC_FW = 2, 367 OPAL_LPC_FW = 2,
357}; 368};
358 369
370struct opal_msg {
371 uint32_t msg_type;
372 uint32_t reserved;
373 uint64_t params[8];
374};
375
359struct opal_machine_check_event { 376struct opal_machine_check_event {
360 enum OpalMCE_Version version:8; /* 0x00 */ 377 enum OpalMCE_Version version:8; /* 0x00 */
361 uint8_t in_use; /* 0x01 */ 378 uint8_t in_use; /* 0x01 */
@@ -731,6 +748,9 @@ int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
731int64_t opal_manage_flash(uint8_t op); 748int64_t opal_manage_flash(uint8_t op);
732int64_t opal_update_flash(uint64_t blk_list); 749int64_t opal_update_flash(uint64_t blk_list);
733 750
751int64_t opal_get_msg(uint64_t buffer, size_t size);
752int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
753
734/* Internal functions */ 754/* Internal functions */
735extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); 755extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
736 756
@@ -744,6 +764,8 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
744 int depth, void *data); 764 int depth, void *data);
745 765
746extern int opal_notifier_register(struct notifier_block *nb); 766extern int opal_notifier_register(struct notifier_block *nb);
767extern int opal_message_notifier_register(enum OpalMessageType msg_type,
768 struct notifier_block *nb);
747extern void opal_notifier_enable(void); 769extern void opal_notifier_enable(void);
748extern void opal_notifier_disable(void); 770extern void opal_notifier_disable(void);
749extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val); 771extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index e7806504e976..719aa5c325c6 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -126,3 +126,5 @@ OPAL_CALL(opal_return_cpu, OPAL_RETURN_CPU);
126OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE); 126OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE);
127OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE); 127OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE);
128OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); 128OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
129OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
130OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 01e74cbc67e9..7a184a0ff183 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -40,6 +40,7 @@ extern u64 opal_mc_secondary_handler[];
40static unsigned int *opal_irqs; 40static unsigned int *opal_irqs;
41static unsigned int opal_irq_count; 41static unsigned int opal_irq_count;
42static ATOMIC_NOTIFIER_HEAD(opal_notifier_head); 42static ATOMIC_NOTIFIER_HEAD(opal_notifier_head);
43static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
43static DEFINE_SPINLOCK(opal_notifier_lock); 44static DEFINE_SPINLOCK(opal_notifier_lock);
44static uint64_t last_notified_mask = 0x0ul; 45static uint64_t last_notified_mask = 0x0ul;
45static atomic_t opal_notifier_hold = ATOMIC_INIT(0); 46static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
@@ -167,6 +168,95 @@ void opal_notifier_disable(void)
167 atomic_set(&opal_notifier_hold, 1); 168 atomic_set(&opal_notifier_hold, 1);
168} 169}
169 170
171/*
172 * Opal message notifier based on message type. Allow subscribers to get
173 * notified for specific messgae type.
174 */
175int opal_message_notifier_register(enum OpalMessageType msg_type,
176 struct notifier_block *nb)
177{
178 if (!nb) {
179 pr_warning("%s: Invalid argument (%p)\n",
180 __func__, nb);
181 return -EINVAL;
182 }
183 if (msg_type > OPAL_MSG_TYPE_MAX) {
184 pr_warning("%s: Invalid message type argument (%d)\n",
185 __func__, msg_type);
186 return -EINVAL;
187 }
188 return atomic_notifier_chain_register(
189 &opal_msg_notifier_head[msg_type], nb);
190}
191
192static void opal_message_do_notify(uint32_t msg_type, void *msg)
193{
194 /* notify subscribers */
195 atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
196 msg_type, msg);
197}
198
199static void opal_handle_message(void)
200{
201 s64 ret;
202 /*
203 * TODO: pre-allocate a message buffer depending on opal-msg-size
204 * value in /proc/device-tree.
205 */
206 static struct opal_msg msg;
207
208 ret = opal_get_msg(__pa(&msg), sizeof(msg));
209 /* No opal message pending. */
210 if (ret == OPAL_RESOURCE)
211 return;
212
213 /* check for errors. */
214 if (ret) {
215 pr_warning("%s: Failed to retrive opal message, err=%lld\n",
216 __func__, ret);
217 return;
218 }
219
220 /* Sanity check */
221 if (msg.msg_type > OPAL_MSG_TYPE_MAX) {
222 pr_warning("%s: Unknown message type: %u\n",
223 __func__, msg.msg_type);
224 return;
225 }
226 opal_message_do_notify(msg.msg_type, (void *)&msg);
227}
228
229static int opal_message_notify(struct notifier_block *nb,
230 unsigned long events, void *change)
231{
232 if (events & OPAL_EVENT_MSG_PENDING)
233 opal_handle_message();
234 return 0;
235}
236
237static struct notifier_block opal_message_nb = {
238 .notifier_call = opal_message_notify,
239 .next = NULL,
240 .priority = 0,
241};
242
243static int __init opal_message_init(void)
244{
245 int ret, i;
246
247 for (i = 0; i < OPAL_MSG_TYPE_MAX; i++)
248 ATOMIC_INIT_NOTIFIER_HEAD(&opal_msg_notifier_head[i]);
249
250 ret = opal_notifier_register(&opal_message_nb);
251 if (ret) {
252 pr_err("%s: Can't register OPAL event notifier (%d)\n",
253 __func__, ret);
254 return ret;
255 }
256 return 0;
257}
258early_initcall(opal_message_init);
259
170int opal_get_chars(uint32_t vtermno, char *buf, int count) 260int opal_get_chars(uint32_t vtermno, char *buf, int count)
171{ 261{
172 s64 rc; 262 s64 rc;