diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 18:02:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 18:02:35 -0700 |
commit | 334d094504c2fe1c44211ecb49146ae6bca8c321 (patch) | |
tree | d3c0f68e4b9f8e3d2ccc39e7dfe5de0534a5fad9 /drivers/net/wireless/iwlwifi/iwl-rfkill.c | |
parent | d1a4be630fb068f251d64b62919f143c49ca8057 (diff) | |
parent | d1643d24c61b725bef399cc1cf2944b4c9c23177 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.26
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.26: (1090 commits)
[NET]: Fix and allocate less memory for ->priv'less netdevices
[IPV6]: Fix dangling references on error in fib6_add().
[NETLABEL]: Fix NULL deref in netlbl_unlabel_staticlist_gen() if ifindex not found
[PKT_SCHED]: Fix datalen check in tcf_simp_init().
[INET]: Uninline the __inet_inherit_port call.
[INET]: Drop the inet_inherit_port() call.
SCTP: Initialize partial_bytes_acked to 0, when all of the data is acked.
[netdrvr] forcedeth: internal simplifications; changelog removal
phylib: factor out get_phy_id from within get_phy_device
PHY: add BCM5464 support to broadcom PHY driver
cxgb3: Fix __must_check warning with dev_dbg.
tc35815: Statistics cleanup
natsemi: fix MMIO for PPC 44x platforms
[TIPC]: Cleanup of TIPC reference table code
[TIPC]: Optimized initialization of TIPC reference table
[TIPC]: Remove inlining of reference table locking routines
e1000: convert uint16_t style integers to u16
ixgb: convert uint16_t style integers to u16
sb1000.c: make const arrays static
sb1000.c: stop inlining largish static functions
...
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rfkill.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c new file mode 100644 index 00000000000..5980a5621cb --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -0,0 +1,173 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos <ipw2100-admin@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/init.h> + +#include <net/mac80211.h> + +#include "iwl-eeprom.h" +#include "iwl-4965.h" +#include "iwl-core.h" +#include "iwl-helpers.h" + + +/* software rf-kill from user */ +static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) +{ + struct iwl_priv *priv = data; + int err = 0; + + if (!priv->rfkill_mngr.rfkill) + return 0; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return 0; + + IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); + mutex_lock(&priv->mutex); + + switch (state) { + case RFKILL_STATE_ON: + priv->cfg->ops->lib->radio_kill_sw(priv, 0); + /* if HW rf-kill is set dont allow ON state */ + if (iwl_is_rfkill(priv)) + err = -EBUSY; + break; + case RFKILL_STATE_OFF: + priv->cfg->ops->lib->radio_kill_sw(priv, 1); + if (!iwl_is_rfkill(priv)) + err = -EBUSY; + break; + } + mutex_unlock(&priv->mutex); + + return err; +} + +int iwl_rfkill_init(struct iwl_priv *priv) +{ + struct device *device = wiphy_dev(priv->hw->wiphy); + int ret = 0; + + BUG_ON(device == NULL); + + IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); + priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill_mngr.rfkill) { + IWL_ERROR("Unable to allocate rfkill device.\n"); + ret = -ENOMEM; + goto error; + } + + priv->rfkill_mngr.rfkill->name = priv->cfg->name; + priv->rfkill_mngr.rfkill->data = priv; + priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; + priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; + + priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; + priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + + priv->rfkill_mngr.input_dev = input_allocate_device(); + if (!priv->rfkill_mngr.input_dev) { + IWL_ERROR("Unable to allocate rfkill input device.\n"); + ret = -ENOMEM; + goto freed_rfkill; + } + + priv->rfkill_mngr.input_dev->name = priv->cfg->name; + priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); + priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; + priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; + priv->rfkill_mngr.input_dev->dev.parent = device; + priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); + set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); + + ret = rfkill_register(priv->rfkill_mngr.rfkill); + if (ret) { + IWL_ERROR("Unable to register rfkill: %d\n", ret); + goto free_input_dev; + } + + ret = input_register_device(priv->rfkill_mngr.input_dev); + if (ret) { + IWL_ERROR("Unable to register rfkill input device: %d\n", ret); + goto unregister_rfkill; + } + + IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); + return ret; + +unregister_rfkill: + rfkill_unregister(priv->rfkill_mngr.rfkill); + priv->rfkill_mngr.rfkill = NULL; + +free_input_dev: + input_free_device(priv->rfkill_mngr.input_dev); + priv->rfkill_mngr.input_dev = NULL; + +freed_rfkill: + if (priv->rfkill_mngr.rfkill != NULL) + rfkill_free(priv->rfkill_mngr.rfkill); + priv->rfkill_mngr.rfkill = NULL; + +error: + IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); + return ret; +} +EXPORT_SYMBOL(iwl_rfkill_init); + +void iwl_rfkill_unregister(struct iwl_priv *priv) +{ + + if (priv->rfkill_mngr.input_dev) + input_unregister_device(priv->rfkill_mngr.input_dev); + + if (priv->rfkill_mngr.rfkill) + rfkill_unregister(priv->rfkill_mngr.rfkill); + + priv->rfkill_mngr.input_dev = NULL; + priv->rfkill_mngr.rfkill = NULL; +} +EXPORT_SYMBOL(iwl_rfkill_unregister); + +/* set rf-kill to the right state. */ +void iwl_rfkill_set_hw_state(struct iwl_priv *priv) +{ + + if (!priv->rfkill_mngr.rfkill) + return; + + if (!iwl_is_rfkill(priv)) + priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + else + priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; +} +EXPORT_SYMBOL(iwl_rfkill_set_hw_state); |