diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 11e896903828..6cf73d371203 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -1037,6 +1037,7 @@ void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info) | |||
| 1037 | { | 1037 | { |
| 1038 | memset(info, 0, sizeof(struct hrtimer_start_on_info)); | 1038 | memset(info, 0, sizeof(struct hrtimer_start_on_info)); |
| 1039 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); | 1039 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); |
| 1040 | INIT_LIST_HEAD(&info->list); | ||
| 1040 | } | 1041 | } |
| 1041 | 1042 | ||
| 1042 | /** | 1043 | /** |
| @@ -1055,12 +1056,32 @@ void hrtimer_pull(void) | |||
| 1055 | list_for_each_safe(pos, safe, &list) { | 1056 | list_for_each_safe(pos, safe, &list) { |
| 1056 | info = list_entry(pos, struct hrtimer_start_on_info, list); | 1057 | info = list_entry(pos, struct hrtimer_start_on_info, list); |
| 1057 | TRACE("pulled timer 0x%x\n", info->timer); | 1058 | TRACE("pulled timer 0x%x\n", info->timer); |
| 1058 | list_del(pos); | 1059 | list_del_init(pos); |
| 1059 | hrtimer_start(info->timer, info->time, info->mode); | 1060 | if (!info->timer) continue; |
| 1061 | if (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE) | ||
| 1062 | hrtimer_start(info->timer, info->time, info->mode); | ||
| 1063 | if (atomic_read(&info->state) == HRTIMER_START_ON_INACTIVE) | ||
| 1064 | hrtimer_cancel(info->timer); | ||
| 1060 | } | 1065 | } |
| 1061 | } | 1066 | } |
| 1062 | 1067 | ||
| 1063 | /** | 1068 | /** |
| 1069 | * hrtimer_pull_cancel - Cancel a remote timer pull | ||
| 1070 | */ | ||
| 1071 | int hrtimer_pull_cancel(int cpu, struct hrtimer *timer, | ||
| 1072 | struct hrtimer_start_on_info *info) | ||
| 1073 | { | ||
| 1074 | struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu); | ||
| 1075 | |||
| 1076 | raw_spin_lock(&base->lock); | ||
| 1077 | list_del_init(&info->list); | ||
| 1078 | raw_spin_unlock(&base->lock); | ||
| 1079 | |||
| 1080 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); | ||
| 1081 | return hrtimer_try_to_cancel(timer); | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | /** | ||
| 1064 | * hrtimer_start_on - trigger timer arming on remote cpu | 1085 | * hrtimer_start_on - trigger timer arming on remote cpu |
| 1065 | * @cpu: remote cpu | 1086 | * @cpu: remote cpu |
| 1066 | * @info: save timer information for enqueuing on remote cpu | 1087 | * @info: save timer information for enqueuing on remote cpu |
| @@ -1069,8 +1090,8 @@ void hrtimer_pull(void) | |||
| 1069 | * @mode: timer mode | 1090 | * @mode: timer mode |
| 1070 | */ | 1091 | */ |
| 1071 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | 1092 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, |
| 1072 | struct hrtimer *timer, ktime_t time, | 1093 | struct hrtimer *timer, ktime_t time, |
| 1073 | const enum hrtimer_mode mode) | 1094 | const enum hrtimer_mode mode) |
| 1074 | { | 1095 | { |
| 1075 | unsigned long flags; | 1096 | unsigned long flags; |
| 1076 | struct hrtimer_cpu_base* base; | 1097 | struct hrtimer_cpu_base* base; |
| @@ -1102,7 +1123,8 @@ int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | |||
| 1102 | __hrtimer_start_range_ns(info->timer, info->time, | 1123 | __hrtimer_start_range_ns(info->timer, info->time, |
| 1103 | 0, info->mode, 0); | 1124 | 0, info->mode, 0); |
| 1104 | } else { | 1125 | } else { |
| 1105 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | 1126 | TRACE("hrtimer_start_on: pulling 0x%x to remote CPU\n", |
| 1127 | info->timer); | ||
| 1106 | base = &per_cpu(hrtimer_bases, cpu); | 1128 | base = &per_cpu(hrtimer_bases, cpu); |
| 1107 | raw_spin_lock_irqsave(&base->lock, flags); | 1129 | raw_spin_lock_irqsave(&base->lock, flags); |
| 1108 | was_empty = list_empty(&base->to_pull); | 1130 | was_empty = list_empty(&base->to_pull); |
