Commit 3cd73eed authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6

* 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6:
  [PATCH] bcm43xx: Fix access to non-existent PHY registers
  [PATCH] bcm43xx: Fix array overrun in bcm43xx_geo_init
  [PATCH] bcm43xx: check for valid MAC address in SPROM
  [PATCH] ieee80211: Fix A band channel count (resent)
  [PATCH] bcm43xx: fix iwmode crash when down
  [PATCH] softmac: make non-operational after being stopped
  [PATCH] softmac: don't reassociate if user asked for deauthentication
  spidernet: enable support for bcm5461 ethernet phy
  spidernet: introduce new setting
  Fix RTL8019AS init for Toshiba RBTX49xx boards
  au1000_eth.c: use ether_crc() from <linux/crc32.h>
  sky2: version 1.3
  Add more support for the Yukon Ultra chip found in dual core centino laptops.
  sky2: synchronize irq on remove
  sky2: dont write status ring
  sky2: edge triggered workaround enhancement
  sky2: use mask instead of modulo operation
  sky2: tx ring index mask fix
  sky2: status irq hang fix
  sky2: backout NAPI reschedule
parents c51e078f 23aee82e
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/crc32.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -2070,23 +2071,6 @@ static void au1000_tx_timeout(struct net_device *dev) ...@@ -2070,23 +2071,6 @@ static void au1000_tx_timeout(struct net_device *dev)
netif_wake_queue(dev); netif_wake_queue(dev);
} }
static unsigned const ethernet_polynomial = 0x04c11db7U;
static inline u32 ether_crc(int length, unsigned char *data)
{
int crc = -1;
while(--length >= 0) {
unsigned char current_octet = *data++;
int bit;
for (bit = 0; bit < 8; bit++, current_octet >>= 1)
crc = (crc << 1) ^
((crc < 0) ^ (current_octet & 1) ?
ethernet_polynomial : 0);
}
return crc;
}
static void set_rx_mode(struct net_device *dev) static void set_rx_mode(struct net_device *dev)
{ {
struct au1000_private *aup = (struct au1000_private *) dev->priv; struct au1000_private *aup = (struct au1000_private *) dev->priv;
......
...@@ -139,8 +139,9 @@ bad_clone_list[] __initdata = { ...@@ -139,8 +139,9 @@ bad_clone_list[] __initdata = {
#if defined(CONFIG_PLAT_MAPPI) #if defined(CONFIG_PLAT_MAPPI)
# define DCR_VAL 0x4b # define DCR_VAL 0x4b
#elif defined(CONFIG_PLAT_OAKS32R) #elif defined(CONFIG_PLAT_OAKS32R) || \
# define DCR_VAL 0x48 defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
# define DCR_VAL 0x48 /* 8-bit mode */
#else #else
# define DCR_VAL 0x49 # define DCR_VAL 0x49
#endif #endif
...@@ -396,6 +397,18 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) ...@@ -396,6 +397,18 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
/* We must set the 8390 for word mode. */ /* We must set the 8390 for word mode. */
outb_p(DCR_VAL, ioaddr + EN0_DCFG); outb_p(DCR_VAL, ioaddr + EN0_DCFG);
start_page = NESM_START_PG; start_page = NESM_START_PG;
/*
* Realtek RTL8019AS datasheet says that the PSTOP register
* shouldn't exceed 0x60 in 8-bit mode.
* This chip can be identified by reading the signature from
* the remote byte count registers (otherwise write-only)...
*/
if ((DCR_VAL & 0x01) == 0 && /* 8-bit mode */
inb(ioaddr + EN0_RCNTLO) == 0x50 &&
inb(ioaddr + EN0_RCNTHI) == 0x70)
stop_page = 0x60;
else
stop_page = NESM_STOP_PG; stop_page = NESM_STOP_PG;
} else { } else {
start_page = NE1SM_START_PG; start_page = NE1SM_START_PG;
...@@ -509,15 +522,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) ...@@ -509,15 +522,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.name = name; ei_status.name = name;
ei_status.tx_start_page = start_page; ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page; ei_status.stop_page = stop_page;
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
wordlength = 1;
#endif
#ifdef CONFIG_PLAT_OAKS32R /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
ei_status.word16 = 0; ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
#else
ei_status.word16 = (wordlength == 2);
#endif
ei_status.rx_start_page = start_page + TX_PAGES; ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE #ifdef PACKETBUF_MEMSIZE
......
This diff is collapsed.
...@@ -378,6 +378,9 @@ enum { ...@@ -378,6 +378,9 @@ enum {
CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */ CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
CHIP_REV_YU_EC_U_A0 = 0,
CHIP_REV_YU_EC_U_A1 = 1,
}; };
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
......
...@@ -1652,6 +1652,8 @@ spider_net_enable_card(struct spider_net_card *card) ...@@ -1652,6 +1652,8 @@ spider_net_enable_card(struct spider_net_card *card)
{ SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE }, { SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
{ SPIDER_NET_GMRWOLCTRL, 0 }, { SPIDER_NET_GMRWOLCTRL, 0 },
{ SPIDER_NET_GTESTMD, 0x10000000 },
{ SPIDER_NET_GTTQMSK, 0x00400040 },
{ SPIDER_NET_GTESTMD, 0 }, { SPIDER_NET_GTESTMD, 0 },
{ SPIDER_NET_GMACINTEN, 0 }, { SPIDER_NET_GMACINTEN, 0 },
...@@ -1792,15 +1794,7 @@ spider_net_setup_phy(struct spider_net_card *card) ...@@ -1792,15 +1794,7 @@ spider_net_setup_phy(struct spider_net_card *card)
if (phy->def->ops->setup_forced) if (phy->def->ops->setup_forced)
phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL); phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
/* the following two writes could be moved to sungem_phy.c */ phy->def->ops->enable_fiber(phy);
/* enable fiber mode */
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x9020);
/* LEDs active in both modes, autosense prio = fiber */
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
/* switch off fibre autoneg */
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
phy->def->ops->read_link(phy); phy->def->ops->read_link(phy);
pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
......
...@@ -120,6 +120,8 @@ extern char spider_net_driver_name[]; ...@@ -120,6 +120,8 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_GMRUAFILnR 0x00000500 #define SPIDER_NET_GMRUAFILnR 0x00000500
#define SPIDER_NET_GMRUA0FIL15R 0x00000578 #define SPIDER_NET_GMRUA0FIL15R 0x00000578
#define SPIDER_NET_GTTQMSK 0x00000934
/* RX DMA controller registers, all 0x00000a.. are for DMA controller A, /* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
* 0x00000b.. for DMA controller B, etc. */ * 0x00000b.. for DMA controller B, etc. */
#define SPIDER_NET_GDADCHA 0x00000a00 #define SPIDER_NET_GDADCHA 0x00000a00
......
...@@ -329,6 +329,30 @@ static int bcm5421_init(struct mii_phy* phy) ...@@ -329,6 +329,30 @@ static int bcm5421_init(struct mii_phy* phy)
return 0; return 0;
} }
static int bcm5421_enable_fiber(struct mii_phy* phy)
{
/* enable fiber mode */
phy_write(phy, MII_NCONFIG, 0x9020);
/* LEDs active in both modes, autosense prio = fiber */
phy_write(phy, MII_NCONFIG, 0x945f);
/* switch off fibre autoneg */
phy_write(phy, MII_NCONFIG, 0xfc01);
phy_write(phy, 0x0b, 0x0004);
return 0;
}
static int bcm5461_enable_fiber(struct mii_phy* phy)
{
phy_write(phy, MII_NCONFIG, 0xfc0c);
phy_write(phy, MII_BMCR, 0x4140);
phy_write(phy, MII_NCONFIG, 0xfc0b);
phy_write(phy, MII_BMCR, 0x0140);
return 0;
}
static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise) static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
{ {
u16 ctl, adv; u16 ctl, adv;
...@@ -762,6 +786,7 @@ static struct mii_phy_ops bcm5421_phy_ops = { ...@@ -762,6 +786,7 @@ static struct mii_phy_ops bcm5421_phy_ops = {
.setup_forced = bcm54xx_setup_forced, .setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link, .poll_link = genmii_poll_link,
.read_link = bcm54xx_read_link, .read_link = bcm54xx_read_link,
.enable_fiber = bcm5421_enable_fiber,
}; };
static struct mii_phy_def bcm5421_phy_def = { static struct mii_phy_def bcm5421_phy_def = {
...@@ -792,6 +817,25 @@ static struct mii_phy_def bcm5421k2_phy_def = { ...@@ -792,6 +817,25 @@ static struct mii_phy_def bcm5421k2_phy_def = {
.ops = &bcm5421k2_phy_ops .ops = &bcm5421k2_phy_ops
}; };
static struct mii_phy_ops bcm5461_phy_ops = {
.init = bcm5421_init,
.suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
.read_link = bcm54xx_read_link,
.enable_fiber = bcm5461_enable_fiber,
};
static struct mii_phy_def bcm5461_phy_def = {
.phy_id = 0x002060c0,
.phy_id_mask = 0xfffffff0,
.name = "BCM5461",
.features = MII_GBIT_FEATURES,
.magic_aneg = 1,
.ops = &bcm5461_phy_ops
};
/* Broadcom BCM 5462 built-in Vesta */ /* Broadcom BCM 5462 built-in Vesta */
static struct mii_phy_ops bcm5462V_phy_ops = { static struct mii_phy_ops bcm5462V_phy_ops = {
.init = bcm5421_init, .init = bcm5421_init,
...@@ -857,6 +901,7 @@ static struct mii_phy_def* mii_phy_table[] = { ...@@ -857,6 +901,7 @@ static struct mii_phy_def* mii_phy_table[] = {
&bcm5411_phy_def, &bcm5411_phy_def,
&bcm5421_phy_def, &bcm5421_phy_def,
&bcm5421k2_phy_def, &bcm5421k2_phy_def,
&bcm5461_phy_def,
&bcm5462V_phy_def, &bcm5462V_phy_def,
&marvell_phy_def, &marvell_phy_def,
&genmii_phy_def, &genmii_phy_def,
......
...@@ -12,6 +12,7 @@ struct mii_phy_ops ...@@ -12,6 +12,7 @@ struct mii_phy_ops
int (*setup_forced)(struct mii_phy *phy, int speed, int fd); int (*setup_forced)(struct mii_phy *phy, int speed, int fd);
int (*poll_link)(struct mii_phy *phy); int (*poll_link)(struct mii_phy *phy);
int (*read_link)(struct mii_phy *phy); int (*read_link)(struct mii_phy *phy);
int (*enable_fiber)(struct mii_phy *phy);
}; };
/* Structure used to statically define an mii/gii based PHY */ /* Structure used to statically define an mii/gii based PHY */
......
...@@ -939,9 +939,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) ...@@ -939,9 +939,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
return 0; return 0;
} }
static void bcm43xx_geo_init(struct bcm43xx_private *bcm) static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
{ {
struct ieee80211_geo geo; struct ieee80211_geo *geo;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
int have_a = 0, have_bg = 0; int have_a = 0, have_bg = 0;
int i; int i;
...@@ -949,7 +949,10 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) ...@@ -949,7 +949,10 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
struct bcm43xx_phyinfo *phy; struct bcm43xx_phyinfo *phy;
const char *iso_country; const char *iso_country;
memset(&geo, 0, sizeof(geo)); geo = kzalloc(sizeof(*geo), GFP_KERNEL);
if (!geo)
return -ENOMEM;
for (i = 0; i < bcm->nr_80211_available; i++) { for (i = 0; i < bcm->nr_80211_available; i++) {
phy = &(bcm->core_80211_ext[i].phy); phy = &(bcm->core_80211_ext[i].phy);
switch (phy->type) { switch (phy->type) {
...@@ -967,31 +970,36 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) ...@@ -967,31 +970,36 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
iso_country = bcm43xx_locale_iso(bcm->sprom.locale); iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
if (have_a) { if (have_a) {
for (i = 0, channel = 0; channel < 201; channel++) { for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
chan = &geo.a[i++]; channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
chan = &geo->a[i++];
chan->freq = bcm43xx_channel_to_freq_a(channel); chan->freq = bcm43xx_channel_to_freq_a(channel);
chan->channel = channel; chan->channel = channel;
} }
geo.a_channels = i; geo->a_channels = i;
} }
if (have_bg) { if (have_bg) {
for (i = 0, channel = 1; channel < 15; channel++) { for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
chan = &geo.bg[i++]; channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
chan = &geo->bg[i++];
chan->freq = bcm43xx_channel_to_freq_bg(channel); chan->freq = bcm43xx_channel_to_freq_bg(channel);
chan->channel = channel; chan->channel = channel;
} }
geo.bg_channels = i; geo->bg_channels = i;
} }
memcpy(geo.name, iso_country, 2); memcpy(geo->name, iso_country, 2);
if (0 /*TODO: Outdoor use only */) if (0 /*TODO: Outdoor use only */)
geo.name[2] = 'O'; geo->name[2] = 'O';
else if (0 /*TODO: Indoor use only */) else if (0 /*TODO: Indoor use only */)
geo.name[2] = 'I'; geo->name[2] = 'I';
else else
geo.name[2] = ' '; geo->name[2] = ' ';
geo.name[3] = '\0'; geo->name[3] = '\0';
ieee80211_set_geo(bcm->ieee, &geo); ieee80211_set_geo(bcm->ieee, geo);
kfree(geo);
return 0;
} }
/* DummyTransmission function, as documented on /* DummyTransmission function, as documented on
...@@ -3479,16 +3487,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) ...@@ -3479,16 +3487,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
goto err_80211_unwind; goto err_80211_unwind;
bcm43xx_wireless_core_disable(bcm); bcm43xx_wireless_core_disable(bcm);
} }
err = bcm43xx_geo_init(bcm);
if (err)
goto err_80211_unwind;
bcm43xx_pctl_set_crystal(bcm, 0); bcm43xx_pctl_set_crystal(bcm, 0);
/* Set the MAC address in the networking subsystem */ /* Set the MAC address in the networking subsystem */
if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) if (is_valid_ether_addr(bcm->sprom.et1macaddr))
memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
else else
memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
bcm43xx_geo_init(bcm);
snprintf(bcm->nick, IW_ESSID_MAX_SIZE, snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
"Broadcom %04X", bcm->chip_id); "Broadcom %04X", bcm->chip_id);
......
...@@ -118,12 +118,14 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, ...@@ -118,12 +118,14 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
static inline static inline
int bcm43xx_is_valid_channel_a(u8 channel) int bcm43xx_is_valid_channel_a(u8 channel)
{ {
return (channel <= 200); return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
&& channel <= IEEE80211_52GHZ_MAX_CHANNEL);
} }
static inline static inline
int bcm43xx_is_valid_channel_bg(u8 channel) int bcm43xx_is_valid_channel_bg(u8 channel)
{ {
return (channel >= 1 && channel <= 14); return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
&& channel <= IEEE80211_24GHZ_MAX_CHANNEL);
} }
static inline static inline
int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
......
...@@ -1287,7 +1287,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) ...@@ -1287,7 +1287,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
if (radio->revision == 8) if (radio->revision == 8)
bcm43xx_phy_write(bcm, 0x0805, 0x3230); bcm43xx_phy_write(bcm, 0x0805, 0x3230);
bcm43xx_phy_init_pctl(bcm); bcm43xx_phy_init_pctl(bcm);
if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) { if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
bcm43xx_phy_write(bcm, 0x0429, bcm43xx_phy_write(bcm, 0x0429,
bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
bcm43xx_phy_write(bcm, 0x04C3, bcm43xx_phy_write(bcm, 0x04C3,
......
...@@ -182,8 +182,11 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, ...@@ -182,8 +182,11 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
mode = BCM43xx_INITIAL_IWMODE; mode = BCM43xx_INITIAL_IWMODE;
bcm43xx_lock_mmio(bcm, flags); bcm43xx_lock_mmio(bcm, flags);
if (bcm->initialized) {
if (bcm->ieee->iw_mode != mode) if (bcm->ieee->iw_mode != mode)
bcm43xx_set_iwmode(bcm, mode); bcm43xx_set_iwmode(bcm, mode);
} else
bcm->ieee->iw_mode = mode;
bcm43xx_unlock_mmio(bcm, flags); bcm43xx_unlock_mmio(bcm, flags);
return 0; return 0;
......
...@@ -831,21 +831,19 @@ static inline void netif_rx_schedule(struct net_device *dev) ...@@ -831,21 +831,19 @@ static inline void netif_rx_schedule(struct net_device *dev)
__netif_rx_schedule(dev); __netif_rx_schedule(dev);
} }
/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().
static inline void __netif_rx_reschedule(struct net_device *dev, int undo) * Do not inline this?
{ */
dev->quota += undo;
list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}
/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */
static inline int netif_rx_reschedule(struct net_device *dev, int undo) static inline int netif_rx_reschedule(struct net_device *dev, int undo)
{ {
if (netif_rx_schedule_prep(dev)) { if (netif_rx_schedule_prep(dev)) {
unsigned long flags; unsigned long flags;
dev->quota += undo;
local_irq_save(flags); local_irq_save(flags);
__netif_rx_reschedule(dev, undo); list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
local_irq_restore(flags); local_irq_restore(flags);
return 1; return 1;
} }
......
...@@ -955,11 +955,13 @@ enum ieee80211_state { ...@@ -955,11 +955,13 @@ enum ieee80211_state {
#define IEEE80211_24GHZ_MIN_CHANNEL 1 #define IEEE80211_24GHZ_MIN_CHANNEL 1
#define IEEE80211_24GHZ_MAX_CHANNEL 14 #define IEEE80211_24GHZ_MAX_CHANNEL 14
#define IEEE80211_24GHZ_CHANNELS 14 #define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
IEEE80211_24GHZ_MIN_CHANNEL + 1)
#define IEEE80211_52GHZ_MIN_CHANNEL 34 #define IEEE80211_52GHZ_MIN_CHANNEL 34
#define IEEE80211_52GHZ_MAX_CHANNEL 165 #define IEEE80211_52GHZ_MAX_CHANNEL 165
#define IEEE80211_52GHZ_CHANNELS 131 #define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
IEEE80211_52GHZ_MIN_CHANNEL + 1)
enum { enum {
IEEE80211_CH_PASSIVE_ONLY = (1 << 0), IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
......
...@@ -204,7 +204,8 @@ struct ieee80211softmac_device { ...@@ -204,7 +204,8 @@ struct ieee80211softmac_device {
/* couple of flags */ /* couple of flags */
u8 scanning:1, /* protects scanning from being done multiple times at once */ u8 scanning:1, /* protects scanning from being done multiple times at once */
associated:1; associated:1,
running:1;
struct ieee80211softmac_scaninfo *scaninfo; struct ieee80211softmac_scaninfo *scaninfo;
struct ieee80211softmac_assoc_info associnfo; struct ieee80211softmac_assoc_info associnfo;
......
...@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft ...@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1; mac->associnfo.associating = 1;
mac->associated = 0; /* just to make sure */ mac->associated = 0; /* just to make sure */
spin_unlock_irqrestore(&mac->lock, flags);
/* Set a timer for timeout */ /* Set a timer for timeout */
/* FIXME: make timeout configurable */ /* FIXME: make timeout configurable */
if (likely(mac->running))
schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
spin_unlock_irqrestore(&mac->lock, flags);
} }
void void
...@@ -320,6 +321,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, ...@@ -320,6 +321,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
struct ieee80211softmac_network *network = NULL; struct ieee80211softmac_network *network = NULL;
unsigned long flags; unsigned long flags;
if (unlikely(!mac->running))
return -ENODEV;
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
if (!mac->associnfo.associating) { if (!mac->associnfo.associating) {
...@@ -377,10 +381,16 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, ...@@ -377,10 +381,16 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
unsigned long flags; unsigned long flags;
if (unlikely(!mac->running))
return -ENODEV;
if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
return 0; return 0;
if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
return 0; return 0;
dprintk(KERN_INFO PFX "got disassoc frame\n"); dprintk(KERN_INFO PFX "got disassoc frame\n");
netif_carrier_off(dev); netif_carrier_off(dev);
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
...@@ -400,6 +410,9 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, ...@@ -400,6 +410,9 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
struct ieee80211softmac_network *network; struct ieee80211softmac_network *network;
if (unlikely(!mac->running))
return -ENODEV;
network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
if (!network) { if (!network) {
dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
......
...@@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data) ...@@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data)
/* Lock and set flags */ /* Lock and set flags */
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
if (unlikely(!mac->running)) {
/* Prevent reschedule on workqueue flush */
spin_unlock_irqrestore(&mac->lock, flags);
return;
}
net->authenticated = 0; net->authenticated = 0;
net->authenticating = 1; net->authenticating = 1;
/* add a timeout call so we eventually give up waiting for an auth reply */ /* add a timeout call so we eventually give up waiting for an auth reply */
...@@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) ...@@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
unsigned long flags; unsigned long flags;
u8 * data; u8 * data;
if (unlikely(!mac->running))
return -ENODEV;
/* Find correct auth queue item */ /* Find correct auth queue item */
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
list_for_each(list_ptr, &mac->auth_queue) { list_for_each(list_ptr, &mac->auth_queue) {
...@@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, ...@@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
/* can't transmit data right now... */ /* can't transmit data right now... */
netif_carrier_off(mac->dev); netif_carrier_off(mac->dev);
/* let's try to re-associate */
schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
} }
...@@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de ...@@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
struct ieee80211softmac_network *net = NULL; struct ieee80211softmac_network *net = NULL;
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
if (unlikely(!mac->running))
return -ENODEV;
if (!deauth) { if (!deauth) {
dprintk("deauth without deauth packet. eek!\n"); dprintk("deauth without deauth packet. eek!\n");
return 0; return 0;
...@@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de ...@@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
} }
ieee80211softmac_deauth_from_net(mac, net); ieee80211softmac_deauth_from_net(mac, net);
/* let's try to re-associate */
schedule_work(&mac->associnfo.work);
return 0; return 0;
} }
...@@ -89,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) ...@@ -89,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
ieee80211softmac_wait_for_scan(sm); ieee80211softmac_wait_for_scan(sm);
spin_lock_irqsave(&sm->lock, flags); spin_lock_irqsave(&sm->lock, flags);
sm->running = 0;
/* Free all pending assoc work items */ /* Free all pending assoc work items */
cancel_delayed_work(&sm->associnfo.work); cancel_delayed_work(&sm->associnfo.work);
...@@ -204,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev) ...@@ -204,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev)
assert(0); assert(0);
if (mac->txrates_change) if (mac->txrates_change)
mac->txrates_change(dev, change, &oldrates); mac->txrates_change(dev, change, &oldrates);
mac->running = 1;
} }
EXPORT_SYMBOL_GPL(ieee80211softmac_start); EXPORT_SYMBOL_GPL(ieee80211softmac_start);
......
...@@ -115,7 +115,15 @@ void ieee80211softmac_scan(void *d) ...@@ -115,7 +115,15 @@ void ieee80211softmac_scan(void *d)
// TODO: is this if correct, or should we do this only if scanning from assoc request? // TODO: is this if correct, or should we do this only if scanning from assoc request?
if (sm->associnfo.req_essid.len) if (sm->associnfo.req_essid.len)
ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
spin_lock_irqsave(&sm->lock, flags);
if (unlikely(!sm->running)) {
/* Prevent reschedule on workqueue flush */
spin_unlock_irqrestore(&sm->lock, flags);
break;
}
schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
spin_unlock_irqrestore(&sm->lock, flags);
return; return;
} else { } else {
dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
......
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