Commit f18b95c3 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'upstream-fixes' of...

Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
parents 17c281ab 848ef855
......@@ -6,7 +6,7 @@ menu "Wireless LAN (non-hamradio)"
depends on NETDEVICES
config NET_RADIO
bool "Wireless LAN drivers (non-hamradio)"
bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
select WIRELESS_EXT
---help---
Support for wireless LANs and everything having to do with radio,
......
......@@ -3139,6 +3139,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
if ( status & EV_LINK ) {
union iwreq_data wrqu;
int scan_forceloss = 0;
/* The link status has changed, if you want to put a
monitor hook in, do it here. (Remember that
interrupts are still disabled!)
......@@ -3157,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
code) */
#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
code) */
#define ASSOCIATED 0x0400 /* Assocatied */
#define ASSOCIATED 0x0400 /* Associated */
#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
#define RC_RESERVED 0 /* Reserved return code */
#define RC_NOREASON 1 /* Unspecified reason */
#define RC_AUTHINV 2 /* Previous authentication invalid */
......@@ -3174,44 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
leaving BSS */
#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
Authenticated with the responding station */
if (newStatus != ASSOCIATED) {
if (auto_wep && !apriv->expires) {
apriv->expires = RUN_AT(3*HZ);
wake_up_interruptible(&apriv->thr_wait);
}
} else {
struct task_struct *task = apriv->task;
if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
scan_forceloss = 1;
if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
if (auto_wep)
apriv->expires = 0;
if (task)
wake_up_process (task);
if (apriv->task)
wake_up_process (apriv->task);
set_bit(FLAG_UPDATE_UNI, &apriv->flags);
set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
}
/* Question : is ASSOCIATED the only status
* that is valid ? We want to catch handover
* and reassociations as valid status
* Jean II */
if(newStatus == ASSOCIATED) {
#if 0
/* FIXME: Grabbing scan results here
* seems to be too early??? Just wait for
* timeout instead. */
if (apriv->scan_timeout > 0) {
set_bit(JOB_SCAN_RESULTS, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
}
#endif
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
airo_send_event(dev);
} else {
memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
} else if (!scan_forceloss) {
if (auto_wep && !apriv->expires) {
apriv->expires = RUN_AT(3*HZ);
wake_up_interruptible(&apriv->thr_wait);
}
/* Send event to user space */
memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
}
}
......@@ -7136,10 +7124,10 @@ static int airo_set_scan(struct net_device *dev,
goto out;
/* Initiate a scan command */
ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS;
issuecommand(ai, &cmd, &rsp);
ai->scan_timeout = RUN_AT(3*HZ);
wake = 1;
out:
......
......@@ -3463,6 +3463,7 @@ static void atmel_command_irq(struct atmel_private *priv)
u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
int fast_scan;
union iwreq_data wrqu;
if (status == CMD_STATUS_IDLE ||
status == CMD_STATUS_IN_PROGRESS)
......@@ -3487,6 +3488,7 @@ static void atmel_command_irq(struct atmel_private *priv)
atmel_scan(priv, 1);
} else {
int bss_index = retrieve_bss(priv);
int notify_scan_complete = 1;
if (bss_index != -1) {
atmel_join_bss(priv, bss_index);
} else if (priv->operating_mode == IW_MODE_ADHOC &&
......@@ -3495,8 +3497,14 @@ static void atmel_command_irq(struct atmel_private *priv)
} else {
priv->fast_scan = !fast_scan;
atmel_scan(priv, 1);
notify_scan_complete = 0;
}
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (notify_scan_complete) {
wrqu.data.length = 0;
wrqu.data.flags = 0;
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
}
}
break;
......@@ -3509,6 +3517,9 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (priv->station_is_associated) {
atmel_enter_state(priv, STATION_STATE_READY);
wrqu.data.length = 0;
wrqu.data.flags = 0;
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
} else {
atmel_scan(priv, 1);
}
......
......@@ -17,8 +17,11 @@ config BCM43XX_DEBUG
config BCM43XX_DMA
bool
depends on BCM43XX
config BCM43XX_PIO
bool
depends on BCM43XX
choice
prompt "BCM43xx data transfer mode"
......
......@@ -15,7 +15,6 @@
#include "bcm43xx_debugfs.h"
#include "bcm43xx_leds.h"
#include "bcm43xx_sysfs.h"
#define PFX KBUILD_MODNAME ": "
......@@ -638,8 +637,6 @@ struct bcm43xx_key {
};
struct bcm43xx_private {
struct bcm43xx_sysfs sysfs;
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
......@@ -772,6 +769,20 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
return ieee80211softmac_priv(dev);
}
struct device;
static inline
struct bcm43xx_private * dev_to_bcm(struct device *dev)
{
struct net_device *net_dev;
struct bcm43xx_private *bcm;
net_dev = dev_get_drvdata(dev);
bcm = bcm43xx_priv(net_dev);
return bcm;
}
/* Helper function, which returns a boolean.
* TRUE, if PIO is used; FALSE, if DMA is used.
......
......@@ -452,12 +452,12 @@ void bcm43xx_printk_dump(const char *data,
size_t i;
char c;
printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
description, size);
for (i = 0; i < size; i++) {
c = data[i];
if (i % 8 == 0)
printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff);
printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
else
printk("0x%02x, ", c & 0xff);
}
......@@ -472,12 +472,12 @@ void bcm43xx_printk_bitdump(const unsigned char *data,
int j;
const unsigned char *d;
printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
for (i = 0; i < bytes; i++) {
d = data + i;
if (i % 8 == 0)
printk("\n" KERN_INFO PFX "0x%08x: ", i);
printk("\n" KERN_INFO PFX "0x%08zx: ", i);
if (msb_to_lsb) {
for (j = 7; j >= 0; j--) {
if (*d & (1 << j))
......
......@@ -196,8 +196,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
}
if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G "
"(0x%08x, len: %lu)\n",
ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
"(0x%llx, len: %lu)\n",
(unsigned long long)ring->dmabase,
BCM43xx_DMA_RINGMEMSIZE);
dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
ring->vbase, ring->dmabase);
return -ENOMEM;
......@@ -307,8 +308,8 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
dev_kfree_skb_any(skb);
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G "
"(0x%08x, len: %u)\n",
dmaaddr, ring->rx_buffersize);
"(0x%llx, len: %u)\n",
(unsigned long long)dmaaddr, ring->rx_buffersize);
return -ENOMEM;
}
meta->skb = skb;
......@@ -729,8 +730,8 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
return_slot(ring, slot);
printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G "
"(0x%08x, len: %u)\n",
meta->dmaaddr, skb->len);
"(0x%llx, len: %u)\n",
(unsigned long long)meta->dmaaddr, skb->len);
return -ENOMEM;
}
......
......@@ -52,6 +52,7 @@
#include "bcm43xx_wx.h"
#include "bcm43xx_ethtool.h"
#include "bcm43xx_xmit.h"
#include "bcm43xx_sysfs.h"
MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
......@@ -3522,6 +3523,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
err = bcm43xx_pio_tx(bcm, txb);
else
err = bcm43xx_dma_tx(bcm, txb);
bcm->net_dev->trans_start = jiffies;
return err;
}
......
......@@ -2151,6 +2151,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
phy->tssi2dbm = NULL;
printk(KERN_ERR PFX "Could not generate "
"tssi2dBm table\n");
kfree(dyn_tssi2dbm);
return -ENODEV;
}
phy->tssi2dbm = dyn_tssi2dbm;
......
......@@ -35,77 +35,101 @@
#include "bcm43xx_main.h"
/* Get the Slow Clock Source */
static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
{
u32 tmp;
int err;
assert(bcm->current_core == &bcm->core_chipcommon);
if (bcm->current_core->rev < 6) {
if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
bcm->bustype == BCM43xx_BUSTYPE_SB)
return BCM43xx_PCTL_CLKSRC_XTALOS;
if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
assert(!err);
if (tmp & 0x10)
return BCM43xx_PCTL_CLKSRC_PCI;
return BCM43xx_PCTL_CLKSRC_XTALOS;
}
}
if (bcm->current_core->rev < 10) {
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
tmp &= 0x7;
if (tmp == 0)
return BCM43xx_PCTL_CLKSRC_LOPWROS;
if (tmp == 1)
return BCM43xx_PCTL_CLKSRC_XTALOS;
if (tmp == 2)
return BCM43xx_PCTL_CLKSRC_PCI;
}
return BCM43xx_PCTL_CLKSRC_XTALOS;
}
/* Get max/min slowclock frequency
* as described in http://bcm-specs.sipsolutions.net/PowerControl
*/
static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
int get_max)
{
int limit = 0;
int limit;
int clocksrc;
int divisor;
int selection;
int err;
u32 tmp;
struct bcm43xx_coreinfo *old_core;
if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
goto out;
old_core = bcm->current_core;
err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
if (err)
goto out;
assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
assert(bcm->current_core == &bcm->core_chipcommon);
clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
if (bcm->current_core->rev < 6) {
if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
(bcm->bustype == BCM43xx_BUSTYPE_SB)) {
selection = 1;
divisor = 32;
} else {
err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
if (err) {
printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
goto out_switchback;
}
if (tmp & 0x10) {
/* PCI */
selection = 2;
switch (clocksrc) {
case BCM43xx_PCTL_CLKSRC_PCI:
divisor = 64;
} else {
/* XTAL */
selection = 1;
break;
case BCM43xx_PCTL_CLKSRC_XTALOS:
divisor = 32;
}
break;
default:
assert(0);
divisor = 1;
}
} else if (bcm->current_core->rev < 10) {
selection = (tmp & 0x07);
if (selection) {
switch (clocksrc) {
case BCM43xx_PCTL_CLKSRC_LOPWROS:
divisor = 1;
break;
case BCM43xx_PCTL_CLKSRC_XTALOS:
case BCM43xx_PCTL_CLKSRC_PCI:
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
} else
divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
divisor *= 4;
break;
default:
assert(0);
divisor = 1;
}
} else {
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
selection = 1;
divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
divisor *= 4;
}
switch (selection) {
case 0:
/* LPO */
switch (clocksrc) {
case BCM43xx_PCTL_CLKSRC_LOPWROS:
if (get_max)
limit = 43000;
else
limit = 25000;
break;
case 1:
/* XTAL */
case BCM43xx_PCTL_CLKSRC_XTALOS:
if (get_max)
limit = 20200000;
else
limit = 19800000;
break;
case 2:
/* PCI */
case BCM43xx_PCTL_CLKSRC_PCI:
if (get_max)
limit = 34000000;
else
......@@ -113,17 +137,14 @@ static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
break;
default:
assert(0);
limit = 0;
}
limit /= divisor;
out_switchback:
err = bcm43xx_switch_core(bcm, old_core);
assert(err == 0);
out:
return limit;
}
/* init power control
* as described in http://bcm-specs.sipsolutions.net/PowerControl
*/
......
......@@ -33,6 +33,15 @@
#include <linux/types.h>
/* Clock sources */
enum {
/* PCI clock */
BCM43xx_PCTL_CLKSRC_PCI,
/* Crystal slow clock oscillator */
BCM43xx_PCTL_CLKSRC_XTALOS,
/* Low power oscillator */
BCM43xx_PCTL_CLKSRC_LOPWROS,
};
struct bcm43xx_private;
......
......@@ -71,14 +71,46 @@ static int get_boolean(const char *buf, size_t count)
return -EINVAL;
}
static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
{
int i, pos = 0;
for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
pos += snprintf(buf + pos, buf_len - pos - 1,
"%04X", swab16(sprom[i]) & 0xFFFF);
}
pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
return pos + 1;
}
static int hex2sprom(u16 *sprom, const char *dump, size_t len)
{
char tmp[5] = { 0 };
int cnt = 0;
unsigned long parsed;
if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
return -EINVAL;
while (cnt < BCM43xx_SPROM_SIZE) {
memcpy(tmp, dump, 4);
dump += 4;
parsed = simple_strtoul(tmp, NULL, 16);
sprom[cnt++] = swab16((u16)parsed);
}
return 0;
}
static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
u16 *sprom;
unsigned long flags;
int i, err;
int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
......@@ -91,55 +123,53 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
bcm43xx_lock_mmio(bcm, flags);
assert(bcm->initialized);
err = bcm43xx_sprom_read(bcm, sprom);
if (!err) {
for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
buf[i * 2] = sprom[i] & 0x00FF;
buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
}
}
if (!err)
err = sprom2hex(sprom, buf, PAGE_SIZE);
bcm43xx_unlock_mmio(bcm, flags);
kfree(sprom);
return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
return err;
}
static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
u16 *sprom;
unsigned long flags;
int i, err;
int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
return -EINVAL;
sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
GFP_KERNEL);
if (!sprom)
return -ENOMEM;
for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
sprom[i] = buf[i * 2] & 0xFF;
sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
}
err = hex2sprom(sprom, buf, count);
if (err)
goto out_kfree;
bcm43xx_lock_mmio(bcm, flags);
assert(bcm->initialized);
err = bcm43xx_sprom_write(bcm, sprom);
bcm43xx_unlock_mmio(bcm, flags);
out_kfree:
kfree(sprom);
return err ? err : count;
}
static DEVICE_ATTR(sprom, 0600,
bcm43xx_attr_sprom_show,
bcm43xx_attr_sprom_store);
static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
ssize_t count = 0;
......@@ -175,7 +205,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
int mode;
......@@ -215,11 +245,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
return err ? err : count;
}
static DEVICE_ATTR(interference, 0644,
bcm43xx_attr_interfmode_show,
bcm43xx_attr_interfmode_store);
static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
ssize_t count;
......@@ -245,7 +279,7 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
struct bcm43xx_private *bcm = dev_to_bcm(dev);
unsigned long flags;
int err;
int value;
......@@ -267,56 +301,41 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
return err ? err : count;
}
static DEVICE_ATTR(shortpreamble, 0644,
bcm43xx_attr_preamble_show,
bcm43xx_attr_preamble_store);
int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
{
struct device *dev = &bcm->pci_dev->dev;
struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
int err;
assert(bcm->initialized);
sysfs->attr_sprom.attr.name = "sprom";
sysfs->attr_sprom.attr.owner = THIS_MODULE;
sysfs->attr_sprom.attr.mode = 0600;
sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
err = device_create_file(dev, &sysfs->attr_sprom);
err = device_create_file(dev, &dev_attr_sprom);
if (err)
goto out;
sysfs->attr_interfmode.attr.name = "interference";
sysfs->attr_interfmode.attr.owner = THIS_MODULE;
sysfs->attr_interfmode.attr.mode = 0600;
sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
err = device_create_file(dev, &sysfs->attr_interfmode);
err = device_create_file(dev, &dev_attr_interference);
if (err)
goto err_remove_sprom;
sysfs->attr_preamble.attr.name = "shortpreamble";
sysfs->attr_preamble.attr.owner = THIS_MODULE;
sysfs->attr_preamble.attr.mode = 0600;
sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
err = device_create_file(dev, &sysfs->attr_preamble);
err = device_create_file(dev, &dev_attr_shortpreamble);
if (err)
goto err_remove_interfmode;
out:
return err;
err_remove_interfmode:
device_remove_file(dev, &sysfs->attr_interfmode);
device_remove_file(dev, &dev_attr_interference);
err_remove_sprom:
device_remove_file(dev, &sysfs->attr_sprom);
device_remove_file(dev, &dev_attr_sprom);
goto out;
}
void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
{
struct device *dev = &bcm->pci_dev->dev;
struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
device_remove_file(dev, &sysfs->attr_preamble);
device_remove_file(dev, &sysfs->attr_interfmode);
device_remove_file(dev, &sysfs->attr_sprom);
device_remove_file(dev, &dev_attr_shortpreamble);
device_remove_file(dev, &dev_attr_interference);
device_remove_file(dev, &dev_attr_sprom);
}
#ifndef BCM43xx_SYSFS_H_
#define BCM43xx_SYSFS_H_
#include <linux/device.h>
struct bcm43xx_sysfs {
struct device_attribute attr_sprom;
struct device_attribute attr_interfmode;
struct device_attribute attr_preamble;
};
#define devattr_to_bcm(attr, attr_name) ({ \
struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \
__s = container_of((attr), struct bcm43xx_sysfs, attr_name); \
__p = container_of(__s, struct bcm43xx_private, sysfs); \
__p; \
})
struct bcm43xx_private;
int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
......
......@@ -962,22 +962,22 @@ static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
{
.cmd = PRIV_WX_SET_SHORTPREAMBLE,
.set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
.name = "set_shortpreambl",
.name = "set_shortpreamb",
},
{
.cmd = PRIV_WX_GET_SHORTPREAMBLE,
.get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
.name = "get_shortpreambl",
.name = "get_shortpreamb",
},
{
.cmd = PRIV_WX_SET_SWENCRYPTION,
.set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
.name = "set_swencryption",
.name = "set_swencrypt",
},
{
.cmd = PRIV_WX_GET_SWENCRYPTION,
.get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
.name = "get_swencryption",
.name = "get_swencrypt",
},
{
.cmd = PRIV_WX_SPROM_WRITE,
......
......@@ -390,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
}
} else {
struct {
__le16 qual, signal, noise;
__le16 qual, signal, noise, unused;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
......
......@@ -267,8 +267,9 @@ extern void ieee80211softmac_stop(struct net_device *dev);
#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8
/* keep this updated! */
#define IEEE80211SOFTMAC_EVENT_LAST 7
#define IEEE80211SOFTMAC_EVENT_LAST 8
/*
* If you want to be notified of certain events, you can call
* ieee80211softmac_notify[_atomic] with
......
......@@ -2698,7 +2698,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
/* If command is `set a parameter', or
* `get the encoding parameters', check if
* the user has the right to do it */
if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) {
if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
|| cmd == SIOCGIWENCODEEXT) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
}
......
......@@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev,
if(!IW_IS_GET(request->cmd))
return -EOPNOTSUPP;
/* If command is `get the encoding parameters', check if
* the user has the right to do it */
if (request->cmd == SIOCGIWENCODE ||
request->cmd == SIOCGIWENCODEEXT) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
}
/* Special cases */
if(request->cmd == SIOCGIWSTATS)
/* Get Wireless Stats */
......
config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL
select WIRELESS_EXT
---help---
This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack.
......
......@@ -101,6 +101,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
mac->associated = 0;
mac->associnfo.associating = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
spin_unlock_irqrestore(&mac->lock, flags);
}
......@@ -373,6 +374,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.bssvalid = 0;
mac->associated = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags);
......@@ -391,6 +393,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
return 0;
}
ieee80211softmac_assoc(mac, network);
schedule_work(&mac->associnfo.work);
return 0;
}
......@@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
"authenticating failed",
"authenticating timed out",
"associating failed because no suitable network was found",
"disassociated",
};
......@@ -128,13 +129,42 @@ void
ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
{
struct ieee80211softmac_event *eventptr, *tmp;
union iwreq_data wrqu;
char *msg;
struct ieee80211softmac_network *network;
if (event >= 0) {
union iwreq_data wrqu;
int we_event;
char *msg = NULL;
switch(event) {
case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
network = (struct ieee80211softmac_network *)event_ctx;
wrqu.data.length = 0;
wrqu.data.flags = 0;
memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
we_event = SIOCGIWAP;
break;
case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
wrqu.data.length = 0;
wrqu.data.flags = 0;
memset(&wrqu, '\0', sizeof (union iwreq_data));
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
we_event = SIOCGIWAP;
break;
case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
wrqu.data.length = 0;
wrqu.data.flags = 0;
memset(&wrqu, '\0', sizeof (union iwreq_data));
we_event = SIOCGIWSCAN;
break;
default:
msg = event_descriptions[event];
wrqu.data.length = strlen(msg);
wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
we_event = IWEVCUSTOM;
break;
}
wireless_send_event(mac->dev, we_event, &wrqu, msg);
}
if (!list_empty(&mac->events))
......
......@@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */
(*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
cpu_to_le16(WLAN_CAPABILITY_ESS) :
cpu_to_le16(WLAN_CAPABILITY_IBSS);
switch (mac->ieee->iw_mode) {
case IW_MODE_INFRA:
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
break;
case IW_MODE_ADHOC:
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
break;
case IW_MODE_AUTO:
(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
break;
default:
/* bleh. we don't ever go to these modes */
printk(KERN_ERR PFX "invalid iw_mode!\n");
break;
}
/* Need to add this
(*pkt)->capability |= mac->ieee->short_slot ?
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
......
......@@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
sm->scanning = 1;
spin_unlock_irqrestore(&sm->lock, flags);
netif_tx_disable(sm->ieee->dev);
ret = sm->start_scan(sm->dev);
if (ret) {
spin_lock_irqsave(&sm->lock, flags);
......@@ -239,6 +240,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
if (net)
sm->set_channel(sm->dev, net->channel);
}
netif_wake_queue(sm->ieee->dev);
ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
......@@ -41,13 +41,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
/* if we're still scanning, return -EAGAIN so that userspace tools
* can get the complete scan results, otherwise return 0. */
int
ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
unsigned long flags;
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
spin_lock_irqsave(&sm->lock, flags);
if (sm->scanning) {
spin_unlock_irqrestore(&sm->lock, flags);
return -EAGAIN;
}
spin_unlock_irqrestore(&sm->lock, flags);
return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
......
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