Merge tag 'mac80211-next-for-davem-2016-02-26' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== Here's another round of updates for -next: * big A-MSDU RX performance improvement (avoid linearize of paged RX) * rfkill changes: cleanups, documentation, platform properties * basic PBSS support in cfg80211 * MU-MIMO action frame processing support * BlockAck reordering & duplicate detection offload support * various cleanups & little fixes ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -41,5 +41,4 @@ config RFKILL_GPIO
|
||||
default n
|
||||
help
|
||||
If you say yes here you get support of a generic gpio RFKILL
|
||||
driver. The platform should fill in the appropriate fields in the
|
||||
rfkill_gpio_platform_data structure and pass that to the driver.
|
||||
driver.
|
||||
|
@@ -57,6 +57,8 @@ struct rfkill {
|
||||
|
||||
bool registered;
|
||||
bool persistent;
|
||||
bool polling_paused;
|
||||
bool suspended;
|
||||
|
||||
const struct rfkill_ops *ops;
|
||||
void *data;
|
||||
@@ -233,29 +235,6 @@ static void rfkill_event(struct rfkill *rfkill)
|
||||
rfkill_send_events(rfkill, RFKILL_OP_CHANGE);
|
||||
}
|
||||
|
||||
static bool __rfkill_set_hw_state(struct rfkill *rfkill,
|
||||
bool blocked, bool *change)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool prev, any;
|
||||
|
||||
BUG_ON(!rfkill);
|
||||
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
prev = !!(rfkill->state & RFKILL_BLOCK_HW);
|
||||
if (blocked)
|
||||
rfkill->state |= RFKILL_BLOCK_HW;
|
||||
else
|
||||
rfkill->state &= ~RFKILL_BLOCK_HW;
|
||||
*change = prev != blocked;
|
||||
any = !!(rfkill->state & RFKILL_BLOCK_ANY);
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
/**
|
||||
* rfkill_set_block - wrapper for set_block method
|
||||
*
|
||||
@@ -285,7 +264,7 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
prev = rfkill->state & RFKILL_BLOCK_SW;
|
||||
|
||||
if (rfkill->state & RFKILL_BLOCK_SW)
|
||||
if (prev)
|
||||
rfkill->state |= RFKILL_BLOCK_SW_PREV;
|
||||
else
|
||||
rfkill->state &= ~RFKILL_BLOCK_SW_PREV;
|
||||
@@ -303,8 +282,8 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
if (err) {
|
||||
/*
|
||||
* Failed -- reset status to _prev, this may be different
|
||||
* from what set set _PREV to earlier in this function
|
||||
* Failed -- reset status to _PREV, which may be different
|
||||
* from what we have set _PREV to earlier in this function
|
||||
* if rfkill_set_sw_state was invoked.
|
||||
*/
|
||||
if (rfkill->state & RFKILL_BLOCK_SW_PREV)
|
||||
@@ -323,6 +302,19 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
|
||||
rfkill_event(rfkill);
|
||||
}
|
||||
|
||||
static void rfkill_update_global_state(enum rfkill_type type, bool blocked)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (type != RFKILL_TYPE_ALL) {
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].cur = blocked;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
|
||||
|
||||
@@ -332,8 +324,7 @@ static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
|
||||
* @blocked: the new state
|
||||
*
|
||||
* This function sets the state of all switches of given type,
|
||||
* unless a specific switch is claimed by userspace (in which case,
|
||||
* that switch is left alone) or suspended.
|
||||
* unless a specific switch is suspended.
|
||||
*
|
||||
* Caller must have acquired rfkill_global_mutex.
|
||||
*/
|
||||
@@ -341,15 +332,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked)
|
||||
{
|
||||
struct rfkill *rfkill;
|
||||
|
||||
if (type == RFKILL_TYPE_ALL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].cur = blocked;
|
||||
} else {
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
}
|
||||
|
||||
rfkill_update_global_state(type, blocked);
|
||||
list_for_each_entry(rfkill, &rfkill_list, node) {
|
||||
if (rfkill->type != type && type != RFKILL_TYPE_ALL)
|
||||
continue;
|
||||
@@ -477,17 +460,28 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
bool ret, change;
|
||||
unsigned long flags;
|
||||
bool ret, prev;
|
||||
|
||||
ret = __rfkill_set_hw_state(rfkill, blocked, &change);
|
||||
BUG_ON(!rfkill);
|
||||
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
prev = !!(rfkill->state & RFKILL_BLOCK_HW);
|
||||
if (blocked)
|
||||
rfkill->state |= RFKILL_BLOCK_HW;
|
||||
else
|
||||
rfkill->state &= ~RFKILL_BLOCK_HW;
|
||||
ret = !!(rfkill->state & RFKILL_BLOCK_ANY);
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
|
||||
if (!rfkill->registered)
|
||||
return ret;
|
||||
|
||||
if (change)
|
||||
if (prev != blocked)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
return ret;
|
||||
@@ -582,6 +576,34 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_states);
|
||||
|
||||
static const char * const rfkill_types[] = {
|
||||
NULL, /* RFKILL_TYPE_ALL */
|
||||
"wlan",
|
||||
"bluetooth",
|
||||
"ultrawideband",
|
||||
"wimax",
|
||||
"wwan",
|
||||
"gps",
|
||||
"fm",
|
||||
"nfc",
|
||||
};
|
||||
|
||||
enum rfkill_type rfkill_find_type(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(rfkill_types) != NUM_RFKILL_TYPES);
|
||||
|
||||
if (!name)
|
||||
return RFKILL_TYPE_ALL;
|
||||
|
||||
for (i = 1; i < NUM_RFKILL_TYPES; i++)
|
||||
if (!strcmp(name, rfkill_types[i]))
|
||||
return i;
|
||||
return RFKILL_TYPE_ALL;
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_find_type);
|
||||
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
@@ -591,38 +613,12 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static const char *rfkill_get_type_str(enum rfkill_type type)
|
||||
{
|
||||
BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_NFC + 1);
|
||||
|
||||
switch (type) {
|
||||
case RFKILL_TYPE_WLAN:
|
||||
return "wlan";
|
||||
case RFKILL_TYPE_BLUETOOTH:
|
||||
return "bluetooth";
|
||||
case RFKILL_TYPE_UWB:
|
||||
return "ultrawideband";
|
||||
case RFKILL_TYPE_WIMAX:
|
||||
return "wimax";
|
||||
case RFKILL_TYPE_WWAN:
|
||||
return "wwan";
|
||||
case RFKILL_TYPE_GPS:
|
||||
return "gps";
|
||||
case RFKILL_TYPE_FM:
|
||||
return "fm";
|
||||
case RFKILL_TYPE_NFC:
|
||||
return "nfc";
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
return sprintf(buf, "%s\n", rfkill_types[rfkill->type]);
|
||||
}
|
||||
static DEVICE_ATTR_RO(type);
|
||||
|
||||
@@ -730,20 +726,12 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RW(state);
|
||||
|
||||
static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", 0);
|
||||
}
|
||||
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,
|
||||
@@ -768,7 +756,7 @@ static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
if (error)
|
||||
return error;
|
||||
error = add_uevent_var(env, "RFKILL_TYPE=%s",
|
||||
rfkill_get_type_str(rfkill->type));
|
||||
rfkill_types[rfkill->type]);
|
||||
if (error)
|
||||
return error;
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
@@ -786,6 +774,7 @@ void rfkill_pause_polling(struct rfkill *rfkill)
|
||||
if (!rfkill->ops->poll)
|
||||
return;
|
||||
|
||||
rfkill->polling_paused = true;
|
||||
cancel_delayed_work_sync(&rfkill->poll_work);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_pause_polling);
|
||||
@@ -797,6 +786,11 @@ void rfkill_resume_polling(struct rfkill *rfkill)
|
||||
if (!rfkill->ops->poll)
|
||||
return;
|
||||
|
||||
rfkill->polling_paused = false;
|
||||
|
||||
if (rfkill->suspended)
|
||||
return;
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rfkill->poll_work, 0);
|
||||
}
|
||||
@@ -807,7 +801,8 @@ static int rfkill_suspend(struct device *dev)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
rfkill_pause_polling(rfkill);
|
||||
rfkill->suspended = true;
|
||||
cancel_delayed_work_sync(&rfkill->poll_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -817,12 +812,16 @@ static int rfkill_resume(struct device *dev)
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
bool cur;
|
||||
|
||||
rfkill->suspended = false;
|
||||
|
||||
if (!rfkill->persistent) {
|
||||
cur = !!(rfkill->state & RFKILL_BLOCK_SW);
|
||||
rfkill_set_block(rfkill, cur);
|
||||
}
|
||||
|
||||
rfkill_resume_polling(rfkill);
|
||||
if (rfkill->ops->poll && !rfkill->polling_paused)
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rfkill->poll_work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1164,15 +1163,8 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
if (ev.op == RFKILL_OP_CHANGE_ALL) {
|
||||
if (ev.type == RFKILL_TYPE_ALL) {
|
||||
enum rfkill_type i;
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].cur = ev.soft;
|
||||
} else {
|
||||
rfkill_global_states[ev.type].cur = ev.soft;
|
||||
}
|
||||
}
|
||||
if (ev.op == RFKILL_OP_CHANGE_ALL)
|
||||
rfkill_update_global_state(ev.type, ev.soft);
|
||||
|
||||
list_for_each_entry(rfkill, &rfkill_list, node) {
|
||||
if (rfkill->idx != ev.idx && ev.op != RFKILL_OP_CHANGE_ALL)
|
||||
@@ -1261,10 +1253,8 @@ static struct miscdevice rfkill_miscdev = {
|
||||
static int __init rfkill_init(void)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].cur = !rfkill_default_state;
|
||||
rfkill_update_global_state(RFKILL_TYPE_ALL, !rfkill_default_state);
|
||||
|
||||
error = class_register(&rfkill_class);
|
||||
if (error)
|
||||
|
@@ -27,8 +27,6 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include <linux/rfkill-gpio.h>
|
||||
|
||||
struct rfkill_gpio_data {
|
||||
const char *name;
|
||||
enum rfkill_type type;
|
||||
@@ -81,7 +79,6 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
rfkill->name = dev_name(dev);
|
||||
rfkill->type = (unsigned)id->driver_data;
|
||||
|
||||
return acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
|
||||
@@ -90,24 +87,27 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
|
||||
|
||||
static int rfkill_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct rfkill_gpio_data *rfkill;
|
||||
struct gpio_desc *gpio;
|
||||
const char *type_name;
|
||||
int ret;
|
||||
|
||||
rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
|
||||
if (!rfkill)
|
||||
return -ENOMEM;
|
||||
|
||||
device_property_read_string(&pdev->dev, "name", &rfkill->name);
|
||||
device_property_read_string(&pdev->dev, "type", &type_name);
|
||||
|
||||
if (!rfkill->name)
|
||||
rfkill->name = dev_name(&pdev->dev);
|
||||
|
||||
rfkill->type = rfkill_find_type(type_name);
|
||||
|
||||
if (ACPI_HANDLE(&pdev->dev)) {
|
||||
ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (pdata) {
|
||||
rfkill->name = pdata->name;
|
||||
rfkill->type = pdata->type;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rfkill->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
@@ -124,10 +124,8 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
rfkill->shutdown_gpio = gpio;
|
||||
|
||||
/* Make sure at-least one of the GPIO is defined and that
|
||||
* a name is specified for this instance
|
||||
*/
|
||||
if ((!rfkill->reset_gpio && !rfkill->shutdown_gpio) || !rfkill->name) {
|
||||
/* Make sure at-least one GPIO is defined for this instance */
|
||||
if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) {
|
||||
dev_err(&pdev->dev, "invalid platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user