bool registered;
bool suspended;
+ bool persistent;
const struct rfkill_ops *ops;
void *data;
"Default initial state for all radio types, 0 = radio off");
static struct {
- bool cur, def;
+ bool cur, sav;
} rfkill_global_states[NUM_RFKILL_TYPES];
-static unsigned long rfkill_states_default_locked;
-
static bool rfkill_epo_lock_active;
unsigned long flags;
int err;
+ if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP))
+ return;
+
/*
* Some platforms (...!) generate input events which affect the
* _hard_ kill state -- whenever something tries to change the
rfkill->state |= RFKILL_BLOCK_SW_SETCALL;
spin_unlock_irqrestore(&rfkill->lock, flags);
- if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP))
- return;
-
err = rfkill->ops->set_block(rfkill->data, blocked);
spin_lock_irqsave(&rfkill->lock, flags);
rfkill_set_block(rfkill, true);
for (i = 0; i < NUM_RFKILL_TYPES; i++) {
- rfkill_global_states[i].def = rfkill_global_states[i].cur;
+ rfkill_global_states[i].sav = rfkill_global_states[i].cur;
rfkill_global_states[i].cur = true;
}
rfkill_epo_lock_active = false;
for (i = 0; i < NUM_RFKILL_TYPES; i++)
- __rfkill_switch_all(i, rfkill_global_states[i].def);
+ __rfkill_switch_all(i, rfkill_global_states[i].sav);
mutex_unlock(&rfkill_global_mutex);
}
}
#endif
-void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked)
-{
- BUG_ON(type == RFKILL_TYPE_ALL);
-
- mutex_lock(&rfkill_global_mutex);
-
- /* don't allow unblock when epo */
- if (rfkill_epo_lock_active && !blocked)
- goto out;
-
- /* too late */
- if (rfkill_states_default_locked & BIT(type))
- goto out;
-
- rfkill_states_default_locked |= BIT(type);
-
- rfkill_global_states[type].cur = blocked;
- rfkill_global_states[type].def = blocked;
- out:
- mutex_unlock(&rfkill_global_mutex);
-}
-EXPORT_SYMBOL(rfkill_set_global_sw_state);
-
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
{
blocked = blocked || hwblock;
spin_unlock_irqrestore(&rfkill->lock, flags);
- if (!rfkill->registered)
- return blocked;
+ if (!rfkill->registered) {
+ rfkill->persistent = true;
+ } else {
+ if (prev != blocked && !hwblock)
+ schedule_work(&rfkill->uevent_work);
- if (prev != blocked && !hwblock)
- schedule_work(&rfkill->uevent_work);
-
- rfkill_led_trigger_event(rfkill);
+ rfkill_led_trigger_event(rfkill);
+ }
return blocked;
}
spin_unlock_irqrestore(&rfkill->lock, flags);
- if (!rfkill->registered)
- return;
-
- if (swprev != sw || hwprev != hw)
- schedule_work(&rfkill->uevent_work);
+ if (!rfkill->registered) {
+ rfkill->persistent = true;
+ } else {
+ if (swprev != sw || hwprev != hw)
+ schedule_work(&rfkill->uevent_work);
- rfkill_led_trigger_event(rfkill);
+ rfkill_led_trigger_event(rfkill);
+ }
}
EXPORT_SYMBOL(rfkill_set_states);
struct rfkill *rfkill = to_rfkill(dev);
bool cur;
- mutex_lock(&rfkill_global_mutex);
- cur = rfkill_global_states[rfkill->type].cur;
+ cur = !!(rfkill->state & RFKILL_BLOCK_SW);
rfkill_set_block(rfkill, cur);
- mutex_unlock(&rfkill_global_mutex);
rfkill->suspended = false;
- schedule_work(&rfkill->uevent_work);
-
rfkill_resume_polling(rfkill);
return 0;
.resume = rfkill_resume,
};
+bool rfkill_blocked(struct rfkill *rfkill)
+{
+ unsigned long flags;
+ u32 state;
+
+ spin_lock_irqsave(&rfkill->lock, flags);
+ state = rfkill->state;
+ spin_unlock_irqrestore(&rfkill->lock, flags);
+
+ return !!(state & RFKILL_BLOCK_ANY);
+}
+EXPORT_SYMBOL(rfkill_blocked);
+
struct rfkill * __must_check rfkill_alloc(const char *name,
struct device *parent,
dev_set_name(dev, "rfkill%lu", rfkill_no);
rfkill_no++;
- if (!(rfkill_states_default_locked & BIT(rfkill->type))) {
- /* first of its kind */
- BUILD_BUG_ON(NUM_RFKILL_TYPES >
- sizeof(rfkill_states_default_locked) * 8);
- rfkill_states_default_locked |= BIT(rfkill->type);
- rfkill_global_states[rfkill->type].cur =
- rfkill_global_states[rfkill->type].def;
- }
-
list_add_tail(&rfkill->node, &rfkill_list);
error = device_add(dev);
rfkill->registered = true;
- if (rfkill->ops->poll) {
- INIT_DELAYED_WORK(&rfkill->poll_work, rfkill_poll);
+ INIT_DELAYED_WORK(&rfkill->poll_work, rfkill_poll);
+ INIT_WORK(&rfkill->uevent_work, rfkill_uevent_work);
+ INIT_WORK(&rfkill->sync_work, rfkill_sync_work);
+
+ if (rfkill->ops->poll)
schedule_delayed_work(&rfkill->poll_work,
round_jiffies_relative(POLL_INTERVAL));
- }
- INIT_WORK(&rfkill->uevent_work, rfkill_uevent_work);
+ if (!rfkill->persistent || rfkill_epo_lock_active) {
+ schedule_work(&rfkill->sync_work);
+ } else {
+#ifdef CONFIG_RFKILL_INPUT
+ bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW);
+
+ if (!atomic_read(&rfkill_input_disabled))
+ __rfkill_switch_all(rfkill->type, soft_blocked);
+#endif
+ }
- INIT_WORK(&rfkill->sync_work, rfkill_sync_work);
- schedule_work(&rfkill->sync_work);
rfkill_send_events(rfkill, RFKILL_OP_ADD);
mutex_unlock(&rfkill_global_mutex);
#ifdef CONFIG_RFKILL_INPUT
if (data->input_handler)
- atomic_dec(&rfkill_input_disabled);
+ if (atomic_dec_return(&rfkill_input_disabled) == 0)
+ printk(KERN_DEBUG "rfkill: input handler enabled\n");
#endif
kfree(data);
mutex_lock(&data->mtx);
if (!data->input_handler) {
- atomic_inc(&rfkill_input_disabled);
+ if (atomic_inc_return(&rfkill_input_disabled) == 1)
+ printk(KERN_DEBUG "rfkill: input handler disabled\n");
data->input_handler = true;
}
int i;
for (i = 0; i < NUM_RFKILL_TYPES; i++)
- rfkill_global_states[i].def = !rfkill_default_state;
+ rfkill_global_states[i].cur = !rfkill_default_state;
error = class_register(&rfkill_class);
if (error)