diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rfkill.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.c | 69 |
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 */ |
39 | static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | 39 | static 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 | } | ||
69 | out_unlock: | 61 | out_unlock: |
70 | mutex_unlock(&priv->mutex); | 62 | mutex_unlock(&priv->mutex); |
71 | 63 | return 0; | |
72 | return err; | ||
73 | } | 64 | } |
74 | 65 | ||
66 | static const struct rfkill_ops iwl_rfkill_ops = { | ||
67 | .set_block = iwl_rfkill_soft_rf_kill, | ||
68 | }; | ||
69 | |||
75 | int iwl_rfkill_init(struct iwl_priv *priv) | 70 | int 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 | ||
107 | free_rfkill: | 97 | free_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 | ||
112 | error: | 101 | error: |
@@ -118,8 +107,10 @@ EXPORT_SYMBOL(iwl_rfkill_init); | |||
118 | void iwl_rfkill_unregister(struct iwl_priv *priv) | 107 | void 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 | } |
144 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); | 131 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); |