aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rfkill.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rfkill.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.c69
1 files changed, 28 insertions, 41 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 65605ad44e4b..13149936fd26 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -36,42 +36,37 @@
36#include "iwl-core.h" 36#include "iwl-core.h"
37 37
38/* software rf-kill from user */ 38/* software rf-kill from user */
39static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) 39static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
40{ 40{
41 struct iwl_priv *priv = data; 41 struct iwl_priv *priv = data;
42 int err = 0;
43 42
44 if (!priv->rfkill) 43 if (!priv->rfkill)
45 return 0; 44 return -EINVAL;
46 45
47 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 46 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
48 return 0; 47 return 0;
49 48
50 IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state); 49 IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
50
51 mutex_lock(&priv->mutex); 51 mutex_lock(&priv->mutex);
52 52
53 switch (state) { 53 if (iwl_is_rfkill_hw(priv))
54 case RFKILL_STATE_UNBLOCKED: 54 goto out_unlock;
55 if (iwl_is_rfkill_hw(priv)) { 55
56 err = -EBUSY; 56 if (!blocked)
57 goto out_unlock;
58 }
59 iwl_radio_kill_sw_enable_radio(priv); 57 iwl_radio_kill_sw_enable_radio(priv);
60 break; 58 else
61 case RFKILL_STATE_SOFT_BLOCKED:
62 iwl_radio_kill_sw_disable_radio(priv); 59 iwl_radio_kill_sw_disable_radio(priv);
63 break; 60
64 default:
65 IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
66 state);
67 break;
68 }
69out_unlock: 61out_unlock:
70 mutex_unlock(&priv->mutex); 62 mutex_unlock(&priv->mutex);
71 63 return 0;
72 return err;
73} 64}
74 65
66static const struct rfkill_ops iwl_rfkill_ops = {
67 .set_block = iwl_rfkill_soft_rf_kill,
68};
69
75int iwl_rfkill_init(struct iwl_priv *priv) 70int iwl_rfkill_init(struct iwl_priv *priv)
76{ 71{
77 struct device *device = wiphy_dev(priv->hw->wiphy); 72 struct device *device = wiphy_dev(priv->hw->wiphy);
@@ -80,21 +75,16 @@ int iwl_rfkill_init(struct iwl_priv *priv)
80 BUG_ON(device == NULL); 75 BUG_ON(device == NULL);
81 76
82 IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n"); 77 IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
83 priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); 78 priv->rfkill = rfkill_alloc(priv->cfg->name,
79 device,
80 RFKILL_TYPE_WLAN,
81 &iwl_rfkill_ops, priv);
84 if (!priv->rfkill) { 82 if (!priv->rfkill) {
85 IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); 83 IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
86 ret = -ENOMEM; 84 ret = -ENOMEM;
87 goto error; 85 goto error;
88 } 86 }
89 87
90 priv->rfkill->name = priv->cfg->name;
91 priv->rfkill->data = priv;
92 priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
93 priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
94
95 priv->rfkill->dev.class->suspend = NULL;
96 priv->rfkill->dev.class->resume = NULL;
97
98 ret = rfkill_register(priv->rfkill); 88 ret = rfkill_register(priv->rfkill);
99 if (ret) { 89 if (ret) {
100 IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret); 90 IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
@@ -102,11 +92,10 @@ int iwl_rfkill_init(struct iwl_priv *priv)
102 } 92 }
103 93
104 IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); 94 IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
105 return ret; 95 return 0;
106 96
107free_rfkill: 97free_rfkill:
108 if (priv->rfkill != NULL) 98 rfkill_destroy(priv->rfkill);
109 rfkill_free(priv->rfkill);
110 priv->rfkill = NULL; 99 priv->rfkill = NULL;
111 100
112error: 101error:
@@ -118,8 +107,10 @@ EXPORT_SYMBOL(iwl_rfkill_init);
118void iwl_rfkill_unregister(struct iwl_priv *priv) 107void iwl_rfkill_unregister(struct iwl_priv *priv)
119{ 108{
120 109
121 if (priv->rfkill) 110 if (priv->rfkill) {
122 rfkill_unregister(priv->rfkill); 111 rfkill_unregister(priv->rfkill);
112 rfkill_destroy(priv->rfkill);
113 }
123 114
124 priv->rfkill = NULL; 115 priv->rfkill = NULL;
125} 116}
@@ -131,14 +122,10 @@ void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
131 if (!priv->rfkill) 122 if (!priv->rfkill)
132 return; 123 return;
133 124
134 if (iwl_is_rfkill_hw(priv)) { 125 if (rfkill_set_hw_state(priv->rfkill,
135 rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); 126 !!iwl_is_rfkill_hw(priv)))
136 return; 127 iwl_radio_kill_sw_disable_radio(priv);
137 }
138
139 if (!iwl_is_rfkill_sw(priv))
140 rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
141 else 128 else
142 rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); 129 iwl_radio_kill_sw_enable_radio(priv);
143} 130}
144EXPORT_SYMBOL(iwl_rfkill_set_hw_state); 131EXPORT_SYMBOL(iwl_rfkill_set_hw_state);