Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 103288
b: refs/heads/master
c: ebef200
h: refs/heads/master
v: v3
  • Loading branch information
Abhijeet Kolekar authored and John W. Linville committed Jun 30, 2008
1 parent 39c8b37 commit 5b6f33f
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2ff75b7877c40b1917f23cc5fafccaf3c1ab4745
refs/heads/master: ebef2008082f579d8a40cc92e868fe8bf1296a60
25 changes: 25 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-3945.h
Original file line number Diff line number Diff line change
Expand Up @@ -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[];

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
186 changes: 151 additions & 35 deletions trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 5b6f33f

Please sign in to comment.