blob: b24598ac6e3b4c8513c967886e2215bbae1da3a1 [file] [log] [blame]
Channagoud Kadabi075db3b2017-03-16 14:26:17 -07001/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Chris Lewfa6135e2016-08-01 13:29:46 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/err.h>
13#include <linux/ipc_logging.h>
14#include <linux/list.h>
15#include <linux/module.h>
16#include <linux/notifier.h>
17#include <linux/of.h>
18#include <linux/platform_device.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/suspend.h>
22#include <linux/random.h>
23#include <soc/qcom/glink.h>
24#include <soc/qcom/subsystem_notif.h>
25#include <soc/qcom/subsystem_restart.h>
26#include "glink_private.h"
27
28#define GLINK_SSR_REPLY_TIMEOUT HZ
29#define GLINK_SSR_INTENT_REQ_TIMEOUT_MS 500
30#define GLINK_SSR_EVENT_INIT ~0
31#define NUM_LOG_PAGES 3
32
33#define GLINK_SSR_LOG(x...) do { \
34 if (glink_ssr_log_ctx) \
35 ipc_log_string(glink_ssr_log_ctx, x); \
36} while (0)
37
38#define GLINK_SSR_ERR(x...) do { \
39 pr_err(x); \
40 GLINK_SSR_LOG(x); \
41} while (0)
42
43static void *glink_ssr_log_ctx;
44
45/* Global restart counter */
46static uint32_t sequence_number;
47
48/* Flag indicating if responses were received for all SSR notifications */
49static bool notifications_successful;
50
51/* Completion for setting notifications_successful */
52struct completion notifications_successful_complete;
53
54/**
55 * struct restart_notifier_block - restart notifier wrapper structure
56 * subsystem: the name of the subsystem as recognized by the SSR framework
57 * nb: notifier block structure used by the SSR framework
58 */
59struct restart_notifier_block {
60 const char *subsystem;
61 struct notifier_block nb;
62};
63
64/**
65 * struct configure_and_open_ch_work - Work structure for used for opening
66 * glink_ssr channels
67 * edge: The G-Link edge obtained from the link state callback
68 * transport: The G-Link transport obtained from the link state callback
69 * link_state: The link state obtained from the link state callback
70 * ss_info: Subsystem information structure containing the info for this
71 * callback
72 * work: Work structure
73 */
74struct configure_and_open_ch_work {
75 char edge[GLINK_NAME_SIZE];
76 char transport[GLINK_NAME_SIZE];
77 enum glink_link_state link_state;
78 struct subsys_info *ss_info;
79 struct work_struct work;
80};
81
82/**
Dhoat Harpalecf7b272016-12-20 18:22:57 +053083 * struct rx_done_ch_work - Work structure used for sending rx_done on
84 * glink_ssr channels
85 * handle: G-Link channel handle to be used for sending rx_done
86 * ptr: Intent pointer data provided in notify rx function
87 * work: Work structure
88 */
89struct rx_done_ch_work {
90 void *handle;
91 const void *ptr;
92 struct work_struct work;
93};
94
95/**
Chris Lewfa6135e2016-08-01 13:29:46 -070096 * struct close_ch_work - Work structure for used for closing glink_ssr channels
97 * edge: The G-Link edge name for the channel being closed
98 * handle: G-Link channel handle to be closed
99 * work: Work structure
100 */
101struct close_ch_work {
102 char edge[GLINK_NAME_SIZE];
103 void *handle;
104 struct work_struct work;
105};
106
107static int glink_ssr_restart_notifier_cb(struct notifier_block *this,
108 unsigned long code,
109 void *data);
110static void delete_ss_info_notify_list(struct subsys_info *ss_info);
111static int configure_and_open_channel(struct subsys_info *ss_info);
112static struct workqueue_struct *glink_ssr_wq;
113
114static LIST_HEAD(subsystem_list);
115static atomic_t responses_remaining = ATOMIC_INIT(0);
116static wait_queue_head_t waitqueue;
117
Dhoat Harpalecf7b272016-12-20 18:22:57 +0530118static void rx_done_cb_worker(struct work_struct *work)
119{
120 struct rx_done_ch_work *rx_done_work =
121 container_of(work, struct rx_done_ch_work, work);
122
123 glink_rx_done(rx_done_work->handle, rx_done_work->ptr, false);
124 kfree(rx_done_work);
125}
126
Chris Lewfa6135e2016-08-01 13:29:46 -0700127static void link_state_cb_worker(struct work_struct *work)
128{
129 unsigned long flags;
130 struct configure_and_open_ch_work *ch_open_work =
131 container_of(work, struct configure_and_open_ch_work, work);
132 struct subsys_info *ss_info = ch_open_work->ss_info;
133
134 GLINK_SSR_LOG("<SSR> %s: LINK STATE[%d] %s:%s\n", __func__,
135 ch_open_work->link_state, ch_open_work->edge,
136 ch_open_work->transport);
137
138 if (ss_info && ch_open_work->link_state == GLINK_LINK_STATE_UP) {
139 spin_lock_irqsave(&ss_info->link_up_lock, flags);
140 if (!ss_info->link_up) {
141 ss_info->link_up = true;
142 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
143 if (!configure_and_open_channel(ss_info)) {
144 glink_unregister_link_state_cb(
145 ss_info->link_state_handle);
146 ss_info->link_state_handle = NULL;
147 }
148 kfree(ch_open_work);
149 return;
150 }
151 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
152 } else {
153 if (ss_info) {
154 spin_lock_irqsave(&ss_info->link_up_lock, flags);
155 ss_info->link_up = false;
156 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
157 ss_info->handle = NULL;
158 } else {
159 GLINK_SSR_ERR("<SSR> %s: ss_info is NULL\n", __func__);
160 }
161 }
162
163 kfree(ch_open_work);
164}
165
166/**
167 * glink_lbsrv_link_state_cb() - Callback to receive link state updates
168 * @cb_info: Information containing link & its state.
169 * @priv: Private data passed during the link state registration.
170 *
171 * This function is called by the G-Link core to notify the glink_ssr module
172 * regarding the link state updates. This function is registered with the
173 * G-Link core by the loopback server during glink_register_link_state_cb().
174 */
175static void glink_ssr_link_state_cb(struct glink_link_state_cb_info *cb_info,
176 void *priv)
177{
178 struct subsys_info *ss_info;
179 struct configure_and_open_ch_work *open_ch_work;
180
181 if (!cb_info) {
182 GLINK_SSR_ERR("<SSR> %s: Missing cb_data\n", __func__);
183 return;
184 }
185
186 ss_info = get_info_for_edge(cb_info->edge);
187
188 open_ch_work = kmalloc(sizeof(*open_ch_work), GFP_KERNEL);
189 if (!open_ch_work) {
190 GLINK_SSR_ERR("<SSR> %s: Could not allocate open_ch_work\n",
191 __func__);
192 return;
193 }
194
195 strlcpy(open_ch_work->edge, cb_info->edge, GLINK_NAME_SIZE);
196 strlcpy(open_ch_work->transport, cb_info->transport, GLINK_NAME_SIZE);
197 open_ch_work->link_state = cb_info->link_state;
198 open_ch_work->ss_info = ss_info;
199
200 INIT_WORK(&open_ch_work->work, link_state_cb_worker);
201 queue_work(glink_ssr_wq, &open_ch_work->work);
202}
203
204/**
205 * glink_ssr_notify_rx() - RX Notification callback
206 * @handle: G-Link channel handle
207 * @priv: Private callback data
208 * @pkt_priv: Private packet data
209 * @ptr: Pointer to the data received
210 * @size: Size of the data received
211 *
212 * This function is a notification callback from the G-Link core that data
213 * has been received from the remote side. This data is validate to make
214 * sure it is a cleanup_done message and is processed accordingly if it is.
215 */
216void glink_ssr_notify_rx(void *handle, const void *priv, const void *pkt_priv,
217 const void *ptr, size_t size)
218{
219 struct ssr_notify_data *cb_data = (struct ssr_notify_data *)priv;
220 struct cleanup_done_msg *resp = (struct cleanup_done_msg *)ptr;
Dhoat Harpalecf7b272016-12-20 18:22:57 +0530221 struct rx_done_ch_work *rx_done_work;
Chris Lewfa6135e2016-08-01 13:29:46 -0700222
Dhoat Harpalecf7b272016-12-20 18:22:57 +0530223 rx_done_work = kmalloc(sizeof(*rx_done_work), GFP_ATOMIC);
224 if (!rx_done_work) {
225 GLINK_SSR_ERR("<SSR> %s: Could not allocate rx_done_work\n",
226 __func__);
227 return;
228 }
Chris Lewfa6135e2016-08-01 13:29:46 -0700229 if (unlikely(!cb_data))
230 goto missing_cb_data;
231 if (unlikely(!cb_data->do_cleanup_data))
232 goto missing_do_cleanup_data;
233 if (unlikely(!resp))
234 goto missing_response;
235 if (unlikely(resp->version != cb_data->do_cleanup_data->version))
236 goto version_mismatch;
237 if (unlikely(resp->seq_num != cb_data->do_cleanup_data->seq_num))
238 goto invalid_seq_number;
239 if (unlikely(resp->response != GLINK_SSR_CLEANUP_DONE))
240 goto wrong_response;
241
242 cb_data->responded = true;
243 atomic_dec(&responses_remaining);
244
245 GLINK_SSR_LOG(
246 "<SSR> %s: Response from %s resp[%d] version[%d] seq_num[%d] restarted[%s]\n",
247 __func__, cb_data->edge, resp->response,
248 resp->version, resp->seq_num,
249 cb_data->do_cleanup_data->name);
250
251 kfree(cb_data->do_cleanup_data);
252 cb_data->do_cleanup_data = NULL;
Dhoat Harpalecf7b272016-12-20 18:22:57 +0530253 rx_done_work->ptr = ptr;
254 rx_done_work->handle = handle;
255 INIT_WORK(&rx_done_work->work, rx_done_cb_worker);
256 queue_work(glink_ssr_wq, &rx_done_work->work);
Chris Lewfa6135e2016-08-01 13:29:46 -0700257 wake_up(&waitqueue);
258 return;
259
260missing_cb_data:
261 panic("%s: Missing cb_data!\n", __func__);
262 return;
263missing_do_cleanup_data:
264 panic("%s: Missing do_cleanup data!\n", __func__);
265 return;
266missing_response:
267 GLINK_SSR_ERR("<SSR> %s: Missing response data\n", __func__);
268 return;
269version_mismatch:
270 GLINK_SSR_ERR("<SSR> %s: Version mismatch. %s[%d], %s[%d]\n", __func__,
271 "do_cleanup version", cb_data->do_cleanup_data->version,
272 "cleanup_done version", resp->version);
273 return;
274invalid_seq_number:
275 GLINK_SSR_ERR("<SSR> %s: Invalid seq. number. %s[%d], %s[%d]\n",
276 __func__, "do_cleanup seq num",
277 cb_data->do_cleanup_data->seq_num,
278 "cleanup_done seq_num", resp->seq_num);
279 return;
280wrong_response:
281 GLINK_SSR_ERR("<SSR> %s: Not a cleaup_done message. %s[%d]\n", __func__,
282 "cleanup_done response", resp->response);
283}
284
285/**
286 * glink_ssr_notify_tx_done() - Transmit finished notification callback
287 * @handle: G-Link channel handle
288 * @priv: Private callback data
289 * @pkt_priv: Private packet data
290 * @ptr: Pointer to the data received
291 *
292 * This function is a notification callback from the G-Link core that data
293 * we sent has finished transmitting.
294 */
295void glink_ssr_notify_tx_done(void *handle, const void *priv,
296 const void *pkt_priv, const void *ptr)
297{
298 struct ssr_notify_data *cb_data = (struct ssr_notify_data *)priv;
299
300 if (unlikely(!cb_data)) {
301 panic("%s: cb_data is NULL!\n", __func__);
302 return;
303 }
304
305 GLINK_SSR_LOG("<SSR> %s: Notified %s of restart\n",
306 __func__, cb_data->edge);
307
308 cb_data->tx_done = true;
309}
310
311void close_ch_worker(struct work_struct *work)
312{
313 unsigned long flags;
314 void *link_state_handle;
315 struct subsys_info *ss_info;
316 struct close_ch_work *close_work =
317 container_of(work, struct close_ch_work, work);
318
319 glink_close(close_work->handle);
320
321 ss_info = get_info_for_edge(close_work->edge);
322 if (WARN_ON(!ss_info))
323 return;
324
325 spin_lock_irqsave(&ss_info->link_up_lock, flags);
326 ss_info->link_up = false;
327 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
328
329 if (WARN_ON(ss_info->link_state_handle != NULL))
330 return;
331 link_state_handle = glink_register_link_state_cb(ss_info->link_info,
332 NULL);
333
334 if (IS_ERR_OR_NULL(link_state_handle))
335 GLINK_SSR_ERR("<SSR> %s: %s, ret[%d]\n", __func__,
336 "Couldn't register link state cb",
337 (int)PTR_ERR(link_state_handle));
338 else
339 ss_info->link_state_handle = link_state_handle;
340
341 if (WARN_ON(!ss_info->cb_data))
342 return;
343 kfree(ss_info->cb_data);
Dhoat Harpal12782302017-02-01 20:16:21 +0530344 ss_info->cb_data = NULL;
Chris Lewfa6135e2016-08-01 13:29:46 -0700345 kfree(close_work);
346}
347
348/**
349 * glink_ssr_notify_state() - Channel state notification callback
350 * @handle: G-Link channel handle
351 * @priv: Private callback data
352 * @event: The state that has been transitioned to
353 *
354 * This function is a notification callback from the G-Link core that the
355 * channel state has changed.
356 */
357void glink_ssr_notify_state(void *handle, const void *priv, unsigned int event)
358{
359 struct ssr_notify_data *cb_data = (struct ssr_notify_data *)priv;
360 struct close_ch_work *close_work;
361
362 if (!cb_data) {
363 GLINK_SSR_ERR("<SSR> %s: Could not allocate data for cb_data\n",
364 __func__);
365 } else {
366 GLINK_SSR_LOG("<SSR> %s: event[%d]\n",
367 __func__, event);
368 cb_data->event = event;
369 if (event == GLINK_REMOTE_DISCONNECTED) {
370 close_work =
371 kmalloc(sizeof(struct close_ch_work),
372 GFP_KERNEL);
373 if (!close_work) {
374 GLINK_SSR_ERR(
375 "<SSR> %s: Could not allocate %s\n",
376 __func__, "close work");
377 return;
378 }
379
380 strlcpy(close_work->edge, cb_data->edge,
381 sizeof(close_work->edge));
382 close_work->handle = handle;
383 INIT_WORK(&close_work->work, close_ch_worker);
384 queue_work(glink_ssr_wq, &close_work->work);
385 }
386 }
387}
388
389/**
390 * glink_ssr_notify_rx_intent_req() - RX intent request notification callback
391 * @handle: G-Link channel handle
392 * @priv: Private callback data
393 * @req_size: The size of the requested intent
394 *
395 * This function is a notification callback from the G-Link core of the remote
396 * side's request for an RX intent to be queued.
397 *
398 * Return: Boolean indicating whether or not the request was successfully
399 * received
400 */
401bool glink_ssr_notify_rx_intent_req(void *handle, const void *priv,
402 size_t req_size)
403{
404 struct ssr_notify_data *cb_data = (struct ssr_notify_data *)priv;
405
406 if (!cb_data) {
407 GLINK_SSR_ERR("<SSR> %s: Could not allocate data for cb_data\n",
408 __func__);
409 return false;
410 }
411 GLINK_SSR_LOG("<SSR> %s: rx_intent_req of size %zu\n",
412 __func__, req_size);
413 return true;
414}
415
416/**
417 * glink_ssr_restart_notifier_cb() - SSR restart notifier callback function
418 * @this: Notifier block used by the SSR framework
419 * @code: The SSR code for which stage of restart is occurring
420 * @data: Structure containing private data - not used here.
421 *
422 * This function is a callback for the SSR framework. From here we initiate
423 * our handling of SSR.
424 *
425 * Return: Status of SSR handling
426 */
427static int glink_ssr_restart_notifier_cb(struct notifier_block *this,
428 unsigned long code,
429 void *data)
430{
431 int ret = 0;
432 struct subsys_info *ss_info = NULL;
433 struct restart_notifier_block *notifier =
434 container_of(this, struct restart_notifier_block, nb);
435
436 if (code == SUBSYS_AFTER_SHUTDOWN) {
437 GLINK_SSR_LOG("<SSR> %s: %s: subsystem restart for %s\n",
438 __func__, "SUBSYS_AFTER_SHUTDOWN",
439 notifier->subsystem);
440 ss_info = get_info_for_subsystem(notifier->subsystem);
441 if (ss_info == NULL) {
442 GLINK_SSR_ERR("<SSR> %s: ss_info is NULL\n", __func__);
443 return -EINVAL;
444 }
445
446 glink_ssr(ss_info->edge);
447 ret = notify_for_subsystem(ss_info);
448
449 if (ret) {
450 GLINK_SSR_ERR("<SSR>: %s: %s, ret[%d]\n", __func__,
451 "Subsystem notification failed", ret);
452 return ret;
453 }
454 }
455 return NOTIFY_DONE;
456}
457
458/**
459 * notify for subsystem() - Notify other subsystems that a subsystem is being
460 * restarted
461 * @ss_info: Subsystem info structure for the subsystem being restarted
462 *
463 * This function sends notifications to affected subsystems that the subsystem
464 * in ss_info is being restarted, and waits for the cleanup done response from
465 * all of those subsystems. It also initiates any local cleanup that is
466 * necessary.
467 *
468 * Return: 0 on success, standard error codes otherwise
469 */
470int notify_for_subsystem(struct subsys_info *ss_info)
471{
472 struct subsys_info *ss_info_channel;
473 struct subsys_info_leaf *ss_leaf_entry;
474 struct do_cleanup_msg *do_cleanup_data;
475 void *handle;
476 int wait_ret;
477 int ret;
478 unsigned long flags;
479
480 if (!ss_info) {
481 GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n",
482 __func__);
483 return -EINVAL;
484 }
485
486 /*
487 * No locking is needed here because ss_info->notify_list_len is
488 * only modified during setup.
489 */
490 atomic_set(&responses_remaining, ss_info->notify_list_len);
491 init_waitqueue_head(&waitqueue);
492 notifications_successful = true;
493
494 list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
495 notify_list_node) {
496 GLINK_SSR_LOG(
497 "<SSR> %s: Notifying: %s:%s of %s restart, seq_num[%d]\n",
498 __func__, ss_leaf_entry->edge,
499 ss_leaf_entry->xprt, ss_info->edge,
500 sequence_number);
501
502 ss_info_channel =
503 get_info_for_subsystem(ss_leaf_entry->ssr_name);
504 if (ss_info_channel == NULL) {
505 GLINK_SSR_ERR(
506 "<SSR> %s: unable to find subsystem name\n",
507 __func__);
508 return -ENODEV;
509 }
510 handle = ss_info_channel->handle;
511 ss_leaf_entry->cb_data = ss_info_channel->cb_data;
512
513 spin_lock_irqsave(&ss_info->link_up_lock, flags);
514 if (IS_ERR_OR_NULL(ss_info_channel->handle) ||
515 !ss_info_channel->cb_data ||
516 !ss_info_channel->link_up ||
517 ss_info_channel->cb_data->event
518 != GLINK_CONNECTED) {
519
520 GLINK_SSR_LOG(
521 "<SSR> %s: %s:%s %s[%d], %s[%p], %s[%d]\n",
522 __func__, ss_leaf_entry->edge, "Not connected",
523 "resp. remaining",
524 atomic_read(&responses_remaining), "handle",
525 ss_info_channel->handle, "link_up",
526 ss_info_channel->link_up);
527
528 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
529 atomic_dec(&responses_remaining);
530 continue;
531 }
532 spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
533
534 do_cleanup_data = kmalloc(sizeof(struct do_cleanup_msg),
535 GFP_KERNEL);
536 if (!do_cleanup_data) {
537 GLINK_SSR_ERR(
538 "%s %s: Could not allocate do_cleanup_msg\n",
539 "<SSR>", __func__);
540 return -ENOMEM;
541 }
542
543 do_cleanup_data->version = 0;
544 do_cleanup_data->command = GLINK_SSR_DO_CLEANUP;
545 do_cleanup_data->seq_num = sequence_number;
546 do_cleanup_data->name_len = strlen(ss_info->edge);
547 strlcpy(do_cleanup_data->name, ss_info->edge,
548 do_cleanup_data->name_len + 1);
549 ss_leaf_entry->cb_data->do_cleanup_data = do_cleanup_data;
550
551 ret = glink_queue_rx_intent(handle,
552 (void *)ss_leaf_entry->cb_data,
553 sizeof(struct cleanup_done_msg));
554 if (ret) {
555 GLINK_SSR_ERR(
556 "%s %s: %s, ret[%d], resp. remaining[%d]\n",
557 "<SSR>", __func__,
558 "queue_rx_intent failed", ret,
559 atomic_read(&responses_remaining));
560 kfree(do_cleanup_data);
561 ss_leaf_entry->cb_data->do_cleanup_data = NULL;
562
563 if (strcmp(ss_leaf_entry->ssr_name, "rpm")) {
564 subsystem_restart(ss_leaf_entry->ssr_name);
565 ss_leaf_entry->restarted = true;
566 } else {
567 panic("%s: Could not queue intent for RPM!\n",
568 __func__);
569 }
570 atomic_dec(&responses_remaining);
571 continue;
572 }
573
574 if (strcmp(ss_leaf_entry->ssr_name, "rpm"))
575 ret = glink_tx(handle, ss_leaf_entry->cb_data,
576 do_cleanup_data,
577 sizeof(*do_cleanup_data),
578 GLINK_TX_REQ_INTENT);
579 else
580 ret = glink_tx(handle, ss_leaf_entry->cb_data,
581 do_cleanup_data,
582 sizeof(*do_cleanup_data),
583 GLINK_TX_SINGLE_THREADED);
584
585 if (ret) {
586 GLINK_SSR_ERR("<SSR> %s: tx failed, ret[%d], %s[%d]\n",
587 __func__, ret, "resp. remaining",
588 atomic_read(&responses_remaining));
589 kfree(do_cleanup_data);
590 ss_leaf_entry->cb_data->do_cleanup_data = NULL;
591
592 if (strcmp(ss_leaf_entry->ssr_name, "rpm")) {
593 subsystem_restart(ss_leaf_entry->ssr_name);
594 ss_leaf_entry->restarted = true;
595 } else {
596 panic("%s: glink_tx() to RPM failed!\n",
597 __func__);
598 }
599 atomic_dec(&responses_remaining);
600 continue;
601 }
602
603 sequence_number++;
604 }
605
606 wait_ret = wait_event_timeout(waitqueue,
607 atomic_read(&responses_remaining) == 0,
608 GLINK_SSR_REPLY_TIMEOUT);
609
610 list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
611 notify_list_node) {
612 if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data)
613 && !ss_leaf_entry->cb_data->responded) {
614 GLINK_SSR_ERR("%s %s: Subsystem %s %s\n",
615 "<SSR>", __func__, ss_leaf_entry->edge,
616 "failed to respond. Restarting.");
617
618 notifications_successful = false;
619
620 /* Check for RPM, as it can't be restarted */
621 if (!strcmp(ss_leaf_entry->ssr_name, "rpm"))
622 panic("%s: RPM failed to respond!\n", __func__);
623 else if (!ss_leaf_entry->restarted)
624 subsystem_restart(ss_leaf_entry->ssr_name);
625 }
626 ss_leaf_entry->restarted = false;
627
628 if (!IS_ERR_OR_NULL(ss_leaf_entry->cb_data))
629 ss_leaf_entry->cb_data->responded = false;
630 }
631 complete(&notifications_successful_complete);
632 return 0;
633}
634EXPORT_SYMBOL(notify_for_subsystem);
635
636/**
637 * configure_and_open_channel() - configure and open a G-Link channel for
638 * the given subsystem
639 * @ss_info: The subsys_info structure where the channel will be stored
640 *
641 * Return: 0 on success, standard error codes otherwise
642 */
643static int configure_and_open_channel(struct subsys_info *ss_info)
644{
645 struct glink_open_config open_cfg;
646 struct ssr_notify_data *cb_data = NULL;
647 void *handle = NULL;
648
649 if (!ss_info) {
650 GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n",
651 __func__);
652 return -EINVAL;
653 }
654
655 cb_data = kmalloc(sizeof(struct ssr_notify_data), GFP_KERNEL);
656 if (!cb_data) {
657 GLINK_SSR_ERR("<SSR> %s: Could not allocate cb_data\n",
658 __func__);
659 return -ENOMEM;
660 }
661 cb_data->responded = false;
662 cb_data->event = GLINK_SSR_EVENT_INIT;
663 cb_data->edge = ss_info->edge;
664 ss_info->cb_data = cb_data;
665
666 memset(&open_cfg, 0, sizeof(struct glink_open_config));
667
668 if (ss_info->xprt) {
669 open_cfg.transport = ss_info->xprt;
670 } else {
671 open_cfg.transport = NULL;
672 open_cfg.options = GLINK_OPT_INITIAL_XPORT;
673 }
674 open_cfg.edge = ss_info->edge;
675 open_cfg.name = "glink_ssr";
676 open_cfg.notify_rx = glink_ssr_notify_rx;
677 open_cfg.notify_tx_done = glink_ssr_notify_tx_done;
678 open_cfg.notify_state = glink_ssr_notify_state;
679 open_cfg.notify_rx_intent_req = glink_ssr_notify_rx_intent_req;
680 open_cfg.priv = ss_info->cb_data;
681 open_cfg.rx_intent_req_timeout_ms = GLINK_SSR_INTENT_REQ_TIMEOUT_MS;
682
683 handle = glink_open(&open_cfg);
684 if (IS_ERR_OR_NULL(handle)) {
685 GLINK_SSR_ERR(
686 "<SSR> %s:%s %s: unable to open channel, ret[%d]\n",
687 open_cfg.edge, open_cfg.name, __func__,
688 (int)PTR_ERR(handle));
689 kfree(cb_data);
690 cb_data = NULL;
691 ss_info->cb_data = NULL;
692 return PTR_ERR(handle);
693 }
694 ss_info->handle = handle;
695 return 0;
696}
697
698/**
699 * get_info_for_subsystem() - Retrieve information about a subsystem from the
700 * global subsystem_info_list
701 * @subsystem: The name of the subsystem recognized by the SSR
702 * framework
703 *
704 * Return: subsys_info structure containing info for the requested subsystem;
705 * NULL if no structure can be found for the requested subsystem
706 */
707struct subsys_info *get_info_for_subsystem(const char *subsystem)
708{
709 struct subsys_info *ss_info_entry;
710
711 list_for_each_entry(ss_info_entry, &subsystem_list,
712 subsystem_list_node) {
713 if (!strcmp(subsystem, ss_info_entry->ssr_name))
714 return ss_info_entry;
715 }
716
717 return NULL;
718}
719EXPORT_SYMBOL(get_info_for_subsystem);
720
721/**
722 * get_info_for_edge() - Retrieve information about a subsystem from the
723 * global subsystem_info_list
724 * @edge: The name of the edge recognized by G-Link
725 *
726 * Return: subsys_info structure containing info for the requested subsystem;
727 * NULL if no structure can be found for the requested subsystem
728 */
729struct subsys_info *get_info_for_edge(const char *edge)
730{
731 struct subsys_info *ss_info_entry;
732
733 list_for_each_entry(ss_info_entry, &subsystem_list,
734 subsystem_list_node) {
735 if (!strcmp(edge, ss_info_entry->edge))
736 return ss_info_entry;
737 }
738
739 return NULL;
740}
741EXPORT_SYMBOL(get_info_for_edge);
742
743/**
744 * glink_ssr_get_seq_num() - Get the current SSR sequence number
745 *
746 * Return: The current SSR sequence number
747 */
748uint32_t glink_ssr_get_seq_num(void)
749{
750 return sequence_number;
751}
752EXPORT_SYMBOL(glink_ssr_get_seq_num);
753
754/**
755 * delete_ss_info_notify_list() - Delete the notify list for a subsystem
756 * @ss_info: The subsystem info structure
757 */
758static void delete_ss_info_notify_list(struct subsys_info *ss_info)
759{
760 struct subsys_info_leaf *leaf, *temp;
761
762 list_for_each_entry_safe(leaf, temp, &ss_info->notify_list,
763 notify_list_node) {
764 list_del(&leaf->notify_list_node);
765 kfree(leaf);
766 }
767}
768
769/**
770 * glink_ssr_wait_cleanup_done() - Get the value of the
771 * notifications_successful flag.
772 * @timeout_multiplier: timeout multiplier for waiting on all processors
773 *
774 * Return: True if cleanup_done received from all processors, false otherwise
775 */
776bool glink_ssr_wait_cleanup_done(unsigned int ssr_timeout_multiplier)
777{
778 int wait_ret =
779 wait_for_completion_timeout(&notifications_successful_complete,
780 ssr_timeout_multiplier * GLINK_SSR_REPLY_TIMEOUT);
781 reinit_completion(&notifications_successful_complete);
782
783 if (!notifications_successful || !wait_ret)
784 return false;
785 else
786 return true;
787}
788EXPORT_SYMBOL(glink_ssr_wait_cleanup_done);
789
790/**
791 * glink_ssr_probe() - G-Link SSR platform device probe function
792 * @pdev: Pointer to the platform device structure
793 *
794 * This function parses DT for information on which subsystems should be
795 * notified when each subsystem undergoes SSR. The global subsystem information
796 * list is built from this information. In addition, SSR notifier callback
797 * functions are registered here for the necessary subsystems.
798 *
799 * Return: 0 on success, standard error codes otherwise
800 */
801static int glink_ssr_probe(struct platform_device *pdev)
802{
803 struct device_node *node;
804 struct device_node *phandle_node;
805 struct restart_notifier_block *nb;
806 struct subsys_info *ss_info;
Channagoud Kadabi075db3b2017-03-16 14:26:17 -0700807 struct subsys_info_leaf *ss_info_leaf = NULL;
Chris Lewfa6135e2016-08-01 13:29:46 -0700808 struct glink_link_info *link_info;
809 char *key;
810 const char *edge;
811 const char *subsys_name;
812 const char *xprt;
813 void *handle;
814 void *link_state_handle;
815 int phandle_index = 0;
816 int ret = 0;
817
818 if (!pdev) {
819 GLINK_SSR_ERR("<SSR> %s: pdev is NULL\n", __func__);
820 ret = -EINVAL;
821 goto pdev_null_or_ss_info_alloc_failed;
822 }
823
824 node = pdev->dev.of_node;
825
826 ss_info = kmalloc(sizeof(*ss_info), GFP_KERNEL);
827 if (!ss_info) {
828 GLINK_SSR_ERR("<SSR> %s: %s\n", __func__,
829 "Could not allocate subsystem info structure\n");
830 ret = -ENOMEM;
831 goto pdev_null_or_ss_info_alloc_failed;
832 }
833 INIT_LIST_HEAD(&ss_info->notify_list);
834
835 link_info = kmalloc(sizeof(struct glink_link_info),
836 GFP_KERNEL);
837 if (!link_info) {
838 GLINK_SSR_ERR("<SSR> %s: %s\n", __func__,
839 "Could not allocate link info structure\n");
840 ret = -ENOMEM;
841 goto link_info_alloc_failed;
842 }
843 ss_info->link_info = link_info;
844
845 key = "label";
846 subsys_name = of_get_property(node, key, NULL);
847 if (!subsys_name) {
848 GLINK_SSR_ERR("<SSR> %s: missing key %s\n", __func__, key);
849 ret = -ENODEV;
850 goto label_or_edge_missing;
851 }
852
853 key = "qcom,edge";
854 edge = of_get_property(node, key, NULL);
855 if (!edge) {
856 GLINK_SSR_ERR("<SSR> %s: missing key %s\n", __func__, key);
857 ret = -ENODEV;
858 goto label_or_edge_missing;
859 }
860
861 key = "qcom,xprt";
862 xprt = of_get_property(node, key, NULL);
863 if (!xprt)
864 GLINK_SSR_LOG(
865 "%s %s: no transport present for subys/edge %s/%s\n",
866 "<SSR>", __func__, subsys_name, edge);
867
868 ss_info->ssr_name = subsys_name;
869 ss_info->edge = edge;
870 ss_info->xprt = xprt;
871 ss_info->notify_list_len = 0;
872 ss_info->link_info->transport = xprt;
873 ss_info->link_info->edge = edge;
874 ss_info->link_info->glink_link_state_notif_cb = glink_ssr_link_state_cb;
875 ss_info->link_up = false;
876 ss_info->handle = NULL;
877 ss_info->link_state_handle = NULL;
878 ss_info->cb_data = NULL;
879 spin_lock_init(&ss_info->link_up_lock);
880
881 nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL);
882 if (!nb) {
883 GLINK_SSR_ERR("<SSR> %s: Could not allocate notifier block\n",
884 __func__);
885 ret = -ENOMEM;
886 goto label_or_edge_missing;
887 }
888
889 nb->subsystem = subsys_name;
890 nb->nb.notifier_call = glink_ssr_restart_notifier_cb;
891
892 handle = subsys_notif_register_notifier(nb->subsystem, &nb->nb);
893 if (IS_ERR_OR_NULL(handle)) {
894 GLINK_SSR_ERR("<SSR> %s: Could not register SSR notifier cb\n",
895 __func__);
896 ret = -EINVAL;
897 goto nb_registration_fail;
898 }
899
900 key = "qcom,notify-edges";
901 while (true) {
902 phandle_node = of_parse_phandle(node, key, phandle_index++);
903 if (!phandle_node && phandle_index == 0) {
904 GLINK_SSR_ERR(
905 "<SSR> %s: qcom,notify-edges is not present",
906 __func__);
907 ret = -ENODEV;
908 goto notify_edges_not_present;
909 }
910
911 if (!phandle_node)
912 break;
913
914 ss_info_leaf = kmalloc(sizeof(struct subsys_info_leaf),
915 GFP_KERNEL);
916 if (!ss_info_leaf) {
917 GLINK_SSR_ERR(
918 "<SSR> %s: Could not allocate subsys_info_leaf\n",
919 __func__);
920 ret = -ENOMEM;
921 goto notify_edges_not_present;
922 }
923
924 subsys_name = of_get_property(phandle_node, "label", NULL);
925 edge = of_get_property(phandle_node, "qcom,edge", NULL);
926 xprt = of_get_property(phandle_node, "qcom,xprt", NULL);
927
928 of_node_put(phandle_node);
929
930 if (!subsys_name || !edge) {
931 GLINK_SSR_ERR(
932 "%s, %s: Found DT node with invalid data!\n",
933 "<SSR>", __func__);
934 ret = -EINVAL;
935 goto invalid_dt_node;
936 }
937
938 ss_info_leaf->ssr_name = subsys_name;
939 ss_info_leaf->edge = edge;
940 ss_info_leaf->xprt = xprt;
941 ss_info_leaf->restarted = false;
942 list_add_tail(&ss_info_leaf->notify_list_node,
943 &ss_info->notify_list);
944 ss_info->notify_list_len++;
945 }
946
947 list_add_tail(&ss_info->subsystem_list_node, &subsystem_list);
948
949 link_state_handle = glink_register_link_state_cb(ss_info->link_info,
950 NULL);
951 if (IS_ERR_OR_NULL(link_state_handle)) {
952 GLINK_SSR_ERR("<SSR> %s: Could not register link state cb\n",
953 __func__);
954 ret = PTR_ERR(link_state_handle);
955 goto link_state_register_fail;
956 }
957 ss_info->link_state_handle = link_state_handle;
958
959 return 0;
960
961link_state_register_fail:
962 list_del(&ss_info->subsystem_list_node);
963invalid_dt_node:
964 kfree(ss_info_leaf);
965notify_edges_not_present:
966 subsys_notif_unregister_notifier(handle, &nb->nb);
967 delete_ss_info_notify_list(ss_info);
968nb_registration_fail:
969 kfree(nb);
970label_or_edge_missing:
971 kfree(link_info);
972link_info_alloc_failed:
973 kfree(ss_info);
974pdev_null_or_ss_info_alloc_failed:
975 return ret;
976}
977
978static const struct of_device_id match_table[] = {
979 { .compatible = "qcom,glink_ssr" },
980 {},
981};
982
983static struct platform_driver glink_ssr_driver = {
984 .probe = glink_ssr_probe,
985 .driver = {
986 .name = "msm_glink_ssr",
987 .owner = THIS_MODULE,
988 .of_match_table = match_table,
989 },
990};
991
992static int glink_ssr_init(void)
993{
994 int ret;
995
996 glink_ssr_log_ctx =
997 ipc_log_context_create(NUM_LOG_PAGES, "glink_ssr", 0);
998 glink_ssr_wq = create_singlethread_workqueue("glink_ssr_wq");
999 ret = platform_driver_register(&glink_ssr_driver);
1000 if (ret)
1001 GLINK_SSR_ERR("<SSR> %s: %s ret: %d\n", __func__,
1002 "glink_ssr driver registration failed", ret);
1003
1004 notifications_successful = false;
1005 init_completion(&notifications_successful_complete);
1006 return 0;
1007}
1008
1009module_init(glink_ssr_init);
1010
1011MODULE_DESCRIPTION("MSM Generic Link (G-Link) SSR Module");
1012MODULE_LICENSE("GPL v2");