The attached patch fixes iwlwifi to set the rfkill state to
RFKILL_STATE_HARD_BLOCKED when the device is disabled by the hardware
rfkill.
---------------
This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
radio is disabled by a hardware killswitch.
It does not allow setting the sw state while the device is blocked by
a hardware rfkill switch.
Signed-off-by: Adel Gadllah <[email protected]>
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h
b/drivers/net/wireless/iwlwifi/iwl-core.h
index 2838093..ad479f3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -349,10 +349,19 @@ static inline int iwl_is_init(struct iwl_priv *priv)
return test_bit(STATUS_INIT, &priv->status);
}
+static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_SW, &priv->status);
+}
+
+static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
static inline int iwl_is_rfkill(struct iwl_priv *priv)
{
- return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status);
+ return iwl_is_rfkill_sw(priv) || iwl_is_rfkill_hw(priv);
}
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index ffefbb4..b75813e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -53,22 +53,23 @@ static int iwl_rfkill_soft_rf_kill(void *data,
enum rfkill_state state)
IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
mutex_lock(&priv->mutex);
+ if (iwl_is_rfkill_hw(priv)) {
+ err = -EBUSY;
+ goto out;
+ }
+
switch (state) {
case RFKILL_STATE_UNBLOCKED:
iwl_radio_kill_sw_enable_radio(priv);
- /* if HW rf-kill is set dont allow ON state */
- if (iwl_is_rfkill(priv))
- err = -EBUSY;
break;
case RFKILL_STATE_SOFT_BLOCKED:
iwl_radio_kill_sw_disable_radio(priv);
- if (!iwl_is_rfkill(priv))
- err = -EBUSY;
break;
default:
IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
break;
}
+out:
mutex_unlock(&priv->mutex);
return err;
@@ -177,9 +178,14 @@ 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;
+ if (iwl_is_rfkill_hw(priv)) {
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_HARD_BLOCKED;
+ return;
+ }
+
+ if (!iwl_is_rfkill_sw(priv))
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_UNBLOCKED;
else
- priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_BLOCKED;
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
On Sat, Jun 28, 2008 at 3:14 PM, Henrique de Moraes Holschuh
<[email protected]> wrote:
> On Sat, 28 Jun 2008, drago01 wrote:
>> This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
>> radio is disabled by a hardware killswitch.
>> It does not allow setting the sw state while the device is blocked by
>> a hardware rfkill switch.
>
> It should. In fact, you should do it in a way that it is possible to
> double-block the radio (i.e. in SW while it is blocked in HW), so that if
> the HW block goes away, the radio remains blocked.
>
> Read the docs and examples again, please. There even is special code in the
> rfkill_toggle_radio private function to allow for it, we want drivers to be
> able to double-block.
OK, v2 attached it allows double-block.
-----
This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
radio is disabled by a hardware killswitch.
It does not allow unblocking the sw state while the device is blocked by
a hardware rfkill switch.
Signed-off-by: Adel Gadllah <[email protected]>
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h
b/drivers/net/wireless/iwlwifi/iwl-core.h
index 2838093..7f4f598 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -349,10 +349,19 @@ static inline int iwl_is_init(struct iwl_priv *priv)
return test_bit(STATUS_INIT, &priv->status);
}
+static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_SW, &priv->status);
+}
+
+static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
static inline int iwl_is_rfkill(struct iwl_priv *priv)
{
- return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status);
+ return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
}
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index ffefbb4..8a47bdc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -55,20 +55,20 @@ static int iwl_rfkill_soft_rf_kill(void *data,
enum rfkill_state state)
switch (state) {
case RFKILL_STATE_UNBLOCKED:
- iwl_radio_kill_sw_enable_radio(priv);
- /* if HW rf-kill is set dont allow ON state */
- if (iwl_is_rfkill(priv))
+ if (iwl_is_rfkill_hw(priv)) {
err = -EBUSY;
+ goto out_unlock;
+ }
+ iwl_radio_kill_sw_enable_radio(priv);
break;
case RFKILL_STATE_SOFT_BLOCKED:
iwl_radio_kill_sw_disable_radio(priv);
- if (!iwl_is_rfkill(priv))
- err = -EBUSY;
break;
default:
IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
break;
}
+out_unlock:
mutex_unlock(&priv->mutex);
return err;
@@ -91,7 +91,7 @@ int iwl_rfkill_init(struct iwl_priv *priv)
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->state = RFKILL_STATE_UNBLOCKED;
priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
@@ -177,9 +177,14 @@ 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;
+ if (iwl_is_rfkill_hw(priv)) {
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_HARD_BLOCKED;
+ return;
+ }
+
+ if (!iwl_is_rfkill_sw(priv))
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_UNBLOCKED;
else
- priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
On Sat, 28 Jun 2008, drago01 wrote:
> On Sat, Jun 28, 2008 at 3:14 PM, Henrique de Moraes Holschuh
> <[email protected]> wrote:
> > On Sat, 28 Jun 2008, drago01 wrote:
> >> This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
> >> radio is disabled by a hardware killswitch.
> >> It does not allow setting the sw state while the device is blocked by
> >> a hardware rfkill switch.
> >
> > It should. In fact, you should do it in a way that it is possible to
> > double-block the radio (i.e. in SW while it is blocked in HW), so that if
> > the HW block goes away, the radio remains blocked.
> >
> > Read the docs and examples again, please. There even is special code in the
> > rfkill_toggle_radio private function to allow for it, we want drivers to be
> > able to double-block.
>
> OK, v2 attached it allows double-block.
Looks good at first glance (I just looked over the patch, I have never
looked at the iwlwifi code, though.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
On Sat, 28 Jun 2008, drago01 wrote:
> This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
> radio is disabled by a hardware killswitch.
> It does not allow setting the sw state while the device is blocked by
> a hardware rfkill switch.
It should. In fact, you should do it in a way that it is possible to
double-block the radio (i.e. in SW while it is blocked in HW), so that if
the HW block goes away, the radio remains blocked.
Read the docs and examples again, please. There even is special code in the
rfkill_toggle_radio private function to allow for it, we want drivers to be
able to double-block.
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
The attached patch fixes iwlwifi to set the rfkill state to
RFKILL_STATE_HARD_BLOCKED when the device is disabled by the hardware
rfkill. It also converts all _OFF/_ON states to the new states.
-------
This patch fixes the rfkill states to set RFKILL_STATE_HARD_BLOCKED when the
radio is disabled by a hardware killswitch.
It does not allow setting the sw state while the device is blocked by
a hardware rfkill switch.
Signed-off-by: Adel Gadllah <[email protected]>
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h
b/drivers/net/wireless/iwlwifi/iwl-core.h
index 2838093..7f4f598 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -349,10 +349,19 @@ static inline int iwl_is_init(struct iwl_priv *priv)
return test_bit(STATUS_INIT, &priv->status);
}
+static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_SW, &priv->status);
+}
+
+static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
+{
+ return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
static inline int iwl_is_rfkill(struct iwl_priv *priv)
{
- return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status);
+ return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
}
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index ffefbb4..96d515c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -53,22 +53,23 @@ static int iwl_rfkill_soft_rf_kill(void *data,
enum rfkill_state state)
IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
mutex_lock(&priv->mutex);
+ if (iwl_is_rfkill_hw(priv)) {
+ err = -EBUSY;
+ goto out;
+ }
+
switch (state) {
case RFKILL_STATE_UNBLOCKED:
iwl_radio_kill_sw_enable_radio(priv);
- /* if HW rf-kill is set dont allow ON state */
- if (iwl_is_rfkill(priv))
- err = -EBUSY;
break;
case RFKILL_STATE_SOFT_BLOCKED:
iwl_radio_kill_sw_disable_radio(priv);
- if (!iwl_is_rfkill(priv))
- err = -EBUSY;
break;
default:
IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
break;
}
+out:
mutex_unlock(&priv->mutex);
return err;
@@ -91,7 +92,7 @@ int iwl_rfkill_init(struct iwl_priv *priv)
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->state = RFKILL_STATE_UNBLOCKED;
priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
@@ -177,9 +178,14 @@ 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;
+ if (iwl_is_rfkill_hw(priv)) {
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_HARD_BLOCKED;
+ return;
+ }
+
+ if (!iwl_is_rfkill_sw(priv))
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_UNBLOCKED;
else
- priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);