static ktime_t watchdog_next_keepalive(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data = wdd->wd_data; unsigned int timeout_ms = wdd->timeout * 1000; ktime_t keepalive_interval; ktime_t last_heartbeat, latest_heartbeat; ktime_t virt_timeout; unsigned int hw_heartbeat_ms; virt_timeout = ktime_add(wd_data->last_keepalive, ms_to_ktime(timeout_ms)); hw_heartbeat_ms = min_not_zero(timeout_ms, wdd->max_hw_heartbeat_ms); keepalive_interval = ms_to_ktime(hw_heartbeat_ms / 2); if (!watchdog_active(wdd)) return keepalive_interval; /* * To ensure that the watchdog times out wdd->timeout seconds * after the most recent ping from userspace, the last * worker ping has to come in hw_heartbeat_ms before this timeout. */ last_heartbeat = ktime_sub(virt_timeout, ms_to_ktime(hw_heartbeat_ms)); latest_heartbeat = ktime_sub(last_heartbeat, ktime_get()); if (ktime_before(latest_heartbeat, keepalive_interval)) return latest_heartbeat; return keepalive_interval; }
static void pp_pong(struct pp_ctx *pp) { u32 msg_data = -1, spad_data = -1; int pidx = 0; /* Read pong data */ spad_data = ntb_spad_read(pp->ntb, 0); msg_data = ntb_msg_read(pp->ntb, &pidx, 0); ntb_msg_clear_sts(pp->ntb, -1); /* * Scratchpad and message data may differ, since message register can't * be rewritten unless status is cleared. Additionally either of them * might be unsupported */ dev_dbg(&pp->ntb->dev, "Pong spad %#x, msg %#x (port %d)\n", spad_data, msg_data, ntb_peer_port_number(pp->ntb, pidx)); atomic_inc(&pp->count); ntb_db_set_mask(pp->ntb, pp->in_db); ntb_db_clear(pp->ntb, pp->in_db); hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL); }
static int __watchdog_ping(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data = wdd->wd_data; ktime_t earliest_keepalive, now; int err; earliest_keepalive = ktime_add(wd_data->last_hw_keepalive, ms_to_ktime(wdd->min_hw_heartbeat_ms)); now = ktime_get(); if (ktime_after(earliest_keepalive, now)) { hrtimer_start(&wd_data->timer, ktime_sub(earliest_keepalive, now), HRTIMER_MODE_REL); return 0; } wd_data->last_hw_keepalive = now; if (wdd->ops->ping) err = wdd->ops->ping(wdd); /* ping the watchdog */ else err = wdd->ops->start(wdd); /* restart watchdog */ watchdog_update_worker(wdd); return err; }
static int jiqhrtimer_seq_show(struct seq_file *m, void *v) { struct clientdata *data = m->private; ktime_t period = ms_to_ktime(jiffies_to_msecs(delay)); int retval; data->seq_file = m; data->ktime = ktime_get(); data->delay = delay; data->count = max_count; data->stopped = false; hrtimer_init(&data->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); data->hrtimer.function = jiq_hrtimedout; jiq_print2(data); /* print and go to sleep */ hrtimer_start(&data->hrtimer, period, HRTIMER_MODE_REL); retval = wait_event_interruptible(jiq_wait, !data->count); if (retval < 0) { data->stopped = true; hrtimer_cancel(&data->hrtimer); /* in case a signal woke us up */ } return retval; }
static void ledtrig_general_activity(struct ledtrig_t * trigger) { struct ledtrig_general_pdata_t * pdat = (struct ledtrig_general_pdata_t *)trigger->priv; pdat->activity++; timer_start_now(&pdat->timer, ms_to_ktime(20)); }
static int key_gpio_timer_function(struct timer_t * timer, void * data) { struct input_t * input = (struct input_t *)(data); struct key_gpio_private_data_t * dat = (struct key_gpio_private_data_t *)input->priv; struct key_gpio_data_t * rdat = (struct key_gpio_data_t *)dat->rdat; enum event_type_t type; int i, val; for(i = 0; i < rdat->nbutton; i++) { val = gpio_get_value(rdat->buttons[i].gpio); if(val != dat->state[i]) { if(rdat->buttons[i].active_low) type = val ? EVENT_TYPE_KEY_UP : EVENT_TYPE_KEY_DOWN; else type = val ? EVENT_TYPE_KEY_DOWN : EVENT_TYPE_KEY_UP; if(type == EVENT_TYPE_KEY_DOWN) push_event_key_down(input, rdat->buttons[i].key); else if(type == EVENT_TYPE_KEY_UP) push_event_key_up(input, rdat->buttons[i].key); } dat->state[i] = val; } timer_forward_now(timer, ms_to_ktime(100)); return 1; }
static enum hrtimer_restart jiq_hrtimedout(struct hrtimer *hrtimer) { struct clientdata *data = container_of(hrtimer, struct clientdata, hrtimer); ktime_t period = ms_to_ktime(jiffies_to_msecs(data->delay)); if (!jiq_print2(data)) return HRTIMER_NORESTART; hrtimer_forward(hrtimer, hrtimer_get_expires(hrtimer), period); return HRTIMER_RESTART; }
enum hrtimer_restart nxt_i2c_sensor_poll_timer(struct hrtimer *timer) { struct nxt_i2c_sensor_data *data = container_of(timer, struct nxt_i2c_sensor_data, poll_timer); hrtimer_forward_now(timer, ms_to_ktime(data->poll_ms)); schedule_work(&data->poll_work); return HRTIMER_RESTART; }
static void ledtrig_heartbeat_init(struct ledtrig_t * trigger) { struct ledtrig_heartbeat_data_t * dat = (struct ledtrig_heartbeat_data_t *)trigger->priv; if(dat) { dat->phase = 0; timer_init(&dat->timer, heartbeat_timer_function, trigger); timer_start_now(&dat->timer, ms_to_ktime(10)); } }
enum hrtimer_restart brickpi_poll_timer_function(struct hrtimer *timer) { struct brickpi_data *data = container_of(timer, struct brickpi_data, poll_timer); hrtimer_forward_now(timer, ms_to_ktime(BRICKPI_POLL_MS)); if (data->closing) return HRTIMER_NORESTART; schedule_work(&data->poll_work); return HRTIMER_RESTART; }
static int buzzer_pwm_timer_function(struct timer_t * timer, void * data) { struct buzzer_t * buzzer = (struct buzzer_t *)(data); struct buzzer_pwm_pdata_t * pdat = (struct buzzer_pwm_pdata_t *)buzzer->priv; struct beep_param_t * param = queue_pop(pdat->beep); if(!param) { buzzer_pwm_set(buzzer, 0); return 0; } buzzer_pwm_set(buzzer, param->frequency); timer_forward_now(&pdat->timer, ms_to_ktime(param->millisecond)); free(param); return 1; }
static int ledtrig_general_timer_function(struct timer_t * timer, void * data) { struct ledtrig_t * trigger = (struct ledtrig_t *)(data); struct ledtrig_general_pdata_t * pdat = (struct ledtrig_general_pdata_t *)trigger->priv; if(pdat->last_activity != pdat->activity) { pdat->last_activity = pdat->activity; led_set_brightness(pdat->led, CONFIG_MAX_BRIGHTNESS); timer_forward_now(timer, ms_to_ktime(20)); return 1; } else { led_set_brightness(pdat->led, 0); return 0; } }
static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { ktime_t start; ktime_t stop; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(timeout)); do { if ((ioread32(reg) & mask) == value) return true; usleep_range(50, 100); } while (ktime_before(ktime_get(), stop)); return ((ioread32(reg) & mask) == value); }
static void pp_setup(struct pp_ctx *pp) { int ret; ntb_db_set_mask(pp->ntb, pp->in_db); hrtimer_cancel(&pp->timer); ret = pp_find_next_peer(pp); if (ret == -ENODEV) { dev_dbg(&pp->ntb->dev, "Got no peers, so cancel\n"); return; } dev_dbg(&pp->ntb->dev, "Ping-pong started with port %d, db %#llx\n", ntb_peer_port_number(pp->ntb, pp->out_pidx), pp->out_db); hrtimer_start(&pp->timer, ms_to_ktime(delay_ms), HRTIMER_MODE_REL); }
static int heartbeat_timer_function(struct timer_t * timer, void * data) { struct ledtrig_t * trigger = (struct ledtrig_t *)(data); struct ledtrig_heartbeat_data_t * dat = (struct ledtrig_heartbeat_data_t *)trigger->priv; struct led_t * led = (struct led_t *)(trigger->led); int brightness = 0; u32_t delay = 0; /* * Acts like an actual heart beat -- thump-thump-pause ... */ switch(dat->phase) { case 0: dat->period = 1260; delay = 70; dat->phase++; brightness = CONFIG_MAX_BRIGHTNESS; break; case 1: delay = dat->period / 4 - 70; dat->phase++; brightness = 0; break; case 2: delay = 70; dat->phase++; brightness = CONFIG_MAX_BRIGHTNESS; break; default: delay = dat->period - dat->period / 4 - 70; dat->phase = 0; brightness = 0; break; } led_set_brightness(led, brightness); timer_forward_now(timer, ms_to_ktime(delay)); return 1; }
/** * mei_txe_aliveness_poll - waits for aliveness to settle * * @dev: the device structure * @expected: expected aliveness value * * Polls for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set * * Return: 0 if the expected value was received, -ETIME otherwise */ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected) { struct mei_txe_hw *hw = to_txe_hw(dev); ktime_t stop, start; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(SEC_ALIVENESS_WAIT_TIMEOUT)); do { hw->aliveness = mei_txe_aliveness_get(dev); if (hw->aliveness == expected) { dev->pg_event = MEI_PG_EVENT_IDLE; dev_dbg(dev->dev, "aliveness settled after %lld usecs\n", ktime_to_us(ktime_sub(ktime_get(), start))); return 0; } usleep_range(20, 50); } while (ktime_before(ktime_get(), stop)); dev->pg_event = MEI_PG_EVENT_IDLE; dev_err(dev->dev, "aliveness timed out\n"); return -ETIME; }
static void buzzer_gpio_beep(struct buzzer_t * buzzer, int frequency, int millisecond) { struct buzzer_gpio_pdata_t * pdat = (struct buzzer_gpio_pdata_t *)buzzer->priv; struct beep_param_t * param; if((frequency == 0) && (millisecond == 0)) { timer_cancel(&pdat->timer); queue_clear(pdat->beep, iteration_beep_param); buzzer_gpio_set(buzzer, 0); return; } param = malloc(sizeof(struct beep_param_t)); if(!param) return; param->frequency = frequency; param->millisecond = millisecond; queue_push(pdat->beep, param); if(queue_avail(pdat->beep) == 1) timer_start_now(&pdat->timer, ms_to_ktime(1)); }
static void input_init(struct input_t * input) { struct key_gpio_private_data_t * dat = (struct key_gpio_private_data_t *)input->priv; struct key_gpio_data_t * rdat = (struct key_gpio_data_t *)dat->rdat; int i; if(!dat) return; dat->state = malloc(rdat->nbutton * sizeof(int)); if(!dat->state) return; for(i = 0; i < rdat->nbutton; i++) { gpio_set_pull(rdat->buttons[i].gpio, rdat->buttons[i].active_low ? GPIO_PULL_UP :GPIO_PULL_DOWN); gpio_direction_input(rdat->buttons[i].gpio); dat->state[i] = gpio_get_value(rdat->buttons[i].gpio); } timer_init(&dat->timer, key_gpio_timer_function, input); timer_start_now(&dat->timer, ms_to_ktime(100)); }
static void cpufreq_limit_work(struct work_struct *work) { struct cpufreq_limit_data *limit = container_of(work, struct cpufreq_limit_data, limit_work); struct task_struct *p = NULL, *t = NULL; char **s = limit->limit_name; char *comm = task_comm; int cpu, i = 0, len = limit->limit_num; if (!test_bit(STATE_RESUME_DONE, &limit->resume_state)) goto _exit; task_comm[0] = 0; for_each_possible_cpu(cpu) { p = curr_task(cpu); t = find_task_by_vpid(task_tgid_vnr(p)); /* parent */ if (t) p = t; if (p->flags & PF_KTHREAD) continue; if (!likely(p->mm)) continue; cpufreq_cmdline(p, comm); pr_debug("cpu %d current (%d) %s\n", cpu, p->pid, comm); for (i = 0; len > i; i++) { /* boost : task is running */ if (!strncmp(comm, s[i], strlen(s[i]))) { limit->time_stamp = 0; cpufreq_set_max_frequency(limit, 1); pr_debug(": run %s\n", s[i]); goto _exit; } } } for_each_process(p) { if (p->flags & PF_KTHREAD) continue; if (!likely(p->mm)) continue; cpufreq_cmdline(p, comm); for (i = 0; len > i; i++) { if (!strncmp(comm, s[i], strlen(s[i]))) { pr_debug("detect %s:%s [%ld.%ld ms]\n", s[i], comm, limit->time_stamp, limit->time_stamp%1000); limit->current_time_stamp = ktime_to_ms(ktime_get()); if (0 == limit->time_stamp) { limit->time_stamp = limit->current_time_stamp; } else { /* restore : task is sleep status */ if ((limit->current_time_stamp - limit->time_stamp) > limit->op_timeout) cpufreq_set_max_frequency(limit, 0); } goto _exit; } } } /* restore : not find task */ cpufreq_set_max_frequency(limit, 0); limit->time_stamp = 0; _exit: hrtimer_start(&limit->limit_timer, ms_to_ktime(limit->timer_duration), HRTIMER_MODE_REL_PINNED); }
static int acpi_lid_notify_state(struct acpi_device *device, int state) { struct acpi_button *button = acpi_driver_data(device); int ret; ktime_t next_report; bool do_update; /* * In lid_init_state=ignore mode, if user opens/closes lid * frequently with "open" missing, and "last_time" is also updated * frequently, "close" cannot be delivered to the userspace. * So "last_time" is only updated after a timeout or an actual * switch. */ if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE || button->last_state != !!state) do_update = true; else do_update = false; next_report = ktime_add(button->last_time, ms_to_ktime(lid_report_interval)); if (button->last_state == !!state && ktime_after(ktime_get(), next_report)) { /* Complain the buggy firmware */ pr_warn_once("The lid device is not compliant to SW_LID.\n"); /* * Send the unreliable complement switch event: * * On most platforms, the lid device is reliable. However * there are exceptions: * 1. Platforms returning initial lid state as "close" by * default after booting/resuming: * https://bugzilla.kernel.org/show_bug.cgi?id=89211 * https://bugzilla.kernel.org/show_bug.cgi?id=106151 * 2. Platforms never reporting "open" events: * https://bugzilla.kernel.org/show_bug.cgi?id=106941 * On these buggy platforms, the usage model of the ACPI * lid device actually is: * 1. The initial returning value of _LID may not be * reliable. * 2. The open event may not be reliable. * 3. The close event is reliable. * * But SW_LID is typed as input switch event, the input * layer checks if the event is redundant. Hence if the * state is not switched, the userspace cannot see this * platform triggered reliable event. By inserting a * complement switch event, it then is guaranteed that the * platform triggered reliable one can always be seen by * the userspace. */ if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) { do_update = true; /* * Do generate complement switch event for "close" * as "close" is reliable and wrong "open" won't * trigger unexpected behaviors. * Do not generate complement switch event for * "open" as "open" is not reliable and wrong * "close" will trigger unexpected behaviors. */ if (!state) { input_report_switch(button->input, SW_LID, state); input_sync(button->input); } } } /* Send the platform triggered reliable event */ if (do_update) { acpi_handle_debug(device->handle, "ACPI LID %s\n", state ? "open" : "closed"); input_report_switch(button->input, SW_LID, !state); input_sync(button->input); button->last_state = !!state; button->last_time = ktime_get(); } if (state) acpi_pm_wakeup_event(&device->dev); ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE) ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { /* * It is also regarded as success if the notifier_chain * returns NOTIFY_OK or NOTIFY_DONE. */ ret = 0; } return ret; }