net/rfkill/input.c

Source file repositories/reference/linux-study-clean/net/rfkill/input.c

File Facts

System
Linux kernel
Corpus path
net/rfkill/input.c
Extension
.c
Size
8775 bytes
Lines
344
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rfkill_op_pending) {
			enum rfkill_sched_op op = rfkill_op;
			rfkill_op_pending = false;
			memset(rfkill_sw_pending, 0,
				sizeof(rfkill_sw_pending));
			spin_unlock_irq(&rfkill_op_lock);

			__rfkill_handle_global_op(op);

			spin_lock_irq(&rfkill_op_lock);

			/*
			 * handle global ops first -- during unlocked period
			 * we might have gotten a new global op.
			 */
			if (rfkill_op_pending)
				continue;
		}

		if (rfkill_is_epo_lock_active())
			continue;

		for (i = 0; i < NUM_RFKILL_TYPES; i++) {
			if (__test_and_clear_bit(i, rfkill_sw_pending)) {
				c = __test_and_clear_bit(i, rfkill_sw_state);
				spin_unlock_irq(&rfkill_op_lock);

				__rfkill_handle_normal_op(i, c);

				spin_lock_irq(&rfkill_op_lock);
			}
		}
	} while (rfkill_op_pending);
	spin_unlock_irq(&rfkill_op_lock);
}

static DECLARE_DELAYED_WORK(rfkill_op_work, rfkill_op_handler);
static unsigned long rfkill_last_scheduled;

static unsigned long rfkill_ratelimit(const unsigned long last)
{
	const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY);
	return time_after(jiffies, last + delay) ? 0 : delay;
}

static void rfkill_schedule_ratelimited(void)
{
	if (schedule_delayed_work(&rfkill_op_work,
				  rfkill_ratelimit(rfkill_last_scheduled)))
		rfkill_last_scheduled = jiffies;
}

static void rfkill_schedule_global_op(enum rfkill_sched_op op)
{
	unsigned long flags;

	spin_lock_irqsave(&rfkill_op_lock, flags);
	rfkill_op = op;
	rfkill_op_pending = true;
	if (op == RFKILL_GLOBAL_OP_EPO && !rfkill_is_epo_lock_active()) {
		/* bypass the limiter for EPO */
		mod_delayed_work(system_percpu_wq, &rfkill_op_work, 0);
		rfkill_last_scheduled = jiffies;
	} else
		rfkill_schedule_ratelimited();
	spin_unlock_irqrestore(&rfkill_op_lock, flags);
}

static void rfkill_schedule_toggle(enum rfkill_type type)
{
	unsigned long flags;

	if (rfkill_is_epo_lock_active())
		return;

	spin_lock_irqsave(&rfkill_op_lock, flags);
	if (!rfkill_op_pending) {
		__set_bit(type, rfkill_sw_pending);
		__change_bit(type, rfkill_sw_state);
		rfkill_schedule_ratelimited();
	}
	spin_unlock_irqrestore(&rfkill_op_lock, flags);
}

static void rfkill_schedule_evsw_rfkillall(int state)
{
	if (state)
		rfkill_schedule_global_op(rfkill_master_switch_op);
	else
		rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);

Annotation

Implementation Notes