Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6

+84 -30
+27 -18
drivers/net/wireless/bcm43xx/bcm43xx_main.c
··· 939 939 return 0; 940 940 } 941 941 942 - static void bcm43xx_geo_init(struct bcm43xx_private *bcm) 942 + static int bcm43xx_geo_init(struct bcm43xx_private *bcm) 943 943 { 944 - struct ieee80211_geo geo; 944 + struct ieee80211_geo *geo; 945 945 struct ieee80211_channel *chan; 946 946 int have_a = 0, have_bg = 0; 947 947 int i; ··· 949 949 struct bcm43xx_phyinfo *phy; 950 950 const char *iso_country; 951 951 952 - memset(&geo, 0, sizeof(geo)); 952 + geo = kzalloc(sizeof(*geo), GFP_KERNEL); 953 + if (!geo) 954 + return -ENOMEM; 955 + 953 956 for (i = 0; i < bcm->nr_80211_available; i++) { 954 957 phy = &(bcm->core_80211_ext[i].phy); 955 958 switch (phy->type) { ··· 970 967 iso_country = bcm43xx_locale_iso(bcm->sprom.locale); 971 968 972 969 if (have_a) { 973 - for (i = 0, channel = 0; channel < 201; channel++) { 974 - chan = &geo.a[i++]; 970 + for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; 971 + channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) { 972 + chan = &geo->a[i++]; 975 973 chan->freq = bcm43xx_channel_to_freq_a(channel); 976 974 chan->channel = channel; 977 975 } 978 - geo.a_channels = i; 976 + geo->a_channels = i; 979 977 } 980 978 if (have_bg) { 981 - for (i = 0, channel = 1; channel < 15; channel++) { 982 - chan = &geo.bg[i++]; 979 + for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; 980 + channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) { 981 + chan = &geo->bg[i++]; 983 982 chan->freq = bcm43xx_channel_to_freq_bg(channel); 984 983 chan->channel = channel; 985 984 } 986 - geo.bg_channels = i; 985 + geo->bg_channels = i; 987 986 } 988 - memcpy(geo.name, iso_country, 2); 987 + memcpy(geo->name, iso_country, 2); 989 988 if (0 /*TODO: Outdoor use only */) 990 - geo.name[2] = 'O'; 989 + geo->name[2] = 'O'; 991 990 else if (0 /*TODO: Indoor use only */) 992 - geo.name[2] = 'I'; 991 + geo->name[2] = 'I'; 993 992 else 994 - geo.name[2] = ' '; 995 - geo.name[3] = '\0'; 993 + geo->name[2] = ' '; 994 + geo->name[3] = '\0'; 996 995 997 - ieee80211_set_geo(bcm->ieee, &geo); 996 + ieee80211_set_geo(bcm->ieee, geo); 997 + kfree(geo); 998 + 999 + return 0; 998 1000 } 999 1001 1000 1002 /* DummyTransmission function, as documented on ··· 3487 3479 goto err_80211_unwind; 3488 3480 bcm43xx_wireless_core_disable(bcm); 3489 3481 } 3482 + err = bcm43xx_geo_init(bcm); 3483 + if (err) 3484 + goto err_80211_unwind; 3490 3485 bcm43xx_pctl_set_crystal(bcm, 0); 3491 3486 3492 3487 /* Set the MAC address in the networking subsystem */ 3493 - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) 3488 + if (is_valid_ether_addr(bcm->sprom.et1macaddr)) 3494 3489 memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); 3495 3490 else 3496 3491 memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); 3497 - 3498 - bcm43xx_geo_init(bcm); 3499 3492 3500 3493 snprintf(bcm->nick, IW_ESSID_MAX_SIZE, 3501 3494 "Broadcom %04X", bcm->chip_id);
+4 -2
drivers/net/wireless/bcm43xx/bcm43xx_main.h
··· 118 118 static inline 119 119 int bcm43xx_is_valid_channel_a(u8 channel) 120 120 { 121 - return (channel <= 200); 121 + return (channel >= IEEE80211_52GHZ_MIN_CHANNEL 122 + && channel <= IEEE80211_52GHZ_MAX_CHANNEL); 122 123 } 123 124 static inline 124 125 int bcm43xx_is_valid_channel_bg(u8 channel) 125 126 { 126 - return (channel >= 1 && channel <= 14); 127 + return (channel >= IEEE80211_24GHZ_MIN_CHANNEL 128 + && channel <= IEEE80211_24GHZ_MAX_CHANNEL); 127 129 } 128 130 static inline 129 131 int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
+1 -1
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
··· 1287 1287 if (radio->revision == 8) 1288 1288 bcm43xx_phy_write(bcm, 0x0805, 0x3230); 1289 1289 bcm43xx_phy_init_pctl(bcm); 1290 - if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) { 1290 + if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) { 1291 1291 bcm43xx_phy_write(bcm, 0x0429, 1292 1292 bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); 1293 1293 bcm43xx_phy_write(bcm, 0x04C3,
+5 -2
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
··· 182 182 mode = BCM43xx_INITIAL_IWMODE; 183 183 184 184 bcm43xx_lock_mmio(bcm, flags); 185 - if (bcm->ieee->iw_mode != mode) 186 - bcm43xx_set_iwmode(bcm, mode); 185 + if (bcm->initialized) { 186 + if (bcm->ieee->iw_mode != mode) 187 + bcm43xx_set_iwmode(bcm, mode); 188 + } else 189 + bcm->ieee->iw_mode = mode; 187 190 bcm43xx_unlock_mmio(bcm, flags); 188 191 189 192 return 0;
+4 -2
include/net/ieee80211.h
··· 955 955 956 956 #define IEEE80211_24GHZ_MIN_CHANNEL 1 957 957 #define IEEE80211_24GHZ_MAX_CHANNEL 14 958 - #define IEEE80211_24GHZ_CHANNELS 14 958 + #define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \ 959 + IEEE80211_24GHZ_MIN_CHANNEL + 1) 959 960 960 961 #define IEEE80211_52GHZ_MIN_CHANNEL 34 961 962 #define IEEE80211_52GHZ_MAX_CHANNEL 165 962 - #define IEEE80211_52GHZ_CHANNELS 131 963 + #define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \ 964 + IEEE80211_52GHZ_MIN_CHANNEL + 1) 963 965 964 966 enum { 965 967 IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+2 -1
include/net/ieee80211softmac.h
··· 204 204 205 205 /* couple of flags */ 206 206 u8 scanning:1, /* protects scanning from being done multiple times at once */ 207 - associated:1; 207 + associated:1, 208 + running:1; 208 209 209 210 struct ieee80211softmac_scaninfo *scaninfo; 210 211 struct ieee80211softmac_assoc_info associnfo;
+15 -2
net/ieee80211/softmac/ieee80211softmac_assoc.c
··· 51 51 spin_lock_irqsave(&mac->lock, flags); 52 52 mac->associnfo.associating = 1; 53 53 mac->associated = 0; /* just to make sure */ 54 - spin_unlock_irqrestore(&mac->lock, flags); 55 54 56 55 /* Set a timer for timeout */ 57 56 /* FIXME: make timeout configurable */ 58 - schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); 57 + if (likely(mac->running)) 58 + schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); 59 + spin_unlock_irqrestore(&mac->lock, flags); 59 60 } 60 61 61 62 void ··· 320 319 u16 status = le16_to_cpup(&resp->status); 321 320 struct ieee80211softmac_network *network = NULL; 322 321 unsigned long flags; 322 + 323 + if (unlikely(!mac->running)) 324 + return -ENODEV; 323 325 324 326 spin_lock_irqsave(&mac->lock, flags); 325 327 ··· 381 377 { 382 378 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 383 379 unsigned long flags; 380 + 381 + if (unlikely(!mac->running)) 382 + return -ENODEV; 383 + 384 384 if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) 385 385 return 0; 386 + 386 387 if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) 387 388 return 0; 389 + 388 390 dprintk(KERN_INFO PFX "got disassoc frame\n"); 389 391 netif_carrier_off(dev); 390 392 spin_lock_irqsave(&mac->lock, flags); ··· 409 399 { 410 400 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 411 401 struct ieee80211softmac_network *network; 402 + 403 + if (unlikely(!mac->running)) 404 + return -ENODEV; 412 405 413 406 network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); 414 407 if (!network) {
+14 -2
net/ieee80211/softmac/ieee80211softmac_auth.c
··· 86 86 87 87 /* Lock and set flags */ 88 88 spin_lock_irqsave(&mac->lock, flags); 89 + if (unlikely(!mac->running)) { 90 + /* Prevent reschedule on workqueue flush */ 91 + spin_unlock_irqrestore(&mac->lock, flags); 92 + return; 93 + } 89 94 net->authenticated = 0; 90 95 net->authenticating = 1; 91 96 /* add a timeout call so we eventually give up waiting for an auth reply */ ··· 129 124 unsigned long flags; 130 125 u8 * data; 131 126 127 + if (unlikely(!mac->running)) 128 + return -ENODEV; 129 + 132 130 /* Find correct auth queue item */ 133 131 spin_lock_irqsave(&mac->lock, flags); 134 132 list_for_each(list_ptr, &mac->auth_queue) { ··· 306 298 307 299 /* can't transmit data right now... */ 308 300 netif_carrier_off(mac->dev); 309 - /* let's try to re-associate */ 310 - schedule_work(&mac->associnfo.work); 311 301 spin_unlock_irqrestore(&mac->lock, flags); 312 302 } 313 303 ··· 344 338 struct ieee80211softmac_network *net = NULL; 345 339 struct ieee80211softmac_device *mac = ieee80211_priv(dev); 346 340 341 + if (unlikely(!mac->running)) 342 + return -ENODEV; 343 + 347 344 if (!deauth) { 348 345 dprintk("deauth without deauth packet. eek!\n"); 349 346 return 0; ··· 369 360 } 370 361 371 362 ieee80211softmac_deauth_from_net(mac, net); 363 + 364 + /* let's try to re-associate */ 365 + schedule_work(&mac->associnfo.work); 372 366 return 0; 373 367 }
+4
net/ieee80211/softmac/ieee80211softmac_module.c
··· 89 89 ieee80211softmac_wait_for_scan(sm); 90 90 91 91 spin_lock_irqsave(&sm->lock, flags); 92 + sm->running = 0; 93 + 92 94 /* Free all pending assoc work items */ 93 95 cancel_delayed_work(&sm->associnfo.work); 94 96 ··· 206 204 assert(0); 207 205 if (mac->txrates_change) 208 206 mac->txrates_change(dev, change, &oldrates); 207 + 208 + mac->running = 1; 209 209 } 210 210 EXPORT_SYMBOL_GPL(ieee80211softmac_start); 211 211
+8
net/ieee80211/softmac/ieee80211softmac_scan.c
··· 115 115 // TODO: is this if correct, or should we do this only if scanning from assoc request? 116 116 if (sm->associnfo.req_essid.len) 117 117 ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); 118 + 119 + spin_lock_irqsave(&sm->lock, flags); 120 + if (unlikely(!sm->running)) { 121 + /* Prevent reschedule on workqueue flush */ 122 + spin_unlock_irqrestore(&sm->lock, flags); 123 + break; 124 + } 118 125 schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); 126 + spin_unlock_irqrestore(&sm->lock, flags); 119 127 return; 120 128 } else { 121 129 dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);