In current kernel, there are several places which need to check whether there is a persistent clock for the platform. Current check is done by calling the read_persistent_clock() and validating its return value. So one optimization is to do the check only once in timekeeping_init(), and use a flag persistent_clock_exist to record it. v2: Add a has_persistent_clock() helper function, as suggested by John.
Unified · Split
| @@ -115,6 +115,12 @@ static inline bool timespec_valid_strict(const struct timespec *ts) · 114 unmodified lines | ||
| 115 | 115 | return true; |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | +extern bool persistent_clock_exist; | |
| 119 | +static inline bool has_persistent_clock(void) | |
| 120 | +{ | |
| 121 | + return persistent_clock_exist; | |
| 122 | +} | |
| 123 | + | |
| 118 | 124 | extern void read_persistent_clock(struct timespec *ts); |
| 119 | 125 | extern void read_boot_clock(struct timespec *ts); |
| 120 | 126 | extern int update_persistent_clock(struct timespec now); |
| @@ -28,6 +28,9 @@ static struct timekeeper timekeeper; · 27 unmodified lines | ||
| 28 | 28 | /* flag for if timekeeping is suspended */ |
| 29 | 29 | int __read_mostly timekeeping_suspended; |
| 30 | 30 | |
| 31 | +/* Flag for if there is a persistent clock on this platform */ | |
| 32 | +bool __read_mostly persistent_clock_exist = false; | |
| 33 | + | |
| 31 | 34 | static inline void tk_normalize_xtime(struct timekeeper *tk) |
| 32 | 35 | { |
| 33 | 36 | while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) { |
| @@ -609,12 +612,14 @@ void __init timekeeping_init(void) · 575 unmodified lines | ||
| 609 | 612 | struct timespec now, boot, tmp; |
| 610 | 613 | |
| 611 | 614 | read_persistent_clock(&now); |
| 615 | + | |
| 612 | 616 | if (!timespec_valid_strict(&now)) { |
| 613 | 617 | pr_warn("WARNING: Persistent clock returned invalid value!\n" |
| 614 | 618 | " Check your CMOS/BIOS settings.\n"); |
| 615 | 619 | now.tv_sec = 0; |
| 616 | 620 | now.tv_nsec = 0; |
| 617 | − } | |
| 621 | + } else if (now.tv_sec || now.tv_nsec) | |
| 622 | + persistent_clock_exist = true; | |
| 618 | 623 | |
| 619 | 624 | read_boot_clock(&boot); |
| 620 | 625 | if (!timespec_valid_strict(&boot)) { |
| @@ -687,11 +692,12 @@ void timekeeping_inject_sleeptime(struct timespec *delta) · 66 unmodified lines | ||
| 687 | 692 | { |
| 688 | 693 | struct timekeeper *tk = &timekeeper; |
| 689 | 694 | unsigned long flags; |
| 690 | − struct timespec ts; | |
| 691 | 695 | |
| 692 | − /* Make sure we don't set the clock twice */ | |
| 693 | − read_persistent_clock(&ts); | |
| 694 | − if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) | |
| 696 | + /* | |
| 697 | + * Make sure we don't set the clock twice, as timekeeping_resume() | |
| 698 | + * already did it | |
| 699 | + */ | |
| 700 | + if (has_persistent_clock()) | |
| 695 | 701 | return; |
| 696 | 702 | |
| 697 | 703 | write_seqlock_irqsave(&tk->lock, flags); |