Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

clocksource/drivers/sh_cmt: Split start/stop of clock source and events

The CMT do a housekeeping such as dealing with runtime PM and
enable/disable clocks when either a clock source is enabled, or when a
new clock event is registered.

Doing this type of housekeeping for when a clock event is registered is
not always possible as it can happen in contexts where holding spinlocks
is not possible. However doing it when registering a clock source is
possible.

As a first step to address this design break apart the CMT start and
stop functions. The path for clock sources need not change, while the
one for clock events need to be reworked in future work.

There is no indented functional change, just breaking the two use-cases
controlled by a flag into two distinct functions.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20250910142657.1148696-2-niklas.soderlund+renesas@ragnatech.se

authored by

Niklas Söderlund and committed by
Daniel Lezcano
0c617a3f cd32e596

+63 -29
+63 -29
drivers/clocksource/sh_cmt.c
··· 578 578 return IRQ_HANDLED; 579 579 } 580 580 581 - static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag) 581 + static int sh_cmt_start_clocksource(struct sh_cmt_channel *ch) 582 582 { 583 583 int ret = 0; 584 584 unsigned long flags; 585 585 586 - if (flag & FLAG_CLOCKSOURCE) 587 - pm_runtime_get_sync(&ch->cmt->pdev->dev); 586 + pm_runtime_get_sync(&ch->cmt->pdev->dev); 588 587 589 588 raw_spin_lock_irqsave(&ch->lock, flags); 590 589 591 - if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) { 592 - if (flag & FLAG_CLOCKEVENT) 593 - pm_runtime_get_sync(&ch->cmt->pdev->dev); 590 + if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) 594 591 ret = sh_cmt_enable(ch); 595 - } 596 592 597 593 if (ret) 598 594 goto out; 599 - ch->flags |= flag; 595 + 596 + ch->flags |= FLAG_CLOCKSOURCE; 600 597 601 598 /* setup timeout if no clockevent */ 602 - if (ch->cmt->num_channels == 1 && 603 - flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT))) 599 + if (ch->cmt->num_channels == 1 && !(ch->flags & FLAG_CLOCKEVENT)) 604 600 __sh_cmt_set_next(ch, ch->max_match_value); 605 - out: 601 + out: 606 602 raw_spin_unlock_irqrestore(&ch->lock, flags); 607 603 608 604 return ret; 609 605 } 610 606 611 - static void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag) 607 + static void sh_cmt_stop_clocksource(struct sh_cmt_channel *ch) 612 608 { 613 609 unsigned long flags; 614 610 unsigned long f; ··· 612 616 raw_spin_lock_irqsave(&ch->lock, flags); 613 617 614 618 f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); 615 - ch->flags &= ~flag; 616 619 617 - if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) { 620 + ch->flags &= ~FLAG_CLOCKSOURCE; 621 + 622 + if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) 618 623 sh_cmt_disable(ch); 619 - if (flag & FLAG_CLOCKEVENT) 620 - pm_runtime_put(&ch->cmt->pdev->dev); 621 - } 622 - 623 - /* adjust the timeout to maximum if only clocksource left */ 624 - if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE)) 625 - __sh_cmt_set_next(ch, ch->max_match_value); 626 624 627 625 raw_spin_unlock_irqrestore(&ch->lock, flags); 628 626 629 - if (flag & FLAG_CLOCKSOURCE) 627 + pm_runtime_put(&ch->cmt->pdev->dev); 628 + } 629 + 630 + static int sh_cmt_start_clockevent(struct sh_cmt_channel *ch) 631 + { 632 + int ret = 0; 633 + unsigned long flags; 634 + 635 + raw_spin_lock_irqsave(&ch->lock, flags); 636 + 637 + if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) { 638 + pm_runtime_get_sync(&ch->cmt->pdev->dev); 639 + ret = sh_cmt_enable(ch); 640 + } 641 + 642 + if (ret) 643 + goto out; 644 + 645 + ch->flags |= FLAG_CLOCKEVENT; 646 + out: 647 + raw_spin_unlock_irqrestore(&ch->lock, flags); 648 + 649 + return ret; 650 + } 651 + 652 + static void sh_cmt_stop_clockevent(struct sh_cmt_channel *ch) 653 + { 654 + unsigned long flags; 655 + unsigned long f; 656 + 657 + raw_spin_lock_irqsave(&ch->lock, flags); 658 + 659 + f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); 660 + 661 + ch->flags &= ~FLAG_CLOCKEVENT; 662 + 663 + if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) { 664 + sh_cmt_disable(ch); 630 665 pm_runtime_put(&ch->cmt->pdev->dev); 666 + } 667 + 668 + /* adjust the timeout to maximum if only clocksource left */ 669 + if (ch->flags & FLAG_CLOCKSOURCE) 670 + __sh_cmt_set_next(ch, ch->max_match_value); 671 + 672 + raw_spin_unlock_irqrestore(&ch->lock, flags); 631 673 } 632 674 633 675 static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs) ··· 706 672 707 673 ch->total_cycles = 0; 708 674 709 - ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE); 675 + ret = sh_cmt_start_clocksource(ch); 710 676 if (!ret) 711 677 ch->cs_enabled = true; 712 678 ··· 719 685 720 686 WARN_ON(!ch->cs_enabled); 721 687 722 - sh_cmt_stop(ch, FLAG_CLOCKSOURCE); 688 + sh_cmt_stop_clocksource(ch); 723 689 ch->cs_enabled = false; 724 690 } 725 691 ··· 730 696 if (!ch->cs_enabled) 731 697 return; 732 698 733 - sh_cmt_stop(ch, FLAG_CLOCKSOURCE); 699 + sh_cmt_stop_clocksource(ch); 734 700 dev_pm_genpd_suspend(&ch->cmt->pdev->dev); 735 701 } 736 702 ··· 742 708 return; 743 709 744 710 dev_pm_genpd_resume(&ch->cmt->pdev->dev); 745 - sh_cmt_start(ch, FLAG_CLOCKSOURCE); 711 + sh_cmt_start_clocksource(ch); 746 712 } 747 713 748 714 static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch, ··· 774 740 775 741 static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic) 776 742 { 777 - sh_cmt_start(ch, FLAG_CLOCKEVENT); 743 + sh_cmt_start_clockevent(ch); 778 744 779 745 if (periodic) 780 746 sh_cmt_set_next(ch, ((ch->cmt->rate + HZ/2) / HZ) - 1); ··· 786 752 { 787 753 struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 788 754 789 - sh_cmt_stop(ch, FLAG_CLOCKEVENT); 755 + sh_cmt_stop_clockevent(ch); 790 756 return 0; 791 757 } 792 758 ··· 797 763 798 764 /* deal with old setting first */ 799 765 if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) 800 - sh_cmt_stop(ch, FLAG_CLOCKEVENT); 766 + sh_cmt_stop_clockevent(ch); 801 767 802 768 dev_info(&ch->cmt->pdev->dev, "ch%u: used for %s clock events\n", 803 769 ch->index, periodic ? "periodic" : "oneshot");