Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (21 commits) mac80211: fix deauth before assoc iwlwifi: add missing rcu_read_lock mac80211: fix function pointer check wireless: remove my name from the maintainer list ath5k: fix NULL pointer in antenna configuration p54usb: Add device ID for Dell WLA3310 USB wl1251: fix a memory leak in probe ipmr: dont corrupt lists 8139too: fix buffer overrun in rtl8139_init_board asix: check packet size against mtu+ETH_HLEN instead of ETH_FRAME_LEN r8169: fix random mdio_write failures ip6mr: fix a typo in ip6mr_for_each_table() iwlwifi: move sysfs_create_group to post request firmware iwlwifi: add name to Maintainers list iwl3945: fix internal scan iwl3945: enable stuck queue detection on 3945 ipv6: avoid high order allocations ath5k: retain promiscuous setting ath5k: depend on CONFIG_PM_SLEEP for suspend/resume functions mac80211: process station blockack action frames from work ...
This commit is contained in:
Коммит
63a07cb64c
|
@ -2978,7 +2978,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
|
||||||
|
@ -2988,7 +2987,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
|
||||||
|
@ -3019,8 +3017,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
|
||||||
|
@ -3030,7 +3028,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
|
||||||
|
|
|
@ -860,6 +860,7 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
|
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
|
||||||
|
i = 0;
|
||||||
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
|
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
|
||||||
dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
|
dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
|
||||||
tp->chipset = 0;
|
tp->chipset = 0;
|
||||||
|
|
|
@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
|
||||||
break;
|
break;
|
||||||
udelay(25);
|
udelay(25);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Some configurations require a small delay even after the write
|
||||||
|
* completed indication or the next write might fail.
|
||||||
|
*/
|
||||||
|
udelay(25);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdio_read(void __iomem *ioaddr, int reg_addr)
|
static int mdio_read(void __iomem *ioaddr, int reg_addr)
|
||||||
|
|
|
@ -344,7 +344,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > ETH_FRAME_LEN) {
|
if (size > dev->net->mtu + ETH_HLEN) {
|
||||||
netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
|
netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
|
||||||
size);
|
size);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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);
|
||||||
#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,
|
||||||
|
@ -708,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||||
ieee80211_free_hw(hw);
|
ieee80211_free_hw(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 ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(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);
|
ath5k_led_enable(sc);
|
||||||
return 0;
|
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 (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;
|
||||||
|
|
|
@ -1814,6 +1814,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;
|
||||||
|
|
||||||
ATH5K_TRACE(ah->ah_sc);
|
ATH5K_TRACE(ah->ah_sc);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -2852,6 +2852,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 = {
|
||||||
|
|
|
@ -1119,10 +1119,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);
|
||||||
|
@ -1137,32 +1136,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;
|
||||||
|
|
|
@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct iwl_station_priv *sta_priv;
|
struct iwl_station_priv *sta_priv;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
|
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
|
||||||
if (sta) {
|
if (sta) {
|
||||||
sta_priv = (void *)sta->drv_priv;
|
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)
|
atomic_dec_return(&sta_priv->pending_frames) == 0)
|
||||||
ieee80211_sta_block_awake(priv->hw, sta, false);
|
ieee80211_sta_block_awake(priv->hw, sta, false);
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
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
|
* uCode download functions
|
||||||
|
@ -1965,6 +2115,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);
|
||||||
|
@ -3262,141 +3419,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||||
return 0;
|
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
|
* driver setup and teardown
|
||||||
|
@ -3550,21 +3572,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,
|
||||||
|
@ -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);
|
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);
|
||||||
|
@ -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);
|
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:
|
||||||
|
|
|
@ -854,6 +854,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
|
||||||
|
|
|
@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
||||||
int iwl_full_rxon_required(struct iwl_priv *priv);
|
int iwl_full_rxon_required(struct iwl_priv *priv);
|
||||||
void iwl_set_rxon_chain(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);
|
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);
|
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);
|
||||||
|
|
|
@ -1844,6 +1844,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,
|
||||||
|
@ -2992,9 +3035,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);
|
||||||
|
|
||||||
scan->channel_count =
|
if (priv->is_internal_short_scan) {
|
||||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
scan->channel_count =
|
||||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
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) {
|
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 = {
|
||||||
{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 @@ disable:
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,8 +267,10 @@ static void __net_exit ipmr_rules_exit(struct net *net)
|
||||||
{
|
{
|
||||||
struct mr_table *mrt, *next;
|
struct mr_table *mrt, *next;
|
||||||
|
|
||||||
list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list)
|
list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
|
||||||
|
list_del(&mrt->list);
|
||||||
kfree(mrt);
|
kfree(mrt);
|
||||||
|
}
|
||||||
fib_rules_unregister(net->ipv4.mr_rules_ops);
|
fib_rules_unregister(net->ipv4.mr_rules_ops);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
|
||||||
static void ipmr_expire_process(unsigned long arg);
|
static void ipmr_expire_process(unsigned long arg);
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
||||||
#define ip6mr_for_each_table(mrt, met) \
|
#define ip6mr_for_each_table(mrt, net) \
|
||||||
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
|
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
|
||||||
|
|
||||||
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
|
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
|
||||||
|
@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
|
||||||
{
|
{
|
||||||
struct mr6_table *mrt, *next;
|
struct mr6_table *mrt, *next;
|
||||||
|
|
||||||
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
|
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
|
||||||
|
list_del(&mrt->list);
|
||||||
ip6mr_free_table(mrt);
|
ip6mr_free_table(mrt);
|
||||||
|
}
|
||||||
fib_rules_unregister(net->ipv6.mr6_rules_ops);
|
fib_rules_unregister(net->ipv6.mr6_rules_ops);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1356,7 +1356,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
|
||||||
IPV6_TLV_PADN, 0 };
|
IPV6_TLV_PADN, 0 };
|
||||||
|
|
||||||
/* we assume size > sizeof(ra) here */
|
/* we assume size > sizeof(ra) here */
|
||||||
skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
|
size += LL_ALLOCATED_SPACE(dev);
|
||||||
|
/* limit our allocations to order-0 page */
|
||||||
|
size = min_t(int, size, SKB_MAX_ORDER(0, 0));
|
||||||
|
skb = sock_alloc_send_skb(sk, size, 1, &err);
|
||||||
|
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -349,7 +349,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,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);
|
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) {
|
||||||
break;
|
case WLAN_CATEGORY_BACK: {
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
int len = skb->len;
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
ieee80211_sta_process_chanswitch(sdata,
|
rcu_read_lock();
|
||||||
&mgmt->u.action.u.chan_switch.sw_elem,
|
sta = sta_info_get(sdata, mgmt->sa);
|
||||||
(void *)ifmgd->associated->priv,
|
if (!sta) {
|
||||||
rx_status->mactime);
|
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,
|
||||||
|
&mgmt->u.action.u.chan_switch.sw_elem,
|
||||||
|
(void *)ifmgd->associated->priv,
|
||||||
|
rx_status->mactime);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&ifmgd->mtx);
|
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);
|
mutex_unlock(&ifmgd->mtx);
|
||||||
|
|
||||||
if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
|
if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
|
||||||
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
|
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
|
||||||
cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
|
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:
|
out:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1944,6 +1944,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 +
|
||||||
|
|
Загрузка…
Ссылка в новой задаче