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;
}
示例#2
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;
}
示例#5
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);
}
示例#6
0
/**
 * 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;
}
示例#7
0
/**
 * 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);
}
示例#8
0
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;
}
示例#9
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);
}
示例#10
0
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;
}