Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
This commit is contained in:
commit
327723edeb
@ -2978,7 +2978,6 @@ F: drivers/net/ixgb/
|
||||
F: drivers/net/ixgbe/
|
||||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
@ -2988,7 +2987,6 @@ F: Documentation/networking/README.ipw2100
|
||||
F: drivers/net/wireless/ipw2x00/ipw2100.*
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
@ -3019,8 +3017,8 @@ F: drivers/net/wimax/i2400m/
|
||||
F: include/linux/wimax/i2400m.h
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
@ -3030,7 +3028,6 @@ F: drivers/net/wireless/iwlwifi/
|
||||
|
||||
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
|
||||
M: Samuel Ortiz <samuel.ortiz@intel.com>
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
|
@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
|
||||
static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id);
|
||||
static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev);
|
||||
static int ath5k_pci_resume(struct device *dev);
|
||||
|
||||
@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
|
||||
#define ATH5K_PM_OPS (&ath5k_pm_ops)
|
||||
#else
|
||||
#define ATH5K_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static struct pci_driver ath5k_pci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
@ -708,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
|
||||
@ -734,7 +734,7 @@ static int ath5k_pci_resume(struct device *dev)
|
||||
ath5k_led_enable(sc);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
||||
/***********************\
|
||||
@ -3140,13 +3140,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
|
||||
if (*new_flags & FIF_PROMISC_IN_BSS) {
|
||||
rfilt |= AR5K_RX_FILTER_PROM;
|
||||
__set_bit(ATH_STAT_PROMISC, sc->status);
|
||||
} else {
|
||||
__clear_bit(ATH_STAT_PROMISC, sc->status);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ATH_STAT_PROMISC, sc->status))
|
||||
rfilt |= AR5K_RX_FILTER_PROM;
|
||||
|
||||
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
|
||||
if (*new_flags & FIF_ALLMULTI) {
|
||||
mfilt[0] = ~0;
|
||||
|
@ -1814,6 +1814,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
|
||||
u8 def_ant, tx_ant, ee_mode;
|
||||
u32 sta_id1 = 0;
|
||||
|
||||
/* if channel is not initialized yet we can't set the antennas
|
||||
* so just store the mode. it will be set on the next reset */
|
||||
if (channel == NULL) {
|
||||
ah->ah_ant_mode = ant_mode;
|
||||
return;
|
||||
}
|
||||
|
||||
def_ant = ah->ah_def_ant;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
|
||||
int events = 0;
|
||||
u16 ev;
|
||||
|
||||
/* Detect early interrupt before driver is fully configued */
|
||||
if (!dev->base_addr) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
|
||||
dev->name);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
|
@ -2852,6 +2852,7 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
.isr = iwl_isr_legacy,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.manage_ibss_station = iwl3945_manage_ibss_station,
|
||||
.recover_from_tx_stall = iwl_bg_monitor_recover,
|
||||
.check_plcp_health = iwl3945_good_plcp_health,
|
||||
|
||||
.debugfs_ops = {
|
||||
|
@ -1119,10 +1119,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int i, added = 0;
|
||||
int added = 0;
|
||||
u16 channel = 0;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
@ -1137,32 +1136,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
/* only scan single channel, good enough to reset the RF */
|
||||
/* pick the first valid not in-use channel */
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
for (i = 14; i < priv->channel_count; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel = priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel =
|
||||
priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
if (channel) {
|
||||
scan_ch->channel = cpu_to_le16(channel);
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
|
@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_station_priv *sta_priv;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
|
||||
if (sta) {
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
@ -1133,6 +1134,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
atomic_dec_return(&sta_priv->pending_frames) == 0)
|
||||
ieee80211_sta_block_awake(priv->hw, sta, false);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
||||
}
|
||||
|
@ -1484,6 +1484,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/*
|
||||
* The following adds a new attribute to the sysfs representation
|
||||
* of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
|
||||
* used for controlling the debug level.
|
||||
*
|
||||
* See the level definitions in iwl for details.
|
||||
*
|
||||
* The debug_level being managed using sysfs below is a per device debug
|
||||
* level that is used instead of the global debug level if it (the per
|
||||
* device debug level) is set.
|
||||
*/
|
||||
static ssize_t show_debug_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
|
||||
}
|
||||
static ssize_t store_debug_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
|
||||
else {
|
||||
priv->debug_level = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv,
|
||||
"Not enough memory to generate traffic log\n");
|
||||
}
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
show_debug_level, store_debug_level);
|
||||
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
return sprintf(buf, "%d\n", priv->temperature);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
|
||||
|
||||
static ssize_t show_tx_power(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return sprintf(buf, "off\n");
|
||||
else
|
||||
return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
|
||||
}
|
||||
|
||||
static ssize_t store_tx_power(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static ssize_t show_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
|
||||
}
|
||||
|
||||
static ssize_t store_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "Input is not in decimal form.\n");
|
||||
else {
|
||||
if (!iwl_is_associated(priv))
|
||||
priv->cfg->use_rts_for_ht = val ? true : false;
|
||||
else
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
"Change protection mechanism is not allowed\n");
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
|
||||
show_rts_ht_protection, store_rts_ht_protection);
|
||||
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
&dev_attr_rts_ht_protection.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwl_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwl_sysfs_entries,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* uCode download functions
|
||||
@ -1965,6 +2115,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
if (err)
|
||||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
|
||||
err = sysfs_create_group(&priv->pci_dev->dev.kobj,
|
||||
&iwl_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "failed to create sysfs device attributes\n");
|
||||
goto out_unbind;
|
||||
}
|
||||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&priv->_agn.firmware_loading_complete);
|
||||
@ -3262,141 +3419,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/*
|
||||
* The following adds a new attribute to the sysfs representation
|
||||
* of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
|
||||
* used for controlling the debug level.
|
||||
*
|
||||
* See the level definitions in iwl for details.
|
||||
*
|
||||
* The debug_level being managed using sysfs below is a per device debug
|
||||
* level that is used instead of the global debug level if it (the per
|
||||
* device debug level) is set.
|
||||
*/
|
||||
static ssize_t show_debug_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
|
||||
}
|
||||
static ssize_t store_debug_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
|
||||
else {
|
||||
priv->debug_level = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv,
|
||||
"Not enough memory to generate traffic log\n");
|
||||
}
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
show_debug_level, store_debug_level);
|
||||
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
return sprintf(buf, "%d\n", priv->temperature);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
|
||||
|
||||
static ssize_t show_tx_power(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return sprintf(buf, "off\n");
|
||||
else
|
||||
return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
|
||||
}
|
||||
|
||||
static ssize_t store_tx_power(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static ssize_t show_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
|
||||
}
|
||||
|
||||
static ssize_t store_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "Input is not in decimal form.\n");
|
||||
else {
|
||||
if (!iwl_is_associated(priv))
|
||||
priv->cfg->use_rts_for_ht = val ? true : false;
|
||||
else
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
"Change protection mechanism is not allowed\n");
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
|
||||
show_rts_ht_protection, store_rts_ht_protection);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* driver setup and teardown
|
||||
@ -3550,21 +3572,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
kfree(priv->scan_cmd);
|
||||
}
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
&dev_attr_rts_ht_protection.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwl_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwl_sysfs_entries,
|
||||
};
|
||||
|
||||
static struct ieee80211_ops iwl_hw_ops = {
|
||||
.tx = iwl_mac_tx,
|
||||
.start = iwl_mac_start,
|
||||
@ -3750,11 +3757,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
|
||||
goto out_disable_msi;
|
||||
}
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "failed to create sysfs device attributes\n");
|
||||
goto out_free_irq;
|
||||
}
|
||||
|
||||
iwl_setup_deferred_work(priv);
|
||||
iwl_setup_rx_handlers(priv);
|
||||
@ -3788,15 +3790,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
err = iwl_request_firmware(priv, true);
|
||||
if (err)
|
||||
goto out_remove_sysfs;
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_sysfs:
|
||||
out_destroy_workqueue:
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
|
||||
out_free_irq:
|
||||
free_irq(priv->pci_dev->irq, priv);
|
||||
iwl_free_isr_ict(priv);
|
||||
out_disable_msi:
|
||||
|
@ -854,6 +854,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_chain);
|
||||
|
||||
/* Return valid channel */
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
int i;
|
||||
u8 channel = 0;
|
||||
|
||||
/* only scan single channel, good enough to reset the RF */
|
||||
/* pick the first valid not in-use channel */
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
for (i = 14; i < priv->channel_count; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel = priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel =
|
||||
priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_single_channel_number);
|
||||
|
||||
/**
|
||||
* iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
|
||||
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
|
||||
|
@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band);
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||
|
@ -1844,6 +1844,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl3945_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int added = 0;
|
||||
u8 channel = 0;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
if (!sband) {
|
||||
IWL_ERR(priv, "invalid band\n");
|
||||
return added;
|
||||
}
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
|
||||
if (channel) {
|
||||
scan_ch->channel = channel;
|
||||
scan_ch->type = 0; /* passive */
|
||||
scan_ch->active_dwell = cpu_to_le16(active_dwell);
|
||||
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
|
||||
/* Set txpower levels to defaults */
|
||||
scan_ch->tpc.dsp_atten = 110;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
|
||||
added++;
|
||||
} else
|
||||
IWL_ERR(priv, "no valid channel found\n");
|
||||
return added;
|
||||
}
|
||||
|
||||
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u8 is_active, u8 n_probes,
|
||||
@ -2992,9 +3035,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
/* select Rx antennas */
|
||||
scan->flags |= iwl3945_get_antenna_flags(priv);
|
||||
|
||||
scan->channel_count =
|
||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
||||
if (priv->is_internal_short_scan) {
|
||||
scan->channel_count =
|
||||
iwl3945_get_single_channel_for_scan(priv, vif, band,
|
||||
(void *)&scan->data[le16_to_cpu(
|
||||
scan->tx_cmd.len)]);
|
||||
} else {
|
||||
scan->channel_count =
|
||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
||||
}
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
|
||||
|
@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
||||
{USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
|
||||
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
|
||||
{USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
|
||||
{USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */
|
||||
{USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
|
||||
{USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
|
||||
{}
|
||||
|
@ -259,6 +259,7 @@ disable:
|
||||
sdio_disable_func(func);
|
||||
release:
|
||||
sdio_release_host(func);
|
||||
wl1251_free_hw(wl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
if (local->ops->conf_tx)
|
||||
if (local->ops->get_survey)
|
||||
ret = local->ops->get_survey(&local->hw, idx, survey);
|
||||
/* trace_drv_get_survey(local, idx, survey, ret); */
|
||||
return ret;
|
||||
|
@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
|
||||
break;
|
||||
case IEEE80211_STYPE_ACTION:
|
||||
if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
|
||||
break;
|
||||
switch (mgmt->u.action.category) {
|
||||
case WLAN_CATEGORY_BACK: {
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int len = skb->len;
|
||||
struct sta_info *sta;
|
||||
|
||||
ieee80211_sta_process_chanswitch(sdata,
|
||||
&mgmt->u.action.u.chan_switch.sw_elem,
|
||||
(void *)ifmgd->associated->priv,
|
||||
rx_status->mactime);
|
||||
break;
|
||||
rcu_read_lock();
|
||||
sta = sta_info_get(sdata, mgmt->sa);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
|
||||
switch (mgmt->u.action.u.addba_req.action_code) {
|
||||
case WLAN_ACTION_ADDBA_REQ:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.addba_req)))
|
||||
break;
|
||||
ieee80211_process_addba_request(local, sta, mgmt, len);
|
||||
break;
|
||||
case WLAN_ACTION_ADDBA_RESP:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.addba_resp)))
|
||||
break;
|
||||
ieee80211_process_addba_resp(local, sta, mgmt, len);
|
||||
break;
|
||||
case WLAN_ACTION_DELBA:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.delba)))
|
||||
break;
|
||||
ieee80211_process_delba(sdata, sta, mgmt, len);
|
||||
break;
|
||||
}
|
||||
local_bh_enable();
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
case WLAN_CATEGORY_SPECTRUM_MGMT:
|
||||
ieee80211_sta_process_chanswitch(sdata,
|
||||
&mgmt->u.action.u.chan_switch.sw_elem,
|
||||
(void *)ifmgd->associated->priv,
|
||||
rx_status->mactime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
@ -1722,9 +1760,45 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
|
||||
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
|
||||
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
|
||||
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_work *wk;
|
||||
|
||||
mutex_lock(&local->work_mtx);
|
||||
list_for_each_entry(wk, &local->work_list, list) {
|
||||
if (wk->sdata != sdata)
|
||||
continue;
|
||||
|
||||
if (wk->type != IEEE80211_WORK_ASSOC)
|
||||
continue;
|
||||
|
||||
if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
|
||||
continue;
|
||||
if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Printing the message only here means we can't
|
||||
* spuriously print it, but it also means that it
|
||||
* won't be printed when the frame comes in before
|
||||
* we even tried to associate or in similar cases.
|
||||
*
|
||||
* Ultimately, I suspect cfg80211 should print the
|
||||
* messages instead.
|
||||
*/
|
||||
printk(KERN_DEBUG
|
||||
"%s: deauthenticated from %pM (Reason: %u)\n",
|
||||
sdata->name, mgmt->bssid,
|
||||
le16_to_cpu(mgmt->u.deauth.reason_code));
|
||||
|
||||
list_del_rcu(&wk->list);
|
||||
free_work(wk);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&local->work_mtx);
|
||||
|
||||
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
|
||||
}
|
||||
out:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
@ -1944,6 +1944,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
|
||||
break;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
return ieee80211_sta_rx_mgmt(sdata, rx->skb);
|
||||
|
||||
switch (mgmt->u.action.u.addba_req.action_code) {
|
||||
case WLAN_ACTION_ADDBA_REQ:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
|
Loading…
Reference in New Issue
Block a user