mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
This commit is contained in:
commit
f18b95c3e2
24 changed files with 289 additions and 171 deletions
|
@ -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) {
|
||||
tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
|
||||
divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
|
||||
} else
|
||||
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 = ((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);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,6 @@
|
|||
#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 */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue