aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
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 /arch/powerpc/platforms
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>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c90
2 files changed, 92 insertions, 0 deletions
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;