diff options
Diffstat (limited to 'drivers/remoteproc/qcom_sysmon.c')
-rw-r--r-- | drivers/remoteproc/qcom_sysmon.c | 25 |
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"); |