static int xpc_hb_checker(void *ignore) { int force_IRQ = 0; /* */ set_cpus_allowed_ptr(current, cpumask_of(XPC_HB_CHECK_CPU)); /* */ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); xpc_start_hb_beater(); while (!xpc_exiting) { dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have " "been received\n", (int)(xpc_hb_check_timeout - jiffies), xpc_activate_IRQ_rcvd); /* */ if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) { xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); dev_dbg(xpc_part, "checking remote heartbeats\n"); xpc_check_remote_hb(); /* */ if (is_shub()) force_IRQ = 1; } /* */ if (xpc_activate_IRQ_rcvd > 0 || force_IRQ != 0) { force_IRQ = 0; dev_dbg(xpc_part, "processing activate IRQs " "received\n"); xpc_arch_ops.process_activate_IRQ_rcvd(); } /* */ (void)wait_event_interruptible(xpc_activate_IRQ_wq, (time_is_before_eq_jiffies( xpc_hb_check_timeout) || xpc_activate_IRQ_rcvd > 0 || xpc_exiting)); } xpc_stop_hb_beater(); dev_dbg(xpc_part, "heartbeat checker is exiting\n"); /* */ complete(&xpc_hb_checker_exited); return 0; }
/* * This thread is responsible for nearly all of the partition * activation/deactivation. */ static int xpc_hb_checker(void *ignore) { int force_IRQ = 0; /* this thread was marked active by xpc_hb_init() */ set_cpus_allowed_ptr(current, cpumask_of(XPC_HB_CHECK_CPU)); /* set our heartbeating to other partitions into motion */ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); xpc_start_hb_beater(); while (!xpc_exiting) { dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have " "been received\n", (int)(xpc_hb_check_timeout - jiffies), xpc_activate_IRQ_rcvd); /* checking of remote heartbeats is skewed by IRQ handling */ if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) { xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); dev_dbg(xpc_part, "checking remote heartbeats\n"); xpc_check_remote_hb(); /* * On sn2 we need to periodically recheck to ensure no * IRQ/amo pairs have been missed. */ if (is_shub()) force_IRQ = 1; } /* check for outstanding IRQs */ if (xpc_activate_IRQ_rcvd > 0 || force_IRQ != 0) { force_IRQ = 0; dev_dbg(xpc_part, "processing activate IRQs " "received\n"); xpc_process_activate_IRQ_rcvd(); } /* wait for IRQ or timeout */ (void)wait_event_interruptible(xpc_activate_IRQ_wq, (time_is_before_eq_jiffies( xpc_hb_check_timeout) || xpc_activate_IRQ_rcvd > 0 || xpc_exiting)); } xpc_stop_hb_beater(); dev_dbg(xpc_part, "heartbeat checker is exiting\n"); /* mark this thread as having exited */ complete(&xpc_hb_checker_exited); return 0; }
/** * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit * @hwlock: the hwspinlock to be locked * @timeout: timeout value in msecs * @mode: mode which controls whether local interrupts are disabled or not * @flags: a pointer to where the caller's interrupt state will be saved at (if * requested) * * This function locks the given @hwlock. If the @hwlock * is already taken, the function will busy loop waiting for it to * be released, but give up after @timeout msecs have elapsed. * * Upon a successful return from this function, preemption is disabled * (and possibly local interrupts, too), so the caller must not sleep, * and is advised to release the hwspinlock as soon as possible. * This is required in order to minimize remote cores polling on the * hardware interconnect. * * The user decides whether local interrupts are disabled or not, and if yes, * whether he wants their previous state to be saved. It is up to the user * to choose the appropriate @mode of operation, exactly the same way users * should decide between spin_lock, spin_lock_irq and spin_lock_irqsave. * * Returns 0 when the @hwlock was successfully taken, and an appropriate * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still * busy after @timeout msecs). The function will never sleep. */ int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to, int mode, unsigned long *flags) { int ret; unsigned long expire; expire = msecs_to_jiffies(to) + jiffies; for (;;) { /* Try to take the hwspinlock */ ret = __hwspin_trylock(hwlock, mode, flags); if (ret != -EBUSY) break; /* * The lock is already taken, let's check if the user wants * us to try again */ if (time_is_before_eq_jiffies(expire)) return -ETIMEDOUT; /* * Allow platform-specific relax handlers to prevent * hogging the interconnect (no sleeping, though) */ if (hwlock->bank->ops->relax) hwlock->bank->ops->relax(hwlock); } return ret; }
static int ar100_wait_ready(unsigned int timeout) { unsigned long expire; expire = msecs_to_jiffies(timeout) + jiffies; /* wait ar100 startup ready */ while (1) { /* * linux cpu interrupt is disable now, * we should query message by hand. */ struct ar100_message *pmessage = ar100_hwmsgbox_query_message(); if (pmessage == NULL) { if (time_is_before_eq_jiffies(expire)) { return -ETIMEDOUT; } /* try to query again */ continue; } /* query valid message */ if (pmessage->type == AR100_STARTUP_NOTIFY) { /* check ar100 software and driver version match or not */ if (pmessage->paras[0] != AR100_VERSIONS) { AR100_ERR("ar100 firmware and driver version not matched\n"); return -EINVAL; } /* received ar100 startup ready message */ AR100_INF("ar100 startup ready\n"); if ((pmessage->attr & AR100_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & AR100_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ AR100_INF("ar100 startup notify message feedback\n"); pmessage->paras[0] = virt_to_phys((void *)&ar100_binary_start); ar100_hwmsgbox_feedback_message(pmessage, AR100_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ AR100_INF("ar100 startup notify message free directly\n"); ar100_message_free(pmessage); } break; } /* * invalid message detected, ignore it. * by sunny at 2012-7-6 18:34:38. */ AR100_WRN("ar100 startup waiting ignore message\n"); if ((pmessage->attr & AR100_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & AR100_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ ar100_hwmsgbox_send_message(pmessage, AR100_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ ar100_message_free(pmessage); } /* we need waiting continue */ } return 0; }
/* * Timer to produce the heartbeat. The timer structures function is * already set when this is initially called. A tunable is used to * specify when the next timeout should occur. */ static void xpc_hb_beater(unsigned long dummy) { xpc_increment_heartbeat(); if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) wake_up_interruptible(&xpc_activate_IRQ_wq); xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ); add_timer(&xpc_hb_timer); }
/** * nfp_cpp_mutex_lock() - Lock a mutex handle, using the NFP MU Atomic Engine * @mutex: NFP CPP Mutex handle * * Return: 0 on success, or -errno on failure */ int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex) { unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ; unsigned long err_at = jiffies + NFP_MUTEX_WAIT_ERROR * HZ; unsigned int timeout_ms = 1; int err; /* We can't use a waitqueue here, because the unlocker * might be on a separate CPU. * * So just wait for now. */ for (;;) { err = nfp_cpp_mutex_trylock(mutex); if (err != -EBUSY) break; err = msleep_interruptible(timeout_ms); if (err != 0) { nfp_info(mutex->cpp, "interrupted waiting for NFP mutex\n"); return -ERESTARTSYS; } if (time_is_before_eq_jiffies(warn_at)) { warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ; nfp_warn(mutex->cpp, "Warning: waiting for NFP mutex [depth:%hd target:%d addr:%llx key:%08x]\n", mutex->depth, mutex->target, mutex->address, mutex->key); } if (time_is_before_eq_jiffies(err_at)) { nfp_err(mutex->cpp, "Error: mutex wait timed out\n"); return -EBUSY; } } return err; }
/** * nfp_resource_acquire() - Acquire a resource handle * @cpp: NFP CPP handle * @name: Name of the resource * * NOTE: This function locks the acquired resource * * Return: NFP Resource handle, or ERR_PTR() */ struct nfp_resource * nfp_resource_acquire(struct nfp_cpp *cpp, const char *name) { unsigned long warn_at = jiffies + 15 * HZ; struct nfp_cpp_mutex *dev_mutex; struct nfp_resource *res; int err; res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) return ERR_PTR(-ENOMEM); strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ); dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET, NFP_RESOURCE_TBL_BASE, NFP_RESOURCE_TBL_KEY); if (!dev_mutex) { kfree(res); return ERR_PTR(-ENOMEM); } for (;;) { err = nfp_resource_try_acquire(cpp, res, dev_mutex); if (!err) break; if (err != -EBUSY) goto err_free; err = msleep_interruptible(1); if (err != 0) { err = -ERESTARTSYS; goto err_free; } if (time_is_before_eq_jiffies(warn_at)) { warn_at = jiffies + 60 * HZ; nfp_warn(cpp, "Warning: waiting for NFP resource %s\n", name); } } nfp_cpp_mutex_free(dev_mutex); return res; err_free: nfp_cpp_mutex_free(dev_mutex); kfree(res); return ERR_PTR(err); }
static int nfp_net_reconfig_wait(struct nfp_net *nn, unsigned long deadline) { bool timed_out = false; /* Poll update field, waiting for NFP to ack the config */ while (!nfp_net_reconfig_check_done(nn, timed_out)) { msleep(1); timed_out = time_is_before_eq_jiffies(deadline); } if (nn_readl(nn, NFP_NET_CFG_UPDATE) & NFP_NET_CFG_UPDATE_ERR) return -EIO; return timed_out ? -EIO : 0; }
/** * ir_timer_keyup() - generates a keyup event after a timeout * @cookie: a pointer to struct ir_input_dev passed to setup_timer() * * This routine will generate a keyup event some time after a keydown event * is generated when no further activity has been detected. */ static void ir_timer_keyup(unsigned long cookie) { struct ir_input_dev *ir = (struct ir_input_dev *)cookie; unsigned long flags; /* * ir->keyup_jiffies is used to prevent a race condition if a * hardware interrupt occurs at this point and the keyup timer * event is moved further into the future as a result. * * The timer will then be reactivated and this function called * again in the future. We need to exit gracefully in that case * to allow the input subsystem to do its auto-repeat magic or * a keyup event might follow immediately after the keydown. */ spin_lock_irqsave(&ir->keylock, flags); if (time_is_before_eq_jiffies(ir->keyup_jiffies)) ir_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); }
static int arisc_wait_ready(unsigned int timeout) { unsigned long expire; #ifdef CONFIG_SUNXI_MODULE struct sunxi_module_info arisc_module_info; #endif expire = msecs_to_jiffies(timeout) + jiffies; /* wait arisc startup ready */ while (1) { /* * linux cpu interrupt is disable now, * we should query message by hand. */ struct arisc_message *pmessage = arisc_hwmsgbox_query_message(); if (pmessage == NULL) { if (time_is_before_eq_jiffies(expire)) { return -ETIMEDOUT; } /* try to query again */ continue; } /* query valid message */ if (pmessage->type == ARISC_STARTUP_NOTIFY) { /* check arisc software and driver version match or not */ if (pmessage->paras[0] != ARISC_VERSIONS) { ARISC_ERR("arisc firmware:%d and driver version:%d not matched\n", pmessage->paras[0], ARISC_VERSIONS); return -EINVAL; } else { /* printf the main and sub version string */ memcpy((void *)arisc_version, (const void*)(&(pmessage->paras[1])), 40); ARISC_LOG("arisc version: [%s]\n", arisc_version); #ifdef CONFIG_SUNXI_MODULE strncpy((char *)arisc_module_info.module, (const char *)"arisc", 16); strncpy((char *)arisc_module_info.version, (const char *)arisc_version, 16); sunxi_module_info_register(&arisc_module_info); #endif } /* received arisc startup ready message */ ARISC_INF("arisc startup ready\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ ARISC_INF("arisc startup notify message feedback\n"); pmessage->paras[0] = virt_to_phys((void *)&arisc_binary_start); arisc_hwmsgbox_feedback_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ ARISC_INF("arisc startup notify message free directly\n"); arisc_message_free(pmessage); } break; } /* * invalid message detected, ignore it. * by sunny at 2012-7-6 18:34:38. */ ARISC_WRN("arisc startup waiting ignore message\n"); if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) || (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) { /* synchronous message, just feedback it */ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); } else { /* asyn message, free message directly */ arisc_message_free(pmessage); } /* we need waiting continue */ } return 0; }