mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 10:57:46 +00:00
[B43]: Use input-polldev for the rfkill switch
This removes the direct call to rfkill on an rfkill event and replaces it with an input device. This way userspace is also notified about the event. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8e9f7529fd
commit
42bb4cd5ae
4 changed files with 110 additions and 101 deletions
|
@ -70,7 +70,7 @@ config B43_LEDS
|
||||||
# RFKILL support
|
# RFKILL support
|
||||||
config B43_RFKILL
|
config B43_RFKILL
|
||||||
bool
|
bool
|
||||||
depends on B43 && RFKILL
|
depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config B43_DEBUG
|
config B43_DEBUG
|
||||||
|
|
|
@ -2143,21 +2143,6 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
|
||||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
|
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns TRUE, if the radio is enabled in hardware. */
|
|
||||||
static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
|
||||||
{
|
|
||||||
if (dev->phy.rev >= 3) {
|
|
||||||
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
|
|
||||||
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
|
|
||||||
& B43_MMIO_RADIO_HWENABLED_LO_MASK)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is the opposite of b43_chip_init() */
|
/* This is the opposite of b43_chip_init() */
|
||||||
static void b43_chip_exit(struct b43_wldev *dev)
|
static void b43_chip_exit(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
|
@ -2350,32 +2335,18 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
|
||||||
//TODO for APHY (temperature?)
|
//TODO for APHY (temperature?)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_periodic_every1sec(struct b43_wldev *dev)
|
|
||||||
{
|
|
||||||
bool radio_hw_enable;
|
|
||||||
|
|
||||||
/* check if radio hardware enabled status changed */
|
|
||||||
radio_hw_enable = b43_is_hw_radio_enabled(dev);
|
|
||||||
if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
|
|
||||||
dev->radio_hw_enable = radio_hw_enable;
|
|
||||||
b43_rfkill_toggled(dev, radio_hw_enable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_periodic_work(struct b43_wldev *dev)
|
static void do_periodic_work(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
|
||||||
state = dev->periodic_state;
|
state = dev->periodic_state;
|
||||||
if (state % 120 == 0)
|
if (state % 8 == 0)
|
||||||
b43_periodic_every120sec(dev);
|
b43_periodic_every120sec(dev);
|
||||||
if (state % 60 == 0)
|
if (state % 4 == 0)
|
||||||
b43_periodic_every60sec(dev);
|
b43_periodic_every60sec(dev);
|
||||||
if (state % 30 == 0)
|
if (state % 2 == 0)
|
||||||
b43_periodic_every30sec(dev);
|
b43_periodic_every30sec(dev);
|
||||||
if (state % 15 == 0)
|
b43_periodic_every15sec(dev);
|
||||||
b43_periodic_every15sec(dev);
|
|
||||||
b43_periodic_every1sec(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Estimate a "Badness" value based on the periodic work
|
/* Estimate a "Badness" value based on the periodic work
|
||||||
|
@ -2386,13 +2357,11 @@ static int estimate_periodic_work_badness(unsigned int state)
|
||||||
{
|
{
|
||||||
int badness = 0;
|
int badness = 0;
|
||||||
|
|
||||||
if (state % 120 == 0) /* every 120 sec */
|
if (state % 8 == 0) /* every 120 sec */
|
||||||
badness += 10;
|
badness += 10;
|
||||||
if (state % 60 == 0) /* every 60 sec */
|
if (state % 4 == 0) /* every 60 sec */
|
||||||
badness += 5;
|
badness += 5;
|
||||||
if (state % 30 == 0) /* every 30 sec */
|
if (state % 2 == 0) /* every 30 sec */
|
||||||
badness += 1;
|
|
||||||
if (state % 15 == 0) /* every 15 sec */
|
|
||||||
badness += 1;
|
badness += 1;
|
||||||
|
|
||||||
#define BADNESS_LIMIT 4
|
#define BADNESS_LIMIT 4
|
||||||
|
@ -2443,13 +2412,13 @@ static void b43_periodic_work_handler(struct work_struct *work)
|
||||||
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
|
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
|
||||||
}
|
}
|
||||||
dev->periodic_state++;
|
dev->periodic_state++;
|
||||||
out_requeue:
|
out_requeue:
|
||||||
if (b43_debug(dev, B43_DBG_PWORK_FAST))
|
if (b43_debug(dev, B43_DBG_PWORK_FAST))
|
||||||
delay = msecs_to_jiffies(50);
|
delay = msecs_to_jiffies(50);
|
||||||
else
|
else
|
||||||
delay = round_jiffies(HZ);
|
delay = round_jiffies(HZ * 15);
|
||||||
queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay);
|
queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->wl->mutex);
|
mutex_unlock(&dev->wl->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3720,6 +3689,7 @@ static int b43_setup_modes(struct b43_wldev *dev,
|
||||||
|
|
||||||
static void b43_wireless_core_detach(struct b43_wldev *dev)
|
static void b43_wireless_core_detach(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
|
b43_rfkill_free(dev);
|
||||||
/* We release firmware that late to not be required to re-request
|
/* We release firmware that late to not be required to re-request
|
||||||
* is all the time when we reinit the core. */
|
* is all the time when we reinit the core. */
|
||||||
b43_release_firmware(dev);
|
b43_release_firmware(dev);
|
||||||
|
@ -3805,6 +3775,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
|
||||||
if (!wl->current_dev)
|
if (!wl->current_dev)
|
||||||
wl->current_dev = dev;
|
wl->current_dev = dev;
|
||||||
INIT_WORK(&dev->restart_work, b43_chip_reset);
|
INIT_WORK(&dev->restart_work, b43_chip_reset);
|
||||||
|
b43_rfkill_alloc(dev);
|
||||||
|
|
||||||
b43_radio_turn_off(dev, 1);
|
b43_radio_turn_off(dev, 1);
|
||||||
b43_switch_analog(dev, 0);
|
b43_switch_analog(dev, 0);
|
||||||
|
|
|
@ -26,46 +26,39 @@
|
||||||
#include "b43.h"
|
#include "b43.h"
|
||||||
|
|
||||||
|
|
||||||
static void b43_notify_rfkill_press(struct work_struct *work)
|
/* Returns TRUE, if the radio is enabled in hardware. */
|
||||||
|
static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
struct b43_rfkill *rfk = container_of(work, struct b43_rfkill,
|
if (dev->phy.rev >= 3) {
|
||||||
notify_work);
|
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
|
||||||
struct b43_wl *wl = container_of(rfk, struct b43_wl, rfkill);
|
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
|
||||||
struct b43_wldev *dev;
|
return 1;
|
||||||
enum rfkill_state state;
|
} else {
|
||||||
|
if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
|
||||||
mutex_lock(&wl->mutex);
|
& B43_MMIO_RADIO_HWENABLED_LO_MASK)
|
||||||
dev = wl->current_dev;
|
return 1;
|
||||||
if (b43_status(dev) < B43_STAT_INITIALIZED) {
|
|
||||||
mutex_unlock(&wl->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dev->radio_hw_enable)
|
|
||||||
state = RFKILL_STATE_ON;
|
|
||||||
else
|
|
||||||
state = RFKILL_STATE_OFF;
|
|
||||||
b43info(wl, "Radio hardware status changed to %s\n",
|
|
||||||
dev->radio_hw_enable ? "ENABLED" : "DISABLED");
|
|
||||||
mutex_unlock(&wl->mutex);
|
|
||||||
|
|
||||||
if (rfk->rfkill) {
|
|
||||||
/* Be careful. This calls back into the software toggle routines.
|
|
||||||
* So we must unlock before calling. */
|
|
||||||
rfkill_switch_all(rfk->rfkill->type, state);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when the RFKILL toggled in hardware.
|
/* The poll callback for the hardware button. */
|
||||||
* This is called with the mutex locked. */
|
static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
|
||||||
void b43_rfkill_toggled(struct b43_wldev *dev, bool on)
|
|
||||||
{
|
{
|
||||||
|
struct b43_wldev *dev = poll_dev->private;
|
||||||
struct b43_wl *wl = dev->wl;
|
struct b43_wl *wl = dev->wl;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
|
B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
|
||||||
/* Update the RF status asynchronously, as rfkill will
|
enabled = b43_is_hw_radio_enabled(dev);
|
||||||
* call back into the software toggle handler.
|
if (unlikely(enabled != dev->radio_hw_enable)) {
|
||||||
* This would deadlock if done synchronously. */
|
dev->radio_hw_enable = enabled;
|
||||||
queue_work(wl->hw->workqueue, &wl->rfkill.notify_work);
|
b43info(wl, "Radio hardware status changed to %s\n",
|
||||||
|
enabled ? "ENABLED" : "DISABLED");
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
input_report_key(poll_dev->input, KEY_WLAN, enabled);
|
||||||
|
} else
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when the RFKILL toggled in software.
|
/* Called when the RFKILL toggled in software.
|
||||||
|
@ -118,38 +111,74 @@ void b43_rfkill_init(struct b43_wldev *dev)
|
||||||
struct b43_rfkill *rfk = &(wl->rfkill);
|
struct b43_rfkill *rfk = &(wl->rfkill);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
snprintf(rfk->name, sizeof(rfk->name),
|
if (rfk->rfkill) {
|
||||||
"b43-%s", wiphy_name(wl->hw->wiphy));
|
err = rfkill_register(rfk->rfkill);
|
||||||
rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
|
if (err) {
|
||||||
if (!rfk->rfkill)
|
b43warn(wl, "Failed to register RF-kill button\n");
|
||||||
goto error;
|
goto err_free_rfk;
|
||||||
rfk->rfkill->name = rfk->name;
|
}
|
||||||
rfk->rfkill->state = RFKILL_STATE_ON;
|
}
|
||||||
rfk->rfkill->data = dev;
|
if (rfk->poll_dev) {
|
||||||
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
|
err = input_register_polled_device(rfk->poll_dev);
|
||||||
rfk->rfkill->user_claim_unsupported = 1;
|
if (err) {
|
||||||
|
b43warn(wl, "Failed to register RF-kill polldev\n");
|
||||||
INIT_WORK(&rfk->notify_work, b43_notify_rfkill_press);
|
goto err_free_polldev;
|
||||||
|
}
|
||||||
err = rfkill_register(rfk->rfkill);
|
}
|
||||||
if (err)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
error:
|
err_free_rfk:
|
||||||
b43warn(dev->wl, "Failed to initialize the RF-kill button\n");
|
|
||||||
rfkill_free(rfk->rfkill);
|
rfkill_free(rfk->rfkill);
|
||||||
rfk->rfkill = NULL;
|
rfk->rfkill = NULL;
|
||||||
|
err_free_polldev:
|
||||||
|
input_free_polled_device(rfk->poll_dev);
|
||||||
|
rfk->poll_dev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void b43_rfkill_exit(struct b43_wldev *dev)
|
void b43_rfkill_exit(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
struct b43_rfkill *rfk = &(dev->wl->rfkill);
|
struct b43_rfkill *rfk = &(dev->wl->rfkill);
|
||||||
|
|
||||||
if (!rfk->rfkill)
|
if (rfk->poll_dev)
|
||||||
|
input_unregister_polled_device(rfk->poll_dev);
|
||||||
|
if (rfk->rfkill)
|
||||||
|
rfkill_unregister(rfk->rfkill);
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_rfkill_alloc(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_wl *wl = dev->wl;
|
||||||
|
struct b43_rfkill *rfk = &(wl->rfkill);
|
||||||
|
|
||||||
|
snprintf(rfk->name, sizeof(rfk->name),
|
||||||
|
"b43-%s", wiphy_name(wl->hw->wiphy));
|
||||||
|
|
||||||
|
rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
|
||||||
|
if (!rfk->rfkill) {
|
||||||
|
b43warn(wl, "Failed to allocate RF-kill button\n");
|
||||||
return;
|
return;
|
||||||
cancel_work_sync(&rfk->notify_work);
|
}
|
||||||
rfkill_unregister(rfk->rfkill);
|
rfk->rfkill->name = rfk->name;
|
||||||
|
rfk->rfkill->state = RFKILL_STATE_ON;
|
||||||
|
rfk->rfkill->data = dev;
|
||||||
|
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
|
||||||
|
rfk->rfkill->user_claim_unsupported = 1;
|
||||||
|
|
||||||
|
rfk->poll_dev = input_allocate_polled_device();
|
||||||
|
if (rfk->poll_dev) {
|
||||||
|
rfk->poll_dev->private = dev;
|
||||||
|
rfk->poll_dev->poll = b43_rfkill_poll;
|
||||||
|
rfk->poll_dev->poll_interval = 1000; /* msecs */
|
||||||
|
} else
|
||||||
|
b43warn(wl, "Failed to allocate RF-kill polldev\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_rfkill_free(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_rfkill *rfk = &(dev->wl->rfkill);
|
||||||
|
|
||||||
|
input_free_polled_device(rfk->poll_dev);
|
||||||
|
rfk->poll_dev = NULL;
|
||||||
rfkill_free(rfk->rfkill);
|
rfkill_free(rfk->rfkill);
|
||||||
rfk->rfkill = NULL;
|
rfk->rfkill = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,19 +7,25 @@ struct b43_wldev;
|
||||||
#ifdef CONFIG_B43_RFKILL
|
#ifdef CONFIG_B43_RFKILL
|
||||||
|
|
||||||
#include <linux/rfkill.h>
|
#include <linux/rfkill.h>
|
||||||
|
#include <linux/input-polldev.h>
|
||||||
|
|
||||||
|
|
||||||
struct b43_rfkill {
|
struct b43_rfkill {
|
||||||
/* The RFKILL subsystem data structure */
|
/* The RFKILL subsystem data structure */
|
||||||
struct rfkill *rfkill;
|
struct rfkill *rfkill;
|
||||||
|
/* The poll device for the RFKILL input button */
|
||||||
|
struct input_polled_dev *poll_dev;
|
||||||
/* The unique name of this rfkill switch */
|
/* The unique name of this rfkill switch */
|
||||||
char name[32];
|
char name[32];
|
||||||
/* Workqueue for asynchronous notification. */
|
|
||||||
struct work_struct notify_work;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* All the init functions return void, because we are not interested
|
||||||
|
* in failing the b43 init process when rfkill init failed. */
|
||||||
|
void b43_rfkill_alloc(struct b43_wldev *dev);
|
||||||
|
void b43_rfkill_free(struct b43_wldev *dev);
|
||||||
void b43_rfkill_init(struct b43_wldev *dev);
|
void b43_rfkill_init(struct b43_wldev *dev);
|
||||||
void b43_rfkill_exit(struct b43_wldev *dev);
|
void b43_rfkill_exit(struct b43_wldev *dev);
|
||||||
void b43_rfkill_toggled(struct b43_wldev *dev, bool on);
|
|
||||||
char * b43_rfkill_led_name(struct b43_wldev *dev);
|
char * b43_rfkill_led_name(struct b43_wldev *dev);
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,15 +36,18 @@ struct b43_rfkill {
|
||||||
/* empty */
|
/* empty */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void b43_rfkill_alloc(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void b43_rfkill_free(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
static inline void b43_rfkill_init(struct b43_wldev *dev)
|
static inline void b43_rfkill_init(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void b43_rfkill_exit(struct b43_wldev *dev)
|
static inline void b43_rfkill_exit(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void b43_rfkill_toggled(struct b43_wldev *dev, bool on)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline char * b43_rfkill_led_name(struct b43_wldev *dev)
|
static inline char * b43_rfkill_led_name(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in a new issue