static void handle_only_power_key(unsigned int code, int value) { struct gpio_input_state *ds = gb_ddata; if (code == KEY_POWER && ds->disable_reset_flag != 0) { if (value) { queue_delayed_work(ds->disable_reset_wq, &ds->clear_hw_reset_work, msecs_to_jiffies(0)); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); #endif } else { __cancel_delayed_work(&ds->clear_hw_reset_work); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif } } }
static void handle_transition_according_to_power_key(int value) { struct gpio_input_state *ds = gb_ddata; #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif if (ds->disable_reset_flag == 0 && value) { #ifdef CONFIG_POWER_VOLUP_RESET wake_lock_timeout(&key_reset_clr_wake_lock, msecs_to_jiffies(1000)); if (!schedule_delayed_work(&power_key_check_reset_work, msecs_to_jiffies(0))) #else wake_lock_timeout(&key_reset_clr_wake_lock, PWRKEYCHKRST_WAKELOCK_TIMEOUT); if (!schedule_delayed_work(&power_key_check_reset_work, PWRKEYCHKRST_DELAY)) #endif KEY_LOGI("[PWR] the reset work in already in the queue\n"); } else if (ds->disable_reset_flag != 0) { handle_only_power_key(KEY_POWER, value); } }
/* * remove hrtimer, called with base lock held */ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (hrtimer_is_queued(timer)) { unsigned long state; int reprogram; /* * Remove the timer and force reprogramming when high * resolution mode is active and the timer is on the current * CPU. If we remove a timer on another CPU, reprogramming is * skipped. The interrupt event on this CPU is fired and * reprogramming happens in the interrupt handler. This is a * rare case and less expensive than a smp call. */ debug_deactivate(timer); timer_stats_hrtimer_clear_start_info(timer); reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); /* * We must preserve the CALLBACK state flag here, * otherwise we could move the timer base in * switch_hrtimer_base. */ state = timer->state & HRTIMER_STATE_CALLBACK; __remove_hrtimer(timer, base, state, reprogram); return 1; } return 0; }
/** * hrtimer_forward - forward the timer expiry * @timer: hrtimer to forward * @now: forward past this time * @interval: the interval to forward * * Forward the timer expiry so it will expire in the future. * Returns the number of overruns. */ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) { u64 orun = 1; ktime_t delta; WARN_ON(hrtimer_is_queued(timer)); delta = ktime_sub(now, hrtimer_get_expires(timer)); if (delta.tv64 < 0) return 0; if (interval.tv64 < timer->base->resolution.tv64) interval.tv64 = timer->base->resolution.tv64; if (unlikely(delta.tv64 >= interval.tv64)) { s64 incr = ktime_to_ns(interval); orun = ktime_divns(delta, incr); hrtimer_add_expires_ns(timer, incr * orun); if (hrtimer_get_expires_tv64(timer) > now.tv64) return orun; /* * This (and the ktime_add() below) is the * correction for exact: */ orun++; } hrtimer_add_expires(timer, interval); return orun; }
/* * remove hrtimer, called with base lock held */ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) { if (hrtimer_is_queued(timer)) { u8 state = timer->state; int reprogram; /* * Remove the timer and force reprogramming when high * resolution mode is active and the timer is on the current * CPU. If we remove a timer on another CPU, reprogramming is * skipped. The interrupt event on this CPU is fired and * reprogramming happens in the interrupt handler. This is a * rare case and less expensive than a smp call. */ debug_deactivate(timer); timer_stats_hrtimer_clear_start_info(timer); reprogram = base->cpu_base == this_cpu_ptr(&hrtimer_bases); if (!restart) state = HRTIMER_STATE_INACTIVE; __remove_hrtimer(timer, base, state, reprogram); return 1; } return 0; }
static int hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct hip04_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; unsigned int tx_head = priv->tx_head, count; struct tx_desc *desc = &priv->tx_desc[tx_head]; dma_addr_t phys; smp_rmb(); count = tx_count(tx_head, ACCESS_ONCE(priv->tx_tail)); if (count == (TX_DESC_NUM - 1)) { netif_stop_queue(ndev); return NETDEV_TX_BUSY; } phys = dma_map_single(&ndev->dev, skb->data, skb->len, DMA_TO_DEVICE); if (dma_mapping_error(&ndev->dev, phys)) { dev_kfree_skb(skb); return NETDEV_TX_OK; } priv->tx_skb[tx_head] = skb; priv->tx_phys[tx_head] = phys; desc->send_addr = cpu_to_be32(phys); desc->send_size = cpu_to_be32(skb->len); desc->cfg = cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV); phys = priv->tx_desc_dma + tx_head * sizeof(struct tx_desc); desc->wb_addr = cpu_to_be32(phys); skb_tx_timestamp(skb); hip04_set_xmit_desc(priv, phys); priv->tx_head = TX_NEXT(tx_head); count++; netdev_sent_queue(ndev, skb->len); stats->tx_bytes += skb->len; stats->tx_packets++; /* Ensure tx_head update visible to tx reclaim */ smp_wmb(); /* queue is getting full, better start cleaning up now */ if (count >= priv->tx_coalesce_frames) { if (napi_schedule_prep(&priv->napi)) { /* disable rx interrupt and timer */ priv->reg_inten &= ~(RCV_INT); writel_relaxed(DEF_INT_MASK & ~RCV_INT, priv->base + PPE_INTEN); hrtimer_cancel(&priv->tx_coalesce_timer); __napi_schedule(&priv->napi); } } else if (!hrtimer_is_queued(&priv->tx_coalesce_timer)) { /* cleanup not pending yet, start a new timer */ hip04_start_tx_timer(priv); } return NETDEV_TX_OK; }
static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (hrtimer_is_queued(timer)) { unsigned long state; int reprogram; debug_deactivate(timer); timer_stats_hrtimer_clear_start_info(timer); reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); state = timer->state & HRTIMER_STATE_CALLBACK; __remove_hrtimer(timer, base, state, reprogram); return 1; } return 0; }
static inline void start_tx_timer(struct mem_link_device *mld, struct hrtimer *timer) { struct link_device *ld = &mld->link_dev; struct modem_ctl *mc = ld->mc; unsigned long flags; spin_lock_irqsave(&mc->lock, flags); if (unlikely(cp_offline(mc))) goto exit; if (!hrtimer_is_queued(timer)) { ktime_t ktime = ktime_set(0, tx_timer_ns); hrtimer_start(timer, ktime, HRTIMER_MODE_REL); } exit: spin_unlock_irqrestore(&mc->lock, flags); }
static void handle_power_key_reset(unsigned int code, int value) { #ifdef CONFIG_POWER_VOLUP_RESET uint8_t i = 0, read_val = 0; struct gpio_event_input_info *aa = gis; if (code == KEY_POWER || code == KEY_VOLUMEUP) { if (!value && code == KEY_VOLUMEUP) { KEY_LOGI("[VUP] start count for power key led off\n"); schedule_delayed_work(&power_key_led_off_work, PWRKEYLEDOFF_DELAY); } for (i = 0; (i < aa->keymap_size && code != KEY_POWER); i++) { if (aa->keymap[i].code == KEY_POWER) { read_val = gpio_get_value(aa->keymap[i].gpio); KEY_LOGI("Idx[%d] GPIO_%d:PWR is %s\n", i, aa->keymap[i].gpio, (read_val ? "NOT pressed" : "PRESSED" )); if (read_val) { #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); #endif return; } else { KEY_LOGI("[PWR+VUP] start count for power key led on\n"); schedule_delayed_work(&power_key_led_on_work, PWRKEYLEDON_DELAY); power_key_led_requested = 1; #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); #endif break; } } } for (i = aa->keymap_size; (i > 0 && code != KEY_VOLUMEUP); i--) { if (aa->keymap[i-1].code == KEY_VOLUMEUP) { read_val = gpio_get_value(aa->keymap[i-1].gpio); KEY_LOGI("Idx[%d] GPIO_%d:VOL_UP is %s\n", i-1, aa->keymap[i-1].gpio, (read_val ? "NOT pressed" : "PRESSED" )); if (read_val) { goto KEY_PWR; } else { KEY_LOGI("[VUP+PWR] start count for power key led on\n"); schedule_delayed_work(&power_key_led_on_work, PWRKEYLEDON_DELAY); power_key_led_requested = 1; break; } } } KEY_PWR: #else if (code == KEY_POWER) { #endif if (value) { #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 1; KEY_LOGD("%s: Enable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); #endif #ifdef CONFIG_POWER_VOLUP_RESET wake_lock_timeout(&key_reset_clr_wake_lock, msecs_to_jiffies(2000)); KEY_LOGI("[PWR] start count for power key check reset\n"); if (!schedule_delayed_work(&power_key_check_reset_work, msecs_to_jiffies(1000))) #else wake_lock_timeout(&key_reset_clr_wake_lock, PWRKEYCHKRST_WAKELOCK_TIMEOUT); KEY_LOGI("[PWR] start count for power key check reset\n"); if (!schedule_delayed_work(&power_key_check_reset_work, PWRKEYCHKRST_DELAY)) #endif KEY_LOGI("[PWR] the reset work in already in the queue\n"); } else { KEY_LOGI("[PWR] start count for power key clear check\n"); if (!schedule_delayed_work(&power_key_clr_check_work, PWRKEYCLRCHK_DELAY)) KEY_LOGI("[PWR] the clear work in already in the queue\n"); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif } } } #ifdef CONFIG_KPDPWR_S2_DVDD_RESET static enum hrtimer_restart clr_kpd_rst_timer_func(struct hrtimer *timer) { if (qpnp_get_reset_en(PON_KPDPWR) > 0) { qpnp_config_reset_enable(PON_KPDPWR, 0); qpnp_config_reset_enable(PON_KPDPWR, 1); hrtimer_start(&enable_kpd_s2_timer, ktime_set(0, 0), HRTIMER_MODE_REL); } return HRTIMER_NORESTART; } static enum hrtimer_restart enable_kpd_s2_timer_func(struct hrtimer *timer) { qpnp_config_reset_enable(PON_KPDPWR, 1); if (clear_kpdpwr_s2_rst_flag) { hrtimer_start(&clr_kpd_reset_timer, ktime_set(0, KPDPWR_CLR_RESET_TIMER), HRTIMER_MODE_REL); } else { if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); } return HRTIMER_NORESTART; }
static void power_key_check_reset_work_func(struct work_struct *dummy) { struct gpio_event_input_info *aa = gis; #ifdef CONFIG_POWER_VOLUP_RESET uint8_t val = 0, i = 0; #else int pocket_mode = 0; #endif KEY_LOGI("[PWR] %s\n", __func__); #ifdef CONFIG_OF if ((aa->dt_clear_hw_reset)) { if (aa->info.rrm1_mode) { KEY_LOGI(" Power key check in Lab Test RRM1 mode.\n"); aa->dt_clear_hw_reset(aa->clr_gpio); #else if ((aa->clear_hw_reset)) { if (aa->info.rrm1_mode) { printk(KERN_INFO "[KEY] Power key check in Lab Test RRM1 mode.\n"); aa->clear_hw_reset(); #endif #ifndef CONFIG_POWER_VOLUP_RESET } else if (board_mfg_mode() == MFG_MODE_NORMAL) { pocket_mode = power_key_check_in_pocket(); if (pocket_mode) { printk(KERN_INFO "[KEY] power_key_check_in_pocket = %d\n", pocket_mode); #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } } else printk(KERN_INFO "[KEY] Not in normal OS mode, mode=%d\n", board_mfg_mode()); #else } else { printk(KERN_INFO "[KEY] OS Mode=%d\n", board_mfg_mode()); for (i = 0; i < aa->keymap_size; i++) { if (aa->keymap[i].code == KEY_VOLUMEUP) { val = gpio_get_value(aa->keymap[i].gpio); break; } } if (!val) { KEY_LOGI("HW RESET continue"); } else { #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } } #endif } else { KEY_LOGI("[PWR] No reset clear function\n"); } handle_power_key_reset(KEY_POWER, 1); } static DECLARE_DELAYED_WORK(power_key_check_reset_work, power_key_check_reset_work_func); static void power_key_clr_check_work_func(struct work_struct *dummy) { #ifdef CONFIG_POWER_VOLUP_RESET uint8_t i = 0, val = 0, pwr_idx = 0; struct gpio_event_input_info *aa = gis; for (i = 0; i < aa->keymap_size; i++) { if (aa->keymap[i].code == KEY_VOLUMEUP) { val = gpio_get_value(aa->keymap[i].gpio); if (val) { KEY_LOGI("volUP clear"); #ifdef CONFIG_OF aa->dt_clear_hw_reset(aa->clr_gpio); #else aa->clear_hw_reset(); #endif } break; } if (aa->keymap[i].code == KEY_POWER) pwr_idx = i; } val = gpio_get_value(aa->keymap[pwr_idx].gpio); if (val) { #endif if (cancel_delayed_work_sync(&power_key_check_reset_work)) KEY_LOGI("[PWR] cancel power key check reset work successfully\n"); else KEY_LOGI("[PWR] cancel power key check reset work unsuccessfully\n"); #ifdef CONFIG_KPDPWR_S2_DVDD_RESET clear_kpdpwr_s2_rst_flag = 0; KEY_LOGD("%s: Disable kpdpwr s2 reset clear up [%d]\n", __func__, clear_kpdpwr_s2_rst_flag); if (hrtimer_is_queued(&clr_kpd_reset_timer)) hrtimer_cancel(&clr_kpd_reset_timer); if (hrtimer_is_queued(&enable_kpd_s2_timer)) hrtimer_cancel(&enable_kpd_s2_timer); #endif #ifdef CONFIG_POWER_VOLUP_RESET } #endif wake_unlock(&key_reset_clr_wake_lock); }