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 <adel.gadllah@xxxxxxxxx> > Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@xxxxxxxxx> > Signed-off-by: Zhu Yi <yi.zhu@xxxxxxxxx> > > 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 majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html