Commit 9d88477c authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-core.h
parents 11b7c609 35dd0509
...@@ -2966,7 +2966,6 @@ F: drivers/net/ixgb/ ...@@ -2966,7 +2966,6 @@ F: drivers/net/ixgb/
F: drivers/net/ixgbe/ F: drivers/net/ixgbe/
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
M: Zhu Yi <yi.zhu@intel.com>
M: Reinette Chatre <reinette.chatre@intel.com> M: Reinette Chatre <reinette.chatre@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com> M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
...@@ -2976,7 +2975,6 @@ F: Documentation/networking/README.ipw2100 ...@@ -2976,7 +2975,6 @@ F: Documentation/networking/README.ipw2100
F: drivers/net/wireless/ipw2x00/ipw2100.* F: drivers/net/wireless/ipw2x00/ipw2100.*
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
M: Zhu Yi <yi.zhu@intel.com>
M: Reinette Chatre <reinette.chatre@intel.com> M: Reinette Chatre <reinette.chatre@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com> M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
...@@ -3007,8 +3005,8 @@ F: drivers/net/wimax/i2400m/ ...@@ -3007,8 +3005,8 @@ F: drivers/net/wimax/i2400m/
F: include/linux/wimax/i2400m.h F: include/linux/wimax/i2400m.h
INTEL WIRELESS WIFI LINK (iwlwifi) INTEL WIRELESS WIFI LINK (iwlwifi)
M: Zhu Yi <yi.zhu@intel.com>
M: Reinette Chatre <reinette.chatre@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> M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
W: http://intellinuxwireless.org W: http://intellinuxwireless.org
...@@ -3018,7 +3016,6 @@ F: drivers/net/wireless/iwlwifi/ ...@@ -3018,7 +3016,6 @@ F: drivers/net/wireless/iwlwifi/
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi) INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
M: Samuel Ortiz <samuel.ortiz@intel.com> M: Samuel Ortiz <samuel.ortiz@intel.com>
M: Zhu Yi <yi.zhu@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com> M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
S: Supported S: Supported
......
...@@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = { ...@@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
static int __devinit ath5k_pci_probe(struct pci_dev *pdev, static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id); const struct pci_device_id *id);
static void __devexit ath5k_pci_remove(struct pci_dev *pdev); 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_suspend(struct device *dev);
static int ath5k_pci_resume(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); ...@@ -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) #define ATH5K_PM_OPS (&ath5k_pm_ops)
#else #else
#define ATH5K_PM_OPS NULL #define ATH5K_PM_OPS NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM_SLEEP */
static struct pci_driver ath5k_pci_driver = { static struct pci_driver ath5k_pci_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
...@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); ...@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq); struct ath5k_txq *txq);
static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw); static int ath5k_start(struct ieee80211_hw *hw);
static void ath5k_stop(struct ieee80211_hw *hw); static void ath5k_stop(struct ieee80211_hw *hw);
static int ath5k_add_interface(struct ieee80211_hw *hw, static int ath5k_add_interface(struct ieee80211_hw *hw,
...@@ -708,7 +707,7 @@ ath5k_pci_remove(struct pci_dev *pdev) ...@@ -708,7 +707,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
ieee80211_free_hw(sc->hw); ieee80211_free_hw(sc->hw);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int ath5k_pci_suspend(struct device *dev) static int ath5k_pci_suspend(struct device *dev)
{ {
struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
...@@ -732,7 +731,7 @@ static int ath5k_pci_resume(struct device *dev) ...@@ -732,7 +731,7 @@ static int ath5k_pci_resume(struct device *dev)
ath5k_led_enable(sc); ath5k_led_enable(sc);
return 0; return 0;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM_SLEEP */
/***********************\ /***********************\
...@@ -2770,7 +2769,7 @@ ath5k_tasklet_reset(unsigned long data) ...@@ -2770,7 +2769,7 @@ ath5k_tasklet_reset(unsigned long data)
{ {
struct ath5k_softc *sc = (void *)data; struct ath5k_softc *sc = (void *)data;
ath5k_reset_wake(sc); ath5k_reset(sc, sc->curchan);
} }
/* /*
...@@ -2949,20 +2948,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ...@@ -2949,20 +2948,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ath5k_beacon_config(sc); ath5k_beacon_config(sc);
/* intrs are enabled by ath5k_beacon_config */ /* intrs are enabled by ath5k_beacon_config */
return 0;
err:
return ret;
}
static int
ath5k_reset_wake(struct ath5k_softc *sc)
{
int ret;
ret = ath5k_reset(sc, sc->curchan);
if (!ret)
ieee80211_wake_queues(sc->hw); ieee80211_wake_queues(sc->hw);
return 0;
err:
return ret; return ret;
} }
...@@ -3159,13 +3148,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, ...@@ -3159,13 +3148,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
if (*new_flags & FIF_PROMISC_IN_BSS) { if (*new_flags & FIF_PROMISC_IN_BSS) {
rfilt |= AR5K_RX_FILTER_PROM;
__set_bit(ATH_STAT_PROMISC, sc->status); __set_bit(ATH_STAT_PROMISC, sc->status);
} else { } else {
__clear_bit(ATH_STAT_PROMISC, sc->status); __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 */ /* Note, AR5K_RX_FILTER_MCAST is already enabled */
if (*new_flags & FIF_ALLMULTI) { if (*new_flags & FIF_ALLMULTI) {
mfilt[0] = ~0; mfilt[0] = ~0;
......
...@@ -1793,6 +1793,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) ...@@ -1793,6 +1793,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
u8 def_ant, tx_ant, ee_mode; u8 def_ant, tx_ant, ee_mode;
u32 sta_id1 = 0; 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; def_ant = ah->ah_def_ant;
switch (channel->hw_value & CHANNEL_MODES) { switch (channel->hw_value & CHANNEL_MODES) {
......
...@@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) ...@@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
int events = 0; int events = 0;
u16 ev; 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); iface = netdev_priv(dev);
local = iface->local; local = iface->local;
......
...@@ -2699,6 +2699,7 @@ static struct iwl_lib_ops iwl3945_lib = { ...@@ -2699,6 +2699,7 @@ static struct iwl_lib_ops iwl3945_lib = {
.isr = iwl_isr_legacy, .isr = iwl_isr_legacy,
.config_ap = iwl3945_config_ap, .config_ap = iwl3945_config_ap,
.manage_ibss_station = iwl3945_manage_ibss_station, .manage_ibss_station = iwl3945_manage_ibss_station,
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl3945_good_plcp_health, .check_plcp_health = iwl3945_good_plcp_health,
.debugfs_ops = { .debugfs_ops = {
......
...@@ -1030,10 +1030,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, ...@@ -1030,10 +1030,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
struct iwl_scan_channel *scan_ch) struct iwl_scan_channel *scan_ch)
{ {
const struct ieee80211_supported_band *sband; const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0; u16 passive_dwell = 0;
u16 active_dwell = 0; u16 active_dwell = 0;
int i, added = 0; int added = 0;
u16 channel = 0; u16 channel = 0;
sband = iwl_get_hw_mode(priv, band); sband = iwl_get_hw_mode(priv, band);
...@@ -1048,32 +1047,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, ...@@ -1048,32 +1047,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
if (passive_dwell <= active_dwell) if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1; passive_dwell = active_dwell + 1;
/* only scan single channel, good enough to reset the RF */ channel = iwl_get_single_channel_number(priv, band);
/* 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;
}
}
}
if (channel) { if (channel) {
scan_ch->channel = cpu_to_le16(channel); scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
......
...@@ -1497,6 +1497,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv, ...@@ -1497,6 +1497,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 * uCode download functions
...@@ -2037,6 +2187,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ...@@ -2037,6 +2187,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
if (err) if (err)
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", 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 */ /* We have our copies now, allow OS release its copies */
release_firmware(ucode_raw); release_firmware(ucode_raw);
complete(&priv->_agn.firmware_loading_complete); complete(&priv->_agn.firmware_loading_complete);
...@@ -3425,141 +3582,6 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, ...@@ -3425,141 +3582,6 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
/*****************************************************************************
*
* 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 * driver setup and teardown
...@@ -3713,21 +3735,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) ...@@ -3713,21 +3735,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
kfree(priv->scan_cmd); 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 = { static struct ieee80211_ops iwl_hw_ops = {
.tx = iwl_mac_tx, .tx = iwl_mac_tx,
.start = iwl_mac_start, .start = iwl_mac_start,
...@@ -3912,11 +3919,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3912,11 +3919,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); IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
goto out_disable_msi; 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_deferred_work(priv);
iwl_setup_rx_handlers(priv); iwl_setup_rx_handlers(priv);
...@@ -3950,15 +3952,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3950,15 +3952,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = iwl_request_firmware(priv, true); err = iwl_request_firmware(priv, true);
if (err) if (err)
goto out_remove_sysfs; goto out_destroy_workqueue;
return 0; return 0;
out_remove_sysfs: out_destroy_workqueue:
destroy_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue);
priv->workqueue = NULL; priv->workqueue = NULL;
sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
out_free_irq:
free_irq(priv->pci_dev->irq, priv); free_irq(priv->pci_dev->irq, priv);
iwl_free_isr_ict(priv); iwl_free_isr_ict(priv);
out_disable_msi: out_disable_msi:
......
...@@ -855,6 +855,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) ...@@ -855,6 +855,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
} }
EXPORT_SYMBOL(iwl_set_rxon_chain); 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 * 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 * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
......
...@@ -350,6 +350,8 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); ...@@ -350,6 +350,8 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
void iwl_set_flags_for_band(struct iwl_priv *priv, void iwl_set_flags_for_band(struct iwl_priv *priv,
enum ieee80211_band band, enum ieee80211_band band,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
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); 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, u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *sta_ht_inf); struct ieee80211_sta_ht_cap *sta_ht_inf);
......
...@@ -1782,6 +1782,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) ...@@ -1782,6 +1782,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
#endif #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, static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band, enum ieee80211_band band,
u8 is_active, u8 n_probes, u8 is_active, u8 n_probes,
...@@ -2932,9 +2975,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -2932,9 +2975,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
/* select Rx antennas */ /* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv); scan->flags |= iwl3945_get_antenna_flags(priv);
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 = scan->channel_count =
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
}
if (scan->channel_count == 0) { if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
......
...@@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { ...@@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
{USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ {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, 0x8102)}, /* Spinnaker DUT */
{USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
{} {}
......
...@@ -259,6 +259,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, ...@@ -259,6 +259,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
sdio_disable_func(func); sdio_disable_func(func);
release: release:
sdio_release_host(func); sdio_release_host(func);
wl1251_free_hw(wl);
return ret; return ret;
} }
......
...@@ -332,14 +332,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) ...@@ -332,14 +332,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
IEEE80211_QUEUE_STOP_REASON_AGGREGATION); IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
spin_unlock(&local->ampdu_lock); spin_unlock(&local->ampdu_lock);
spin_unlock_bh(&sta->lock);
/* send an addBA request */ /* prepare tid data */
sta->ampdu_mlme.dialog_token_allocator++; sta->ampdu_mlme.dialog_token_allocator++;
sta->ampdu_mlme.tid_tx[tid]->dialog_token = sta->ampdu_mlme.tid_tx[tid]->dialog_token =
sta->ampdu_mlme.dialog_token_allocator; sta->ampdu_mlme.dialog_token_allocator;
sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
spin_unlock_bh(&sta->lock);
/* send AddBA request */
ieee80211_send_addba_request(sdata, pubsta->addr, tid, ieee80211_send_addba_request(sdata, pubsta->addr, tid,
sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->dialog_token,
sta->ampdu_mlme.tid_tx[tid]->ssn, sta->ampdu_mlme.tid_tx[tid]->ssn,
......
...@@ -360,7 +360,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx, ...@@ -360,7 +360,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
struct survey_info *survey) struct survey_info *survey)
{ {
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
if (local->ops->conf_tx) if (local->ops->get_survey)
ret = local->ops->get_survey(&local->hw, idx, survey); ret = local->ops->get_survey(&local->hw, idx, survey);
/* trace_drv_get_survey(local, idx, survey, ret); */ /* trace_drv_get_survey(local, idx, survey, ret); */
return ret; return ret;
......
...@@ -1692,15 +1692,53 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -1692,15 +1692,53 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
break; break;
case IEEE80211_STYPE_ACTION: case IEEE80211_STYPE_ACTION:
if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) switch (mgmt->u.action.category) {
case WLAN_CATEGORY_BACK: {
struct ieee80211_local *local = sdata->local;
int len = skb->len;
struct sta_info *sta;
rcu_read_lock();
sta = sta_info_get(sdata, mgmt->sa);
if (!sta) {
rcu_read_unlock();
break; 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, ieee80211_sta_process_chanswitch(sdata,
&mgmt->u.action.u.chan_switch.sw_elem, &mgmt->u.action.u.chan_switch.sw_elem,
(void *)ifmgd->associated->priv, (void *)ifmgd->associated->priv,
rx_status->mactime); rx_status->mactime);
break; break;
} }
}
mutex_unlock(&ifmgd->mtx); mutex_unlock(&ifmgd->mtx);
switch (rma) { switch (rma) {
......
...@@ -1819,17 +1819,26 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) ...@@ -1819,17 +1819,26 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
return RX_CONTINUE; return RX_CONTINUE;
if (ieee80211_is_back_req(bar->frame_control)) { if (ieee80211_is_back_req(bar->frame_control)) {
struct {
__le16 control, start_seq_num;
} __packed bar_data;
if (!rx->sta) if (!rx->sta)
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
&bar_data, sizeof(bar_data)))
return RX_DROP_MONITOR;
spin_lock(&rx->sta->lock); spin_lock(&rx->sta->lock);
tid = le16_to_cpu(bar->control) >> 12; tid = le16_to_cpu(bar_data.control) >> 12;
if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
spin_unlock(&rx->sta->lock); spin_unlock(&rx->sta->lock);
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
} }
tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
/* reset session timer */ /* reset session timer */
if (tid_agg_rx->timeout) if (tid_agg_rx->timeout)
...@@ -1941,6 +1950,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ...@@ -1941,6 +1950,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (len < IEEE80211_MIN_ACTION_SIZE + 1) if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break; 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) { switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ: case WLAN_ACTION_ADDBA_REQ:
if (len < (IEEE80211_MIN_ACTION_SIZE + if (len < (IEEE80211_MIN_ACTION_SIZE +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment