Commit | Line | Data |
---|---|---|
ad97edd2 MA |
1 | /****************************************************************************** |
2 | * | |
01f8162a | 3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. |
ad97edd2 MA |
4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | |
6 | * as portions of the ieee80211 subsystem header files. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of version 2 of the GNU General Public License as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 | * more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along with | |
18 | * this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
20 | * | |
21 | * The full GNU General Public License is included in this distribution in the | |
22 | * file called LICENSE. | |
23 | * | |
24 | * Contact Information: | |
759ef89f | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
ad97edd2 MA |
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | *****************************************************************************/ | |
28 | #include <linux/kernel.h> | |
29 | #include <linux/module.h> | |
ad97edd2 MA |
30 | #include <linux/init.h> |
31 | ||
32 | #include <net/mac80211.h> | |
33 | ||
34 | #include "iwl-eeprom.h" | |
3e0d4cb1 | 35 | #include "iwl-dev.h" |
fee1247a | 36 | #include "iwl-core.h" |
ad97edd2 | 37 | |
ad97edd2 | 38 | /* software rf-kill from user */ |
19d337df | 39 | static int iwl_rfkill_soft_rf_kill(void *data, bool blocked) |
ad97edd2 MA |
40 | { |
41 | struct iwl_priv *priv = data; | |
ad97edd2 | 42 | |
80fcc9e2 | 43 | if (!priv->rfkill) |
19d337df | 44 | return -EINVAL; |
ad97edd2 | 45 | |
59003835 MA |
46 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
47 | return 0; | |
48 | ||
19d337df JB |
49 | IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked); |
50 | ||
ad97edd2 MA |
51 | mutex_lock(&priv->mutex); |
52 | ||
19d337df JB |
53 | if (iwl_is_rfkill_hw(priv)) |
54 | goto out_unlock; | |
55 | ||
56 | if (!blocked) | |
80fcc9e2 | 57 | iwl_radio_kill_sw_enable_radio(priv); |
19d337df | 58 | else |
14a08a7f | 59 | iwl_radio_kill_sw_disable_radio(priv); |
19d337df | 60 | |
80fcc9e2 | 61 | out_unlock: |
ad97edd2 | 62 | mutex_unlock(&priv->mutex); |
19d337df | 63 | return 0; |
ad97edd2 MA |
64 | } |
65 | ||
19d337df JB |
66 | static const struct rfkill_ops iwl_rfkill_ops = { |
67 | .set_block = iwl_rfkill_soft_rf_kill, | |
68 | }; | |
69 | ||
ad97edd2 MA |
70 | int iwl_rfkill_init(struct iwl_priv *priv) |
71 | { | |
72 | struct device *device = wiphy_dev(priv->hw->wiphy); | |
73 | int ret = 0; | |
74 | ||
75 | BUG_ON(device == NULL); | |
76 | ||
e1623446 | 77 | IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n"); |
19d337df JB |
78 | priv->rfkill = rfkill_alloc(priv->cfg->name, |
79 | device, | |
80 | RFKILL_TYPE_WLAN, | |
81 | &iwl_rfkill_ops, priv); | |
80fcc9e2 | 82 | if (!priv->rfkill) { |
15b1687c | 83 | IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); |
ad97edd2 MA |
84 | ret = -ENOMEM; |
85 | goto error; | |
86 | } | |
87 | ||
80fcc9e2 | 88 | ret = rfkill_register(priv->rfkill); |
03d29c68 | 89 | if (ret) { |
15b1687c | 90 | IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret); |
8fa7425c | 91 | goto free_rfkill; |
03d29c68 | 92 | } |
ad97edd2 | 93 | |
e1623446 | 94 | IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); |
19d337df | 95 | return 0; |
ad97edd2 | 96 | |
8fa7425c | 97 | free_rfkill: |
19d337df | 98 | rfkill_destroy(priv->rfkill); |
80fcc9e2 | 99 | priv->rfkill = NULL; |
ad97edd2 MA |
100 | |
101 | error: | |
e1623446 | 102 | IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); |
ad97edd2 MA |
103 | return ret; |
104 | } | |
105 | EXPORT_SYMBOL(iwl_rfkill_init); | |
106 | ||
107 | void iwl_rfkill_unregister(struct iwl_priv *priv) | |
108 | { | |
109 | ||
19d337df | 110 | if (priv->rfkill) { |
80fcc9e2 | 111 | rfkill_unregister(priv->rfkill); |
19d337df JB |
112 | rfkill_destroy(priv->rfkill); |
113 | } | |
ad97edd2 | 114 | |
80fcc9e2 | 115 | priv->rfkill = NULL; |
ad97edd2 | 116 | } |
03d29c68 | 117 | EXPORT_SYMBOL(iwl_rfkill_unregister); |
ad97edd2 | 118 | |
a96a27f9 | 119 | /* set RFKILL to the right state. */ |
ad97edd2 MA |
120 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) |
121 | { | |
80fcc9e2 | 122 | if (!priv->rfkill) |
ad97edd2 MA |
123 | return; |
124 | ||
19d337df JB |
125 | if (rfkill_set_hw_state(priv->rfkill, |
126 | !!iwl_is_rfkill_hw(priv))) | |
127 | iwl_radio_kill_sw_disable_radio(priv); | |
ad97edd2 | 128 | else |
19d337df | 129 | iwl_radio_kill_sw_enable_radio(priv); |
ad97edd2 MA |
130 | } |
131 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); |