diff options
Diffstat (limited to 'net/rfkill/core.c')
| -rw-r--r-- | net/rfkill/core.c | 144 |
1 files changed, 80 insertions, 64 deletions
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 0198191b756..b3b16c070a7 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> @@ -29,6 +27,7 @@ #include <linux/rfkill.h> #include <linux/sched.h> #include <linux/spinlock.h> +#include <linux/device.h> #include <linux/miscdevice.h> #include <linux/wait.h> #include <linux/poll.h> @@ -149,6 +148,20 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) rfkill_led_trigger_event(rfkill); } +const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) +{ + return rfkill->led_trigger.name; +} +EXPORT_SYMBOL(rfkill_get_led_trigger_name); + +void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name) +{ + BUG_ON(!rfkill); + + rfkill->ledtrigname = name; +} +EXPORT_SYMBOL(rfkill_set_led_trigger_name); + static int rfkill_led_trigger_register(struct rfkill *rfkill) { rfkill->led_trigger.name = rfkill->ledtrigname @@ -235,7 +248,7 @@ static bool __rfkill_set_hw_state(struct rfkill *rfkill, else rfkill->state &= ~RFKILL_BLOCK_HW; *change = prev != blocked; - any = rfkill->state & RFKILL_BLOCK_ANY; + any = !!(rfkill->state & RFKILL_BLOCK_ANY); spin_unlock_irqrestore(&rfkill->lock, flags); rfkill_led_trigger_event(rfkill); @@ -255,6 +268,7 @@ static bool __rfkill_set_hw_state(struct rfkill *rfkill, static void rfkill_set_block(struct rfkill *rfkill, bool blocked) { unsigned long flags; + bool prev, curr; int err; if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) @@ -269,6 +283,8 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) rfkill->ops->query(rfkill, rfkill->data); spin_lock_irqsave(&rfkill->lock, flags); + prev = rfkill->state & RFKILL_BLOCK_SW; + if (rfkill->state & RFKILL_BLOCK_SW) rfkill->state |= RFKILL_BLOCK_SW_PREV; else @@ -298,10 +314,13 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) } rfkill->state &= ~RFKILL_BLOCK_SW_SETCALL; rfkill->state &= ~RFKILL_BLOCK_SW_PREV; + curr = rfkill->state & RFKILL_BLOCK_SW; spin_unlock_irqrestore(&rfkill->lock, flags); rfkill_led_trigger_event(rfkill); - rfkill_event(rfkill); + + if (prev != curr) + rfkill_event(rfkill); } #ifdef CONFIG_RFKILL_INPUT @@ -324,7 +343,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked) rfkill_global_states[type].cur = blocked; list_for_each_entry(rfkill, &rfkill_list, node) { - if (rfkill->type != type) + if (rfkill->type != type && type != RFKILL_TYPE_ALL) continue; rfkill_set_block(rfkill, blocked); @@ -555,18 +574,18 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) } EXPORT_SYMBOL(rfkill_set_states); -static ssize_t rfkill_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%s\n", rfkill->name); } +static DEVICE_ATTR_RO(name); static const char *rfkill_get_type_str(enum rfkill_type type) { - BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1); + BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_NFC + 1); switch (type) { case RFKILL_TYPE_WLAN: @@ -583,59 +602,59 @@ static const char *rfkill_get_type_str(enum rfkill_type type) return "gps"; case RFKILL_TYPE_FM: return "fm"; + case RFKILL_TYPE_NFC: + return "nfc"; default: BUG(); } } -static ssize_t rfkill_type_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); } +static DEVICE_ATTR_RO(type); -static ssize_t rfkill_idx_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t index_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", rfkill->idx); } +static DEVICE_ATTR_RO(index); -static ssize_t rfkill_persistent_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t persistent_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", rfkill->persistent); } +static DEVICE_ATTR_RO(persistent); -static ssize_t rfkill_hard_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t hard_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); } +static DEVICE_ATTR_RO(hard); -static ssize_t rfkill_soft_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t soft_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); } -static ssize_t rfkill_soft_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t soft_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct rfkill *rfkill = to_rfkill(dev); unsigned long state; @@ -644,7 +663,7 @@ static ssize_t rfkill_soft_store(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - err = strict_strtoul(buf, 0, &state); + err = kstrtoul(buf, 0, &state); if (err) return err; @@ -655,8 +674,9 @@ static ssize_t rfkill_soft_store(struct device *dev, rfkill_set_block(rfkill, state); mutex_unlock(&rfkill_global_mutex); - return err ?: count; + return count; } +static DEVICE_ATTR_RW(soft); static u8 user_state_from_blocked(unsigned long state) { @@ -668,18 +688,16 @@ static u8 user_state_from_blocked(unsigned long state) return RFKILL_USER_STATE_UNBLOCKED; } -static ssize_t rfkill_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); } -static ssize_t rfkill_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct rfkill *rfkill = to_rfkill(dev); unsigned long state; @@ -688,7 +706,7 @@ static ssize_t rfkill_state_store(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - err = strict_strtoul(buf, 0, &state); + err = kstrtoul(buf, 0, &state); if (err) return err; @@ -700,34 +718,29 @@ static ssize_t rfkill_state_store(struct device *dev, rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); mutex_unlock(&rfkill_global_mutex); - return err ?: count; + return count; } +static DEVICE_ATTR_RW(state); -static ssize_t rfkill_claim_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t claim_show(struct device *dev, struct device_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", 0); } - -static ssize_t rfkill_claim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return -EOPNOTSUPP; -} - -static struct device_attribute rfkill_dev_attrs[] = { - __ATTR(name, S_IRUGO, rfkill_name_show, NULL), - __ATTR(type, S_IRUGO, rfkill_type_show, NULL), - __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), - __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), - __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), - __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), - __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), - __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), - __ATTR_NULL +static DEVICE_ATTR_RO(claim); + +static struct attribute *rfkill_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_type.attr, + &dev_attr_index.attr, + &dev_attr_persistent.attr, + &dev_attr_state.attr, + &dev_attr_claim.attr, + &dev_attr_soft.attr, + &dev_attr_hard.attr, + NULL, }; +ATTRIBUTE_GROUPS(rfkill_dev); static void rfkill_release(struct device *dev) { @@ -776,7 +789,8 @@ void rfkill_resume_polling(struct rfkill *rfkill) if (!rfkill->ops->poll) return; - schedule_work(&rfkill->poll_work.work); + queue_delayed_work(system_power_efficient_wq, + &rfkill->poll_work, 0); } EXPORT_SYMBOL(rfkill_resume_polling); @@ -807,7 +821,7 @@ static int rfkill_resume(struct device *dev) static struct class rfkill_class = { .name = "rfkill", .dev_release = rfkill_release, - .dev_attrs = rfkill_dev_attrs, + .dev_groups = rfkill_dev_groups, .dev_uevent = rfkill_dev_uevent, .suspend = rfkill_suspend, .resume = rfkill_resume, @@ -881,7 +895,8 @@ static void rfkill_poll(struct work_struct *work) */ rfkill->ops->poll(rfkill, rfkill->data); - schedule_delayed_work(&rfkill->poll_work, + queue_delayed_work(system_power_efficient_wq, + &rfkill->poll_work, round_jiffies_relative(POLL_INTERVAL)); } @@ -945,7 +960,8 @@ int __must_check rfkill_register(struct rfkill *rfkill) INIT_WORK(&rfkill->sync_work, rfkill_sync_work); if (rfkill->ops->poll) - schedule_delayed_work(&rfkill->poll_work, + queue_delayed_work(system_power_efficient_wq, + &rfkill->poll_work, round_jiffies_relative(POLL_INTERVAL)); if (!rfkill->persistent || rfkill_epo_lock_active) { @@ -1024,7 +1040,6 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) * start getting events from elsewhere but hold mtx to get * startup events added first */ - list_add(&data->list, &rfkill_fds); list_for_each_entry(rfkill, &rfkill_list, node) { ev = kzalloc(sizeof(*ev), GFP_KERNEL); @@ -1033,6 +1048,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); list_add_tail(&ev->list, &data->events); } + list_add(&data->list, &rfkill_fds); mutex_unlock(&data->mtx); mutex_unlock(&rfkill_global_mutex); |
