Skip to content

Commit

Permalink
iwlwifi: remove input device and fix rfkill state
Browse files Browse the repository at this point in the history
This patch fixes the iwlwifi rfkill. It removes the input device from iwl3945,
adds support for RFKILL_STATE_HARD_BLOCKED and calls rfkill_force_state() to
update the state rather than accessing it directly.
The calls to iwl|iwl3945_rfkill_set_hw_state() had to be moved because
rfkill_force_state() cannot be called from an atomic context.
Tested on iwl3945 and seems to work fine.

Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Ivo van Doorn <ivdoorn@gmail.com>
Cc: Fabien Crespel <fcrespel@gmail.com>
Cc: Zhu Yi <yi.zhu@intel.com>
Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Adel Gadllah authored and John W. Linville committed Jul 8, 2008
1 parent ebd7448 commit 80fcc9e
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 111 deletions.
5 changes: 5 additions & 0 deletions drivers/net/wireless/iwlwifi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ config IWL3945
select IWLWIFI
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
select RFKILL if IWL3945_RFKILL
---help---
Select to build the driver supporting the:

Expand All @@ -126,6 +127,10 @@ config IWL3945
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl3945.ko.

config IWL3945_RFKILL
bool "Enable RF kill support in iwl3945 drivers"
depends on IWL3945

config IWL3945_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl3945 drivers"
depends on IWL3945
Expand Down
11 changes: 3 additions & 8 deletions drivers/net/wireless/iwlwifi/iwl-3945.h
Original file line number Diff line number Diff line change
Expand Up @@ -690,14 +690,9 @@ enum {

#endif

#ifdef CONFIG_IWLWIFI_RFKILL
#ifdef CONFIG_IWL3945_RFKILL
struct iwl3945_priv;

struct iwl3945_rfkill_mngr {
struct rfkill *rfkill;
struct input_dev *input_dev;
};

void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv);
void iwl3945_rfkill_unregister(struct iwl3945_priv *priv);
int iwl3945_rfkill_init(struct iwl3945_priv *priv);
Expand Down Expand Up @@ -800,8 +795,8 @@ struct iwl3945_priv {
struct iwl3945_init_alive_resp card_alive_init;
struct iwl3945_alive_resp card_alive;

#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl3945_rfkill_mngr rfkill_mngr;
#ifdef CONFIG_IWL3945_RFKILL
struct rfkill *rfkill;
#endif

#ifdef CONFIG_IWL3945_LEDS
Expand Down
13 changes: 11 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ struct iwl_priv {
struct iwl_init_alive_resp card_alive_init;
struct iwl_alive_resp card_alive;
#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr rfkill_mngr;
struct rfkill *rfkill;
#endif

#ifdef CONFIG_IWLWIFI_LEDS
Expand Down
57 changes: 31 additions & 26 deletions drivers/net/wireless/iwlwifi/iwl-rfkill.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ 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)
if (!priv->rfkill)
return 0;

if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Expand All @@ -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;
Expand All @@ -82,23 +82,23 @@ int iwl_rfkill_init(struct iwl_priv *priv)
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) {
priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
if (!priv->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->name = priv->cfg->name;
priv->rfkill->data = priv;
priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
priv->rfkill->user_claim_unsupported = 1;

priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
priv->rfkill->dev.class->suspend = NULL;
priv->rfkill->dev.class->resume = NULL;

ret = rfkill_register(priv->rfkill_mngr.rfkill);
ret = rfkill_register(priv->rfkill);
if (ret) {
IWL_ERROR("Unable to register rfkill: %d\n", ret);
goto free_rfkill;
Expand All @@ -108,9 +108,9 @@ int iwl_rfkill_init(struct iwl_priv *priv)
return ret;

free_rfkill:
if (priv->rfkill_mngr.rfkill != NULL)
rfkill_free(priv->rfkill_mngr.rfkill);
priv->rfkill_mngr.rfkill = NULL;
if (priv->rfkill != NULL)
rfkill_free(priv->rfkill);
priv->rfkill = NULL;

error:
IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
Expand All @@ -121,22 +121,27 @@ EXPORT_SYMBOL(iwl_rfkill_init);
void iwl_rfkill_unregister(struct iwl_priv *priv)
{

if (priv->rfkill_mngr.rfkill)
rfkill_unregister(priv->rfkill_mngr.rfkill);
if (priv->rfkill)
rfkill_unregister(priv->rfkill);

priv->rfkill_mngr.rfkill = NULL;
priv->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)
if (!priv->rfkill)
return;

if (!iwl_is_rfkill(priv))
priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
if (iwl_is_rfkill_hw(priv)) {
rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
return;
}

if (!iwl_is_rfkill_sw(priv))
rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
else
priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
3 changes: 0 additions & 3 deletions drivers/net/wireless/iwlwifi/iwl-rfkill.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ struct iwl_priv;
#include <linux/rfkill.h>

#ifdef CONFIG_IWLWIFI_RFKILL
struct iwl_rfkill_mngr {
struct rfkill *rfkill;
};

void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
void iwl_rfkill_unregister(struct iwl_priv *priv);
Expand Down
Loading

0 comments on commit 80fcc9e

Please sign in to comment.