mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-22 17:33:01 +00:00
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 <adel.gadllah@gmail.com> Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
2ff75b7877
commit
ebef200808
@ -36,6 +36,10 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <net/ieee80211_radiotap.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 */
|
/* Hardware specific file defines the PCI IDs table for that hardware module */
|
||||||
extern struct pci_device_id iwl3945_hw_card_ids[];
|
extern struct pci_device_id iwl3945_hw_card_ids[];
|
||||||
|
|
||||||
@ -686,6 +690,23 @@ enum {
|
|||||||
|
|
||||||
#endif
|
#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
|
#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
|
||||||
|
|
||||||
struct iwl3945_priv {
|
struct iwl3945_priv {
|
||||||
@ -779,6 +800,10 @@ struct iwl3945_priv {
|
|||||||
struct iwl3945_init_alive_resp card_alive_init;
|
struct iwl3945_init_alive_resp card_alive_init;
|
||||||
struct iwl3945_alive_resp card_alive;
|
struct iwl3945_alive_resp card_alive;
|
||||||
|
|
||||||
|
#ifdef CONFIG_IWLWIFI_RFKILL
|
||||||
|
struct iwl3945_rfkill_mngr rfkill_mngr;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IWL3945_LEDS
|
#ifdef CONFIG_IWL3945_LEDS
|
||||||
struct iwl3945_led led[IWL_LED_TRG_MAX];
|
struct iwl3945_led led[IWL_LED_TRG_MAX];
|
||||||
unsigned long last_blink_time;
|
unsigned long last_blink_time;
|
||||||
|
@ -5921,7 +5921,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
|
|||||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||||
STATUS_GEO_CONFIGURED |
|
STATUS_GEO_CONFIGURED |
|
||||||
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5936,7 +5938,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
|
|||||||
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
|
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
|
||||||
STATUS_IN_SUSPEND |
|
STATUS_IN_SUSPEND |
|
||||||
test_bit(STATUS_FW_ERROR, &priv->status) <<
|
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);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
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 {
|
else {
|
||||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||||
if (!test_bit(STATUS_IN_SUSPEND, &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");
|
IWL_WARNING("Radio disabled by HW RF Kill switch\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iwl3945_rfkill_set_hw_state(priv);
|
||||||
iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
|
iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
|
||||||
|
|
||||||
rc = iwl3945_hw_nic_init(priv);
|
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);
|
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||||
__iwl3945_down(priv);
|
__iwl3945_down(priv);
|
||||||
|
clear_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||||
|
|
||||||
/* tried to restart and config the device for as long as our
|
/* tried to restart and config the device for as long as our
|
||||||
* patience could withstand */
|
* patience could withstand */
|
||||||
@ -6135,6 +6141,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
|
|||||||
"Kill switch must be turned off for "
|
"Kill switch must be turned off for "
|
||||||
"wireless networking to work.\n");
|
"wireless networking to work.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwl3945_rfkill_set_hw_state(priv);
|
||||||
mutex_unlock(&priv->mutex);
|
mutex_unlock(&priv->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7412,37 +7420,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
|||||||
|
|
||||||
#endif /* CONFIG_IWL3945_DEBUG */
|
#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,
|
static ssize_t show_temperature(struct device *d,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
@ -7928,7 +7905,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
|
|||||||
#endif
|
#endif
|
||||||
&dev_attr_power_level.attr,
|
&dev_attr_power_level.attr,
|
||||||
&dev_attr_retry_rate.attr,
|
&dev_attr_retry_rate.attr,
|
||||||
&dev_attr_rf_kill.attr,
|
|
||||||
&dev_attr_rs_window.attr,
|
&dev_attr_rs_window.attr,
|
||||||
&dev_attr_statistics.attr,
|
&dev_attr_statistics.attr,
|
||||||
&dev_attr_status.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_save_state(pdev);
|
||||||
pci_disable_device(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;
|
return 0;
|
||||||
|
|
||||||
out_free_geos:
|
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);
|
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||||
|
|
||||||
|
iwl3945_rfkill_unregister(priv);
|
||||||
iwl3945_dealloc_ucode_pci(priv);
|
iwl3945_dealloc_ucode_pci(priv);
|
||||||
|
|
||||||
if (priv->rxq.bd)
|
if (priv->rxq.bd)
|
||||||
@ -8299,6 +8281,140 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
|
|||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#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
|
* driver and module entry point
|
||||||
|
Loading…
Reference in New Issue
Block a user