static enum hrtimer_restart tx_timer_func(struct hrtimer *timer) { struct mem_link_device *mld; struct link_device *ld; struct modem_ctl *mc; int i; bool need_schedule; u16 mask; mld = container_of(timer, struct mem_link_device, tx_timer); ld = &mld->link_dev; mc = ld->mc; if (unlikely(cp_online(mc) && !ipc_active(mld))) goto exit; need_schedule = false; mask = 0; for (i = IPC_FMT; i < MAX_SIPC5_DEV; i++) { struct mem_ipc_device *dev = mld->dev[i]; int ret; if (unlikely(under_tx_flow_ctrl(mld, dev))) { ret = check_tx_flow_ctrl(mld, dev); if (ret < 0) { if (ret == -EBUSY || ret == -ETIME) { need_schedule = true; continue; } else { mem_forced_cp_crash(mld); goto exit; } } } ret = tx_frames_to_dev(mld, dev); if (unlikely(ret < 0)) { if (ret == -EBUSY || ret == -ENOSPC) { need_schedule = true; start_tx_flow_ctrl(mld, dev); continue; } else { mem_forced_cp_crash(mld); goto exit; } } mask |= msg_mask(dev); if (!skb_queue_empty(dev->skb_txq)) need_schedule = true; } if (mask) send_ipc_irq(mld, mask2int(mask)); if (need_schedule) { ktime_t ktime = ns_to_ktime(ms2ns(TX_PERIOD_MS)); hrtimer_forward_now(timer, ktime); return HRTIMER_RESTART; } exit: #ifdef CONFIG_LINK_POWER_MANAGEMENT mld->permit_cp_sleep(mld); #endif return HRTIMER_NORESTART; }
static enum hrtimer_restart tx_timer_func(struct hrtimer *timer) { struct mem_link_device *mld; struct link_device *ld; struct modem_ctl *mc; int i; bool need_schedule; u16 mask; unsigned long flags; mld = container_of(timer, struct mem_link_device, tx_timer); ld = &mld->link_dev; mc = ld->mc; need_schedule = false; mask = 0; spin_lock_irqsave(&mc->lock, flags); if (unlikely(!ipc_active(mld))) goto exit; #ifdef CONFIG_LINK_POWER_MANAGEMENT_WITH_FSM if (mld->link_active) { if (!mld->link_active(mld)) { need_schedule = true; goto exit; } } #endif for (i = 0; i < MAX_SIPC5_DEVICES; i++) { struct mem_ipc_device *dev = mld->dev[i]; int ret; if (unlikely(under_tx_flow_ctrl(mld, dev))) { ret = check_tx_flow_ctrl(mld, dev); if (ret < 0) { if (ret == -EBUSY || ret == -ETIME) { need_schedule = true; continue; } else { mem_forced_cp_crash(mld); need_schedule = false; goto exit; } } } ret = tx_frames_to_dev(mld, dev); if (unlikely(ret < 0)) { if (ret == -EBUSY || ret == -ENOSPC) { need_schedule = true; start_tx_flow_ctrl(mld, dev); continue; } else { mem_forced_cp_crash(mld); need_schedule = false; goto exit; } } if (ret > 0) mask |= msg_mask(dev); if (!skb_queue_empty(dev->skb_txq)) need_schedule = true; } if (!need_schedule) { for (i = 0; i < MAX_SIPC5_DEVICES; i++) { if (!txq_empty(mld->dev[i])) { need_schedule = true; break; } } } if (mask) send_ipc_irq(mld, mask2int(mask)); exit: if (need_schedule) { ktime_t ktime = ktime_set(0, ms2ns(TX_PERIOD_MS)); hrtimer_start(timer, ktime, HRTIMER_MODE_REL); } spin_unlock_irqrestore(&mc->lock, flags); return HRTIMER_NORESTART; }