Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80fcc9e2 authored by Adel Gadllah's avatar Adel Gadllah Committed by John W. Linville
Browse files

iwlwifi: remove input device and fix rfkill state



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: default avatarAdel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ebd74487
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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:

@@ -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
+3 −8
Original line number Diff line number Diff line
@@ -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);
@@ -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
+11 −2
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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
+31 −26
Original line number Diff line number Diff line
@@ -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))
@@ -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;
@@ -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;
@@ -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");
@@ -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);
Loading