aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc/qcom_sysmon.c')
-rw-r--r--drivers/remoteproc/qcom_sysmon.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c
index 9eb2f6bccea6..b37b111b15b3 100644
--- a/drivers/remoteproc/qcom_sysmon.c
+++ b/drivers/remoteproc/qcom_sysmon.c
@@ -22,6 +22,9 @@ struct qcom_sysmon {
22 struct rproc_subdev subdev; 22 struct rproc_subdev subdev;
23 struct rproc *rproc; 23 struct rproc *rproc;
24 24
25 int state;
26 struct mutex state_lock;
27
25 struct list_head node; 28 struct list_head node;
26 29
27 const char *name; 30 const char *name;
@@ -448,7 +451,10 @@ static int sysmon_prepare(struct rproc_subdev *subdev)
448 .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP 451 .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP
449 }; 452 };
450 453
454 mutex_lock(&sysmon->state_lock);
455 sysmon->state = SSCTL_SSR_EVENT_BEFORE_POWERUP;
451 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event); 456 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
457 mutex_unlock(&sysmon->state_lock);
452 458
453 return 0; 459 return 0;
454} 460}
@@ -472,20 +478,25 @@ static int sysmon_start(struct rproc_subdev *subdev)
472 .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP 478 .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP
473 }; 479 };
474 480
481 mutex_lock(&sysmon->state_lock);
482 sysmon->state = SSCTL_SSR_EVENT_AFTER_POWERUP;
475 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event); 483 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
484 mutex_unlock(&sysmon->state_lock);
476 485
477 mutex_lock(&sysmon_lock); 486 mutex_lock(&sysmon_lock);
478 list_for_each_entry(target, &sysmon_list, node) { 487 list_for_each_entry(target, &sysmon_list, node) {
479 if (target == sysmon || 488 if (target == sysmon)
480 target->rproc->state != RPROC_RUNNING)
481 continue; 489 continue;
482 490
491 mutex_lock(&target->state_lock);
483 event.subsys_name = target->name; 492 event.subsys_name = target->name;
493 event.ssr_event = target->state;
484 494
485 if (sysmon->ssctl_version == 2) 495 if (sysmon->ssctl_version == 2)
486 ssctl_send_event(sysmon, &event); 496 ssctl_send_event(sysmon, &event);
487 else if (sysmon->ept) 497 else if (sysmon->ept)
488 sysmon_send_event(sysmon, &event); 498 sysmon_send_event(sysmon, &event);
499 mutex_unlock(&target->state_lock);
489 } 500 }
490 mutex_unlock(&sysmon_lock); 501 mutex_unlock(&sysmon_lock);
491 502
@@ -500,7 +511,10 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
500 .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN 511 .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN
501 }; 512 };
502 513
514 mutex_lock(&sysmon->state_lock);
515 sysmon->state = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN;
503 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event); 516 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
517 mutex_unlock(&sysmon->state_lock);
504 518
505 /* Don't request graceful shutdown if we've crashed */ 519 /* Don't request graceful shutdown if we've crashed */
506 if (crashed) 520 if (crashed)
@@ -521,7 +535,10 @@ static void sysmon_unprepare(struct rproc_subdev *subdev)
521 .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN 535 .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN
522 }; 536 };
523 537
538 mutex_lock(&sysmon->state_lock);
539 sysmon->state = SSCTL_SSR_EVENT_AFTER_SHUTDOWN;
524 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event); 540 blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
541 mutex_unlock(&sysmon->state_lock);
525} 542}
526 543
527/** 544/**
@@ -534,11 +551,10 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
534 void *data) 551 void *data)
535{ 552{
536 struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb); 553 struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
537 struct rproc *rproc = sysmon->rproc;
538 struct sysmon_event *sysmon_event = data; 554 struct sysmon_event *sysmon_event = data;
539 555
540 /* Skip non-running rprocs and the originating instance */ 556 /* Skip non-running rprocs and the originating instance */
541 if (rproc->state != RPROC_RUNNING || 557 if (sysmon->state != SSCTL_SSR_EVENT_AFTER_POWERUP ||
542 !strcmp(sysmon_event->subsys_name, sysmon->name)) { 558 !strcmp(sysmon_event->subsys_name, sysmon->name)) {
543 dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name); 559 dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name);
544 return NOTIFY_DONE; 560 return NOTIFY_DONE;
@@ -591,6 +607,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
591 init_completion(&sysmon->ind_comp); 607 init_completion(&sysmon->ind_comp);
592 init_completion(&sysmon->shutdown_comp); 608 init_completion(&sysmon->shutdown_comp);
593 mutex_init(&sysmon->lock); 609 mutex_init(&sysmon->lock);
610 mutex_init(&sysmon->state_lock);
594 611
595 sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node, 612 sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node,
596 "shutdown-ack"); 613 "shutdown-ack");