All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhu Yi <yi.zhu@intel.com>
To: linville@tuxdriver.com
Cc: linux-wireless@vger.kernel.org,
	Abhijeet Kolekar <abhijeet.kolekar@intel.com>,
	Adel Gadllah <adel.gadllah@gmail.com>, Zhu Yi <yi.zhu@intel.com>
Subject: [PATCH 18/33] iwlwifi : Patch adds rfkill subsystem for 3945
Date: Mon, 30 Jun 2008 17:23:18 +0800	[thread overview]
Message-ID: <1214817813-17639-19-git-send-email-yi.zhu@intel.com> (raw)
In-Reply-To: <1214817813-17639-18-git-send-email-yi.zhu@intel.com>

From: Abhijeet Kolekar <abhijeet.kolekar@intel.com>

The patch removes the sysfs interface from iwl3945 and uses
the rfkill subsystem instead.

Original patch by Adel, I fixed the patch to work it properly.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.h     |   25 ++++
 drivers/net/wireless/iwlwifi/iwl3945-base.c |  186 ++++++++++++++++++++++-----
 2 files changed, 176 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index a9b3eda..a774978 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -36,6 +36,10 @@
 #include <linux/kernel.h>
 #include <net/ieee80211_radiotap.h>
 
+/*used for rfkill*/
+#include <linux/rfkill.h>
+#include <linux/input.h>
+
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 extern struct pci_device_id iwl3945_hw_card_ids[];
 
@@ -686,6 +690,23 @@ enum {
 
 #endif
 
+#ifdef CONFIG_IWLWIFI_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);
+#else
+static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {}
+static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {}
+static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; }
+#endif
+
 #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
 
 struct iwl3945_priv {
@@ -779,6 +800,10 @@ 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;
+#endif
+
 #ifdef CONFIG_IWL3945_LEDS
 	struct iwl3945_led led[IWL_LED_TRG_MAX];
 	unsigned long last_blink_time;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index fe60319..43cb8ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5921,7 +5921,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
 			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-					STATUS_IN_SUSPEND;
+					STATUS_IN_SUSPEND |
+				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+					STATUS_EXIT_PENDING;
 		goto exit;
 	}
 
@@ -5936,7 +5938,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
 			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
 				STATUS_IN_SUSPEND |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
-				STATUS_FW_ERROR;
+				STATUS_FW_ERROR |
+			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+				STATUS_EXIT_PENDING;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -6008,11 +6012,12 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
 	else {
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 		if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+			iwl3945_rfkill_set_hw_state(priv);
 			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
 			return -ENODEV;
 		}
 	}
-
+	iwl3945_rfkill_set_hw_state(priv);
 	iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
 
 	rc = iwl3945_hw_nic_init(priv);
@@ -6068,6 +6073,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
 
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
 	__iwl3945_down(priv);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	/* tried to restart and config the device for as long as our
 	 * patience could withstand */
@@ -6135,6 +6141,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
 				    "Kill switch must be turned off for "
 				    "wireless networking to work.\n");
 	}
+
+	iwl3945_rfkill_set_hw_state(priv);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -7412,37 +7420,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
 
 #endif /* CONFIG_IWL3945_DEBUG */
 
-static ssize_t show_rf_kill(struct device *d,
-			    struct device_attribute *attr, char *buf)
-{
-	/*
-	 * 0 - RF kill not enabled
-	 * 1 - SW based RF kill active (sysfs)
-	 * 2 - HW based RF kill active
-	 * 3 - Both HW and SW based RF kill active
-	 */
-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-	int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
-		  (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
-
-	return sprintf(buf, "%i\n", val);
-}
-
-static ssize_t store_rf_kill(struct device *d,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_radio_kill_sw(priv, buf[0] == '1');
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
-
 static ssize_t show_temperature(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
@@ -7928,7 +7905,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
 #endif
 	&dev_attr_power_level.attr,
 	&dev_attr_retry_rate.attr,
-	&dev_attr_rf_kill.attr,
 	&dev_attr_rs_window.attr,
 	&dev_attr_statistics.attr,
 	&dev_attr_status.attr,
@@ -8169,6 +8145,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 
+	err = iwl3945_rfkill_init(priv);
+	if (err)
+		IWL_ERROR("Unable to initialize RFKILL system. "
+				  "Ignoring error: %d\n", err);
+
 	return 0;
 
  out_free_geos:
@@ -8231,6 +8212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
+	iwl3945_rfkill_unregister(priv);
 	iwl3945_dealloc_ucode_pci(priv);
 
 	if (priv->rxq.bd)
@@ -8299,6 +8281,140 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
 
 #endif /* CONFIG_PM */
 
+/*************** RFKILL FUNCTIONS **********/
+#ifdef CONFIG_IWLWIFI_RFKILL
+/* software rf-kill from user */
+static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
+{
+	struct iwl3945_priv *priv = data;
+	int err = 0;
+
+	if (!priv->rfkill_mngr.rfkill)
+	return 0;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return 0;
+
+	IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+	mutex_lock(&priv->mutex);
+
+	switch (state) {
+	case RFKILL_STATE_ON:
+		iwl3945_radio_kill_sw(priv, 0);
+		/* if HW rf-kill is set dont allow ON state */
+		if (iwl3945_is_rfkill(priv))
+			err = -EBUSY;
+		break;
+	case RFKILL_STATE_OFF:
+		iwl3945_radio_kill_sw(priv, 1);
+		if (!iwl3945_is_rfkill(priv))
+			err = -EBUSY;
+		break;
+	}
+	mutex_unlock(&priv->mutex);
+
+	return err;
+}
+
+int iwl3945_rfkill_init(struct iwl3945_priv *priv)
+{
+	struct device *device = wiphy_dev(priv->hw->wiphy);
+	int ret = 0;
+
+	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) {
+		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 = iwl3945_rfkill_soft_rf_kill;
+	priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
+
+	priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
+	priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
+
+	priv->rfkill_mngr.input_dev = input_allocate_device();
+	if (!priv->rfkill_mngr.input_dev) {
+		IWL_ERROR("Unable to allocate rfkill input device.\n");
+		ret = -ENOMEM;
+		goto freed_rfkill;
+	}
+
+	priv->rfkill_mngr.input_dev->name = priv->cfg->name;
+	priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
+	priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
+	priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
+	priv->rfkill_mngr.input_dev->dev.parent = device;
+	priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
+	set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
+
+	ret = rfkill_register(priv->rfkill_mngr.rfkill);
+	if (ret) {
+		IWL_ERROR("Unable to register rfkill: %d\n", ret);
+		goto free_input_dev;
+	}
+
+	ret = input_register_device(priv->rfkill_mngr.input_dev);
+	if (ret) {
+		IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
+		goto unregister_rfkill;
+	}
+
+	IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+	return ret;
+
+unregister_rfkill:
+	rfkill_unregister(priv->rfkill_mngr.rfkill);
+	priv->rfkill_mngr.rfkill = NULL;
+
+free_input_dev:
+	input_free_device(priv->rfkill_mngr.input_dev);
+	priv->rfkill_mngr.input_dev = NULL;
+
+freed_rfkill:
+	if (priv->rfkill_mngr.rfkill != NULL)
+		rfkill_free(priv->rfkill_mngr.rfkill);
+	priv->rfkill_mngr.rfkill = NULL;
+
+error:
+	IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+	return ret;
+}
+
+void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
+{
+
+	if (priv->rfkill_mngr.input_dev)
+		input_unregister_device(priv->rfkill_mngr.input_dev);
+
+	if (priv->rfkill_mngr.rfkill)
+		rfkill_unregister(priv->rfkill_mngr.rfkill);
+
+	priv->rfkill_mngr.input_dev = NULL;
+	priv->rfkill_mngr.rfkill = NULL;
+}
+
+/* set rf-kill to the right state. */
+void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
+{
+
+	if (!priv->rfkill_mngr.rfkill)
+		return;
+
+	if (!iwl3945_is_rfkill(priv))
+		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
+	else
+		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+}
+#endif
+
 /*****************************************************************************
  *
  * driver and module entry point
-- 
1.5.3.6


  reply	other threads:[~2008-06-30  9:27 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-30  9:23 [PATCH 00/33] iwlwifi driver 06/30 updates Zhu Yi
2008-06-30  9:23 ` [PATCH 01/33] iwlwifi: configure uCode to use open loop tx power algorithm Zhu Yi
2008-06-30  9:23   ` [PATCH 02/33] iwlwifi: Add eeprom version to the version file in sysfs Zhu Yi
2008-06-30  9:23     ` [PATCH 03/33] iwlwifi: better station table maintenance Zhu Yi
2008-06-30  9:23       ` [PATCH 04/33] iwlwifi: use iwl_is_associated when possible Zhu Yi
2008-06-30  9:23         ` [PATCH 05/33] iwlwifi: add REPLY_TX_POWER_DBM_CMD to get_cmd_string Zhu Yi
2008-06-30  9:23           ` [PATCH 06/33] iwlwifi: send ADD_STA before RXON with assoc bit Zhu Yi
2008-06-30  9:23             ` [PATCH 07/33] iwlwifi: move RX stats to core, and move temperature to handler Zhu Yi
2008-06-30  9:23               ` [PATCH 08/33] iwlwifi: don't send REPLY_REMOVE_ALL_STA upon exit Zhu Yi
2008-06-30  9:23                 ` [PATCH 09/33] iwlwifi: move RX handlers to iwl-rx.c Zhu Yi
2008-06-30  9:23                   ` [PATCH 10/33] iwlwifi: remove useless network and duplicate checking Zhu Yi
2008-06-30  9:23                     ` [PATCH 11/33] iwlwifi: setup compressed BA handler Zhu Yi
2008-06-30  9:23                       ` [PATCH 12/33] iwlwifi: move rx aggregation functions to iwl-rx.c Zhu Yi
2008-06-30  9:23                         ` [PATCH 13/33] iwlwifi: remove obsolete lq_ready use Zhu Yi
2008-06-30  9:23                           ` [PATCH 14/33] iwlwifi: fix IBSS association flow Zhu Yi
2008-06-30  9:23                             ` [PATCH 15/33] iwlwifi: keep the STATUS_EXIT_PENDING flag till the end of down flow Zhu Yi
2008-06-30  9:23                               ` [PATCH 16/33] mac80211: add beacon timestamp to beacon template in IBSS Zhu Yi
2008-06-30  9:23                                 ` [PATCH 17/33] iwlwifi: adjust TSF " Zhu Yi
2008-06-30  9:23                                   ` Zhu Yi [this message]
2008-06-30  9:23                                     ` [PATCH 19/33] iwlwifi: don't bring up interface if RF-kill avoids radio Zhu Yi
2008-06-30  9:23                                       ` [PATCH 20/33] iwlwifi: unite common settings of HW params Zhu Yi
2008-06-30  9:23                                         ` [PATCH 21/33] iwlwifi: control 11n capabilities through module param Zhu Yi
2008-06-30  9:23                                           ` [PATCH 22/33] iwlwifi: Remove unnecessary code Zhu Yi
2008-06-30  9:23                                             ` [PATCH 23/33] iwlwifi: eliminate iwl4965_mac_get_tsf Zhu Yi
2008-06-30  9:23                                               ` [PATCH 24/33] iwlwifi: blocking mac_start until uCode is complete Zhu Yi
2008-06-30  9:23                                                 ` [PATCH 25/33] iwlwifi: clean up HW RF-kill state machine and restarts Zhu Yi
2008-06-30  9:23                                                   ` [PATCH 26/33] iwlwifi: fix 4965 uCode load Zhu Yi
2008-06-30  9:23                                                     ` [PATCH 27/33] iwlwifi: fix incorrect 5GHz rates reported in monitor mode Zhu Yi
2008-06-30  9:23                                                       ` [PATCH 28/33] iwlwifi: fix incorrect monitor mode operation Zhu Yi
2008-06-30  9:23                                                         ` [PATCH 29/33] iwlwifi: drop skb silently for Tx request in monitor mode Zhu Yi
2008-06-30  9:23                                                           ` [PATCH 30/33] iwlwifi: enable packet injection for iwl3945 Zhu Yi
2008-06-30  9:23                                                             ` [PATCH 31/33] iwlwifi: fix iwl4965 temperature callback calibration issue Zhu Yi
2008-06-30  9:23                                                               ` [PATCH 32/33] iwl3945: remove RFKILL_STATE_HARD_BLOCKED warnings Zhu Yi
2008-06-30  9:23                                                                 ` [PATCH 33/33] iwlwifi: remove the input device from rfkill_mngr Zhu Yi
2008-06-30 10:07                                                             ` [PATCH 30/33] iwlwifi: enable packet injection for iwl3945 Stefanik Gábor
2008-06-30 10:22                                                           ` [PATCH 29/33] iwlwifi: drop skb silently for Tx request in monitor mode Stefanik Gábor
2008-06-30 10:26                                                             ` Michael Buesch
2008-06-30 10:28                                                               ` Stefanik Gábor
2008-07-02  1:07                                                                 ` Zhu Yi
2008-06-30  9:56 ` [PATCH 00/33] iwlwifi driver 06/30 updates drago01
2008-07-02  3:05   ` Zhu Yi
2008-07-02  8:39     ` drago01
2008-07-02  8:41       ` Zhu Yi
2008-07-02  8:51         ` drago01

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1214817813-17639-19-git-send-email-yi.zhu@intel.com \
    --to=yi.zhu@intel.com \
    --cc=abhijeet.kolekar@intel.com \
    --cc=adel.gadllah@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.