Commit 23aee82e authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'upstream-fixes' of...

Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
parents 8ec93459 178e0cc5
...@@ -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);
kfree(geo);
ieee80211_set_geo(bcm->ieee, &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->ieee->iw_mode != mode) if (bcm->initialized) {
bcm43xx_set_iwmode(bcm, mode); if (bcm->ieee->iw_mode != 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;
......
...@@ -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 */
schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); if (likely(mac->running))
schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
spin_unlock_irqrestore(&mac->lock, flags);
} }
void void
...@@ -319,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, ...@@ -319,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
u16 status = le16_to_cpup(&resp->status); u16 status = le16_to_cpup(&resp->status);
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);
...@@ -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