2008-06-26 20:47:18

by Abhijeet Kolekar

[permalink] [raw]
Subject: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d

iwlwifi : Patch adds rfkill subsystem for 3945

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 <[email protected]>
Signed-off-by: Abhijeet Kolekar <[email protected]>
Signed-off-by: Zhu Yi <[email protected]>

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 cca2119..eabbb85 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -5913,7 +5913,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;
}

@@ -5928,7 +5930,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);
@@ -6000,11 +6004,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);
@@ -6060,6 +6065,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 */
@@ -6127,6 +6133,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);
}

@@ -7409,37 +7417,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)
{
@@ -7925,7 +7902,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,
@@ -8166,6 +8142,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:
@@ -8228,6 +8209,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)
@@ -8296,6 +8278,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


2008-06-26 21:13:09

by Abhijeet Kolekar

[permalink] [raw]
Subject: RE: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d



-----Original Message-----
From: drago01 [mailto:[email protected]]
Sent: Thursday, June 26, 2008 2:12 PM
To: Ivo van Doorn
Cc: Kolekar, Abhijeet; [email protected];
[email protected]; [email protected]; Zhu, Yi
Subject: Re: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d

On Thu, Jun 26, 2008 at 10:59 PM, Ivo van Doorn <[email protected]>
wrote:
> On Thursday 26 June 2008, Abhijeet Kolekar wrote:
>> iwlwifi : Patch adds rfkill subsystem for 3945
>>
>> The patch removes the sysfs interface from iwl3945 and uses
>> the rfkill subsystem instead.
>
> Shouldn't the driver depend on CONFIG_RFKILL?
> Otherwise compilation will fail when CONFIG_RFKILL isn't selected...

"[PATCH -next] iwlwifi: fix build for CONFIG_INPUT=n" adresses part of
this.

IWLWIFI_RFKILL depends on IWLCORE but iwl3945 does not use iwlcore
module.
Should we just add a IWL3945_RFKILL and add he changes from the
mentioned patch to 3945 too?

If its ok I can send a patch.

That will be great!!

2008-06-26 21:09:41

by Randy Dunlap

[permalink] [raw]
Subject: Re: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d

On Thu, 26 Jun 2008, Ivo van Doorn wrote:

> On Thursday 26 June 2008, Abhijeet Kolekar wrote:
> > iwlwifi : Patch adds rfkill subsystem for 3945
> >
> > The patch removes the sysfs interface from iwl3945 and uses
> > the rfkill subsystem instead.
>
> Shouldn't the driver depend on CONFIG_RFKILL?
> Otherwise compilation will fail when CONFIG_RFKILL isn't selected...
> Since you are using an input device as well, the same would go for
> CONFIG_INPUT

Yes, RFKILL and RFKILL_INPUT must be honored so that the driver
will build clean when either of them is disabled.

I sent a patch just a couple of days ago for this, so that
it builds cleanly in linux-next. It was acked by Zhu Yi.
See http://marc.info/?l=linux-next&m=121436670630784&w=2

Please incorporate it or something like it.
Oh, maybe my patch was for iwlwifi and this one is for
3945? Still, a similar patch is needed for 3945.


> Ivo
>
> > Original patch by Adel, I fixed the patch to work it properly.
> >
> > Signed-off-by: Adel Gadllah <[email protected]>
> > Signed-off-by: Abhijeet Kolekar <[email protected]>
> > Signed-off-by: Zhu Yi <[email protected]>
> >
> > 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 cca2119..eabbb85 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> > @@ -5913,7 +5913,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;
> > }
> >
> > @@ -5928,7 +5930,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);
> > @@ -6000,11 +6004,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);
> > @@ -6060,6 +6065,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 */
> > @@ -6127,6 +6133,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);
> > }
> >
> > @@ -7409,37 +7417,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)
> > {
> > @@ -7925,7 +7902,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,
> > @@ -8166,6 +8142,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:
> > @@ -8228,6 +8209,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)
> > @@ -8296,6 +8278,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
> > --

--
~Randy

2008-06-26 20:57:54

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d

On Thursday 26 June 2008, Abhijeet Kolekar wrote:
> iwlwifi : Patch adds rfkill subsystem for 3945
>
> The patch removes the sysfs interface from iwl3945 and uses
> the rfkill subsystem instead.

Shouldn't the driver depend on CONFIG_RFKILL?
Otherwise compilation will fail when CONFIG_RFKILL isn't selected...
Since you are using an input device as well, the same would go for
CONFIG_INPUT

Ivo

> Original patch by Adel, I fixed the patch to work it properly.
>
> Signed-off-by: Adel Gadllah <[email protected]>
> Signed-off-by: Abhijeet Kolekar <[email protected]>
> Signed-off-by: Zhu Yi <[email protected]>
>
> 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 cca2119..eabbb85 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -5913,7 +5913,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;
> }
>
> @@ -5928,7 +5930,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);
> @@ -6000,11 +6004,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);
> @@ -6060,6 +6065,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 */
> @@ -6127,6 +6133,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);
> }
>
> @@ -7409,37 +7417,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)
> {
> @@ -7925,7 +7902,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,
> @@ -8166,6 +8142,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:
> @@ -8228,6 +8209,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)
> @@ -8296,6 +8278,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
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>



2008-06-26 21:11:42

by drago01

[permalink] [raw]
Subject: Re: commit 5dc4dfd6165883b6629a48256dc4eadf76d6b65d

On Thu, Jun 26, 2008 at 10:59 PM, Ivo van Doorn <[email protected]> wrote:
> On Thursday 26 June 2008, Abhijeet Kolekar wrote:
>> iwlwifi : Patch adds rfkill subsystem for 3945
>>
>> The patch removes the sysfs interface from iwl3945 and uses
>> the rfkill subsystem instead.
>
> Shouldn't the driver depend on CONFIG_RFKILL?
> Otherwise compilation will fail when CONFIG_RFKILL isn't selected...

"[PATCH -next] iwlwifi: fix build for CONFIG_INPUT=n" adresses part of this.

IWLWIFI_RFKILL depends on IWLCORE but iwl3945 does not use iwlcore module.
Should we just add a IWL3945_RFKILL and add he changes from the
mentioned patch to 3945 too?

If its ok I can send a patch.