diff options
| author | David S. Miller <davem@davemloft.net> | 2009-12-29 22:44:25 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-12-29 22:44:25 -0500 |
| commit | 7f9d3577e2603ca279c3176b696eba392f21cbe2 (patch) | |
| tree | e2135eddba600910cdebb54c8b01de53473ecefb | |
| parent | 96c5340147584481ef0c0afbb5423f7563c1d24a (diff) | |
| parent | 55afc80b2ab100618c17af77915f75307b6bd5d1 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
29 files changed, 130 insertions, 448 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a4c086f069b1..e63b7c40d0ee 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -1903,17 +1903,6 @@ accept: | |||
| 1903 | rxs->noise = sc->ah->ah_noise_floor; | 1903 | rxs->noise = sc->ah->ah_noise_floor; |
| 1904 | rxs->signal = rxs->noise + rs.rs_rssi; | 1904 | rxs->signal = rxs->noise + rs.rs_rssi; |
| 1905 | 1905 | ||
| 1906 | /* An rssi of 35 indicates you should be able use | ||
| 1907 | * 54 Mbps reliably. A more elaborate scheme can be used | ||
| 1908 | * here but it requires a map of SNR/throughput for each | ||
| 1909 | * possible mode used */ | ||
| 1910 | rxs->qual = rs.rs_rssi * 100 / 35; | ||
| 1911 | |||
| 1912 | /* rssi can be more than 35 though, anything above that | ||
| 1913 | * should be considered at 100% */ | ||
| 1914 | if (rxs->qual > 100) | ||
| 1915 | rxs->qual = 100; | ||
| 1916 | |||
| 1917 | rxs->antenna = rs.rs_antenna; | 1906 | rxs->antenna = rs.rs_antenna; |
| 1918 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 1907 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
| 1919 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 1908 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
| @@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc) | |||
| 2381 | */ | 2370 | */ |
| 2382 | ath5k_stop_locked(sc); | 2371 | ath5k_stop_locked(sc); |
| 2383 | 2372 | ||
| 2373 | /* Set PHY calibration interval */ | ||
| 2374 | ah->ah_cal_intval = ath5k_calinterval; | ||
| 2375 | |||
| 2384 | /* | 2376 | /* |
| 2385 | * The basic interface to setting the hardware in a good | 2377 | * The basic interface to setting the hardware in a good |
| 2386 | * state is ``reset''. On return the hardware is known to | 2378 | * state is ``reset''. On return the hardware is known to |
| @@ -2408,10 +2400,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
| 2408 | 2400 | ||
| 2409 | /* Set ack to be sent at low bit-rates */ | 2401 | /* Set ack to be sent at low bit-rates */ |
| 2410 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2402 | ath5k_hw_set_ack_bitrate_high(ah, false); |
| 2411 | |||
| 2412 | /* Set PHY calibration inteval */ | ||
| 2413 | ah->ah_cal_intval = ath5k_calinterval; | ||
| 2414 | |||
| 2415 | ret = 0; | 2403 | ret = 0; |
| 2416 | done: | 2404 | done: |
| 2417 | mmiowb(); | 2405 | mmiowb(); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0c87771383f0..e185479e295e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
| @@ -77,6 +77,9 @@ | |||
| 77 | #define ATH9K_TXERR_XTXOP 0x08 | 77 | #define ATH9K_TXERR_XTXOP 0x08 |
| 78 | #define ATH9K_TXERR_TIMER_EXPIRED 0x10 | 78 | #define ATH9K_TXERR_TIMER_EXPIRED 0x10 |
| 79 | #define ATH9K_TX_ACKED 0x20 | 79 | #define ATH9K_TX_ACKED 0x20 |
| 80 | #define ATH9K_TXERR_MASK \ | ||
| 81 | (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ | ||
| 82 | ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) | ||
| 80 | 83 | ||
| 81 | #define ATH9K_TX_BA 0x01 | 84 | #define ATH9K_TX_BA 0x01 |
| 82 | #define ATH9K_TX_PWRMGMT 0x02 | 85 | #define ATH9K_TX_PWRMGMT 0x02 |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9e68c1a8aef0..996eb90263cc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -2514,6 +2514,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2514 | return; /* another wiphy still in use */ | 2514 | return; /* another wiphy still in use */ |
| 2515 | } | 2515 | } |
| 2516 | 2516 | ||
| 2517 | /* Ensure HW is awake when we try to shut it down. */ | ||
| 2518 | ath9k_ps_wakeup(sc); | ||
| 2519 | |||
| 2517 | if (ah->btcoex_hw.enabled) { | 2520 | if (ah->btcoex_hw.enabled) { |
| 2518 | ath9k_hw_btcoex_disable(ah); | 2521 | ath9k_hw_btcoex_disable(ah); |
| 2519 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 2522 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
| @@ -2534,6 +2537,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2534 | /* disable HAL and put h/w to sleep */ | 2537 | /* disable HAL and put h/w to sleep */ |
| 2535 | ath9k_hw_disable(ah); | 2538 | ath9k_hw_disable(ah); |
| 2536 | ath9k_hw_configpcipowersave(ah, 1, 1); | 2539 | ath9k_hw_configpcipowersave(ah, 1, 1); |
| 2540 | ath9k_ps_restore(sc); | ||
| 2541 | |||
| 2542 | /* Finally, put the chip in FULL SLEEP mode */ | ||
| 2537 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | 2543 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
| 2538 | 2544 | ||
| 2539 | sc->sc_flags |= SC_OP_INVALID; | 2545 | sc->sc_flags |= SC_OP_INVALID; |
| @@ -2647,8 +2653,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
| 2647 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || | 2653 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
| 2648 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || | 2654 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || |
| 2649 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { | 2655 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { |
| 2656 | ath9k_ps_wakeup(sc); | ||
| 2650 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2657 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
| 2651 | ath_beacon_return(sc, avp); | 2658 | ath_beacon_return(sc, avp); |
| 2659 | ath9k_ps_restore(sc); | ||
| 2652 | } | 2660 | } |
| 2653 | 2661 | ||
| 2654 | sc->sc_flags &= ~SC_OP_BEACONS; | 2662 | sc->sc_flags &= ~SC_OP_BEACONS; |
| @@ -3097,15 +3105,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
| 3097 | case IEEE80211_AMPDU_RX_STOP: | 3105 | case IEEE80211_AMPDU_RX_STOP: |
| 3098 | break; | 3106 | break; |
| 3099 | case IEEE80211_AMPDU_TX_START: | 3107 | case IEEE80211_AMPDU_TX_START: |
| 3108 | ath9k_ps_wakeup(sc); | ||
| 3100 | ath_tx_aggr_start(sc, sta, tid, ssn); | 3109 | ath_tx_aggr_start(sc, sta, tid, ssn); |
| 3101 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 3110 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
| 3111 | ath9k_ps_restore(sc); | ||
| 3102 | break; | 3112 | break; |
| 3103 | case IEEE80211_AMPDU_TX_STOP: | 3113 | case IEEE80211_AMPDU_TX_STOP: |
| 3114 | ath9k_ps_wakeup(sc); | ||
| 3104 | ath_tx_aggr_stop(sc, sta, tid); | 3115 | ath_tx_aggr_stop(sc, sta, tid); |
| 3105 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 3116 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
| 3117 | ath9k_ps_restore(sc); | ||
| 3106 | break; | 3118 | break; |
| 3107 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3119 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
| 3120 | ath9k_ps_wakeup(sc); | ||
| 3108 | ath_tx_aggr_resume(sc, sta, tid); | 3121 | ath_tx_aggr_resume(sc, sta, tid); |
| 3122 | ath9k_ps_restore(sc); | ||
| 3109 | break; | 3123 | break; |
| 3110 | default: | 3124 | default: |
| 3111 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 3125 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 5321f735e5a0..f7af5ea54753 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -96,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
| 96 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | 96 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | const static struct ath_bus_ops ath_pci_bus_ops = { | 99 | static const struct ath_bus_ops ath_pci_bus_ops = { |
| 100 | .read_cachesize = ath_pci_read_cachesize, | 100 | .read_cachesize = ath_pci_read_cachesize, |
| 101 | .cleanup = ath_pci_cleanup, | 101 | .cleanup = ath_pci_cleanup, |
| 102 | .eeprom_read = ath_pci_eeprom_read, | 102 | .eeprom_read = ath_pci_eeprom_read, |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1e813bbf474a..fa12b9060b0b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -2072,7 +2072,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
| 2072 | &txq->axq_q, lastbf->list.prev); | 2072 | &txq->axq_q, lastbf->list.prev); |
| 2073 | 2073 | ||
| 2074 | txq->axq_depth--; | 2074 | txq->axq_depth--; |
| 2075 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); | 2075 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); |
| 2076 | txq->axq_tx_inprogress = false; | 2076 | txq->axq_tx_inprogress = false; |
| 2077 | spin_unlock_bh(&txq->axq_lock); | 2077 | spin_unlock_bh(&txq->axq_lock); |
| 2078 | 2078 | ||
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 027be275e035..88d1fd02d40a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -383,160 +383,44 @@ static inline | |||
| 383 | } | 383 | } |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | /* Check if a DMA region fits the device constraints. | ||
| 387 | * Returns true, if the region is OK for usage with this device. */ | ||
| 388 | static inline bool b43_dma_address_ok(struct b43_dmaring *ring, | ||
| 389 | dma_addr_t addr, size_t size) | ||
| 390 | { | ||
| 391 | switch (ring->type) { | ||
| 392 | case B43_DMA_30BIT: | ||
| 393 | if ((u64)addr + size > (1ULL << 30)) | ||
| 394 | return 0; | ||
| 395 | break; | ||
| 396 | case B43_DMA_32BIT: | ||
| 397 | if ((u64)addr + size > (1ULL << 32)) | ||
| 398 | return 0; | ||
| 399 | break; | ||
| 400 | case B43_DMA_64BIT: | ||
| 401 | /* Currently we can't have addresses beyond | ||
| 402 | * 64bit in the kernel. */ | ||
| 403 | break; | ||
| 404 | } | ||
| 405 | return 1; | ||
| 406 | } | ||
| 407 | |||
| 408 | #define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0) | ||
| 409 | #define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0) | ||
| 410 | |||
| 411 | static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base, | ||
| 412 | dma_addr_t dmaaddr, size_t size) | ||
| 413 | { | ||
| 414 | ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE); | ||
| 415 | free_pages((unsigned long)base, get_order(size)); | ||
| 416 | } | ||
| 417 | |||
| 418 | static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
| 419 | dma_addr_t *dmaaddr, size_t size, | ||
| 420 | gfp_t gfp_flags) | ||
| 421 | { | ||
| 422 | void *base; | ||
| 423 | |||
| 424 | base = (void *)__get_free_pages(gfp_flags, get_order(size)); | ||
| 425 | if (!base) | ||
| 426 | return NULL; | ||
| 427 | memset(base, 0, size); | ||
| 428 | *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size, | ||
| 429 | DMA_TO_DEVICE); | ||
| 430 | if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) { | ||
| 431 | free_pages((unsigned long)base, get_order(size)); | ||
| 432 | return NULL; | ||
| 433 | } | ||
| 434 | |||
| 435 | return base; | ||
| 436 | } | ||
| 437 | |||
| 438 | static void * b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
| 439 | dma_addr_t *dmaaddr, size_t size) | ||
| 440 | { | ||
| 441 | void *base; | ||
| 442 | |||
| 443 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
| 444 | GFP_KERNEL); | ||
| 445 | if (!base) { | ||
| 446 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
| 447 | "for DMA ringmemory\n"); | ||
| 448 | return NULL; | ||
| 449 | } | ||
| 450 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
| 451 | /* The memory does not fit our device constraints. | ||
| 452 | * Retry with GFP_DMA set to get lower memory. */ | ||
| 453 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
| 454 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
| 455 | GFP_KERNEL | GFP_DMA); | ||
| 456 | if (!base) { | ||
| 457 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
| 458 | "in the GFP_DMA region for DMA ringmemory\n"); | ||
| 459 | return NULL; | ||
| 460 | } | ||
| 461 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
| 462 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
| 463 | b43err(ring->dev->wl, "Failed to allocate DMA " | ||
| 464 | "ringmemory that fits device constraints\n"); | ||
| 465 | return NULL; | ||
| 466 | } | ||
| 467 | } | ||
| 468 | /* We expect the memory to be 4k aligned, at least. */ | ||
| 469 | if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) { | ||
| 470 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
| 471 | return NULL; | ||
| 472 | } | ||
| 473 | |||
| 474 | return base; | ||
| 475 | } | ||
| 476 | |||
| 477 | static int alloc_ringmemory(struct b43_dmaring *ring) | 386 | static int alloc_ringmemory(struct b43_dmaring *ring) |
| 478 | { | 387 | { |
| 479 | unsigned int required; | 388 | gfp_t flags = GFP_KERNEL; |
| 480 | void *base; | 389 | |
| 481 | dma_addr_t dmaaddr; | 390 | /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K |
| 482 | 391 | * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing | |
| 483 | /* There are several requirements to the descriptor ring memory: | 392 | * has shown that 4K is sufficient for the latter as long as the buffer |
| 484 | * - The memory region needs to fit the address constraints for the | 393 | * does not cross an 8K boundary. |
| 485 | * device (same as for frame buffers). | 394 | * |
| 486 | * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned. | 395 | * For unknown reasons - possibly a hardware error - the BCM4311 rev |
| 487 | * - For 64bit DMA devices, the descriptor ring must be 8k aligned. | 396 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, |
| 397 | * which accounts for the GFP_DMA flag below. | ||
| 398 | * | ||
| 399 | * The flags here must match the flags in free_ringmemory below! | ||
| 488 | */ | 400 | */ |
| 489 | |||
| 490 | if (ring->type == B43_DMA_64BIT) | 401 | if (ring->type == B43_DMA_64BIT) |
| 491 | required = ring->nr_slots * sizeof(struct b43_dmadesc64); | 402 | flags |= GFP_DMA; |
| 492 | else | 403 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, |
| 493 | required = ring->nr_slots * sizeof(struct b43_dmadesc32); | 404 | B43_DMA_RINGMEMSIZE, |
| 494 | if (B43_WARN_ON(required > 0x1000)) | 405 | &(ring->dmabase), flags); |
| 406 | if (!ring->descbase) { | ||
| 407 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); | ||
| 495 | return -ENOMEM; | 408 | return -ENOMEM; |
| 496 | |||
| 497 | ring->alloc_descsize = 0x1000; | ||
| 498 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
| 499 | if (!base) | ||
| 500 | return -ENOMEM; | ||
| 501 | ring->alloc_descbase = base; | ||
| 502 | ring->alloc_dmabase = dmaaddr; | ||
| 503 | |||
| 504 | if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) { | ||
| 505 | /* We're on <=32bit DMA, or we already got 8k aligned memory. | ||
| 506 | * That's all we need, so we're fine. */ | ||
| 507 | ring->descbase = base; | ||
| 508 | ring->dmabase = dmaaddr; | ||
| 509 | return 0; | ||
| 510 | } | ||
| 511 | b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize); | ||
| 512 | |||
| 513 | /* Ok, we failed at the 8k alignment requirement. | ||
| 514 | * Try to force-align the memory region now. */ | ||
| 515 | ring->alloc_descsize = 0x2000; | ||
| 516 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
| 517 | if (!base) | ||
| 518 | return -ENOMEM; | ||
| 519 | ring->alloc_descbase = base; | ||
| 520 | ring->alloc_dmabase = dmaaddr; | ||
| 521 | |||
| 522 | if (is_8k_aligned(dmaaddr)) { | ||
| 523 | /* We're already 8k aligned. That Ok, too. */ | ||
| 524 | ring->descbase = base; | ||
| 525 | ring->dmabase = dmaaddr; | ||
| 526 | return 0; | ||
| 527 | } | 409 | } |
| 528 | /* Force-align it to 8k */ | 410 | memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); |
| 529 | ring->descbase = (void *)((u8 *)base + 0x1000); | ||
| 530 | ring->dmabase = dmaaddr + 0x1000; | ||
| 531 | B43_WARN_ON(!is_8k_aligned(ring->dmabase)); | ||
| 532 | 411 | ||
| 533 | return 0; | 412 | return 0; |
| 534 | } | 413 | } |
| 535 | 414 | ||
| 536 | static void free_ringmemory(struct b43_dmaring *ring) | 415 | static void free_ringmemory(struct b43_dmaring *ring) |
| 537 | { | 416 | { |
| 538 | b43_unmap_and_free_ringmem(ring, ring->alloc_descbase, | 417 | gfp_t flags = GFP_KERNEL; |
| 539 | ring->alloc_dmabase, ring->alloc_descsize); | 418 | |
| 419 | if (ring->type == B43_DMA_64BIT) | ||
| 420 | flags |= GFP_DMA; | ||
| 421 | |||
| 422 | ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, | ||
| 423 | ring->descbase, ring->dmabase, flags); | ||
| 540 | } | 424 | } |
| 541 | 425 | ||
| 542 | /* Reset the RX DMA channel */ | 426 | /* Reset the RX DMA channel */ |
| @@ -646,14 +530,29 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, | |||
| 646 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) | 530 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) |
| 647 | return 1; | 531 | return 1; |
| 648 | 532 | ||
| 649 | if (!b43_dma_address_ok(ring, addr, buffersize)) { | 533 | switch (ring->type) { |
| 650 | /* We can't support this address. Unmap it again. */ | 534 | case B43_DMA_30BIT: |
| 651 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | 535 | if ((u64)addr + buffersize > (1ULL << 30)) |
| 652 | return 1; | 536 | goto address_error; |
| 537 | break; | ||
| 538 | case B43_DMA_32BIT: | ||
| 539 | if ((u64)addr + buffersize > (1ULL << 32)) | ||
| 540 | goto address_error; | ||
| 541 | break; | ||
| 542 | case B43_DMA_64BIT: | ||
| 543 | /* Currently we can't have addresses beyond | ||
| 544 | * 64bit in the kernel. */ | ||
| 545 | break; | ||
| 653 | } | 546 | } |
| 654 | 547 | ||
| 655 | /* The address is OK. */ | 548 | /* The address is OK. */ |
| 656 | return 0; | 549 | return 0; |
| 550 | |||
| 551 | address_error: | ||
| 552 | /* We can't support this address. Unmap it again. */ | ||
| 553 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | ||
| 554 | |||
| 555 | return 1; | ||
| 657 | } | 556 | } |
| 658 | 557 | ||
| 659 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) | 558 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) |
| @@ -715,9 +614,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
| 715 | meta->dmaaddr = dmaaddr; | 614 | meta->dmaaddr = dmaaddr; |
| 716 | ring->ops->fill_descriptor(ring, desc, dmaaddr, | 615 | ring->ops->fill_descriptor(ring, desc, dmaaddr, |
| 717 | ring->rx_buffersize, 0, 0, 0); | 616 | ring->rx_buffersize, 0, 0, 0); |
| 718 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
| 719 | ring->alloc_dmabase, | ||
| 720 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
| 721 | 617 | ||
| 722 | return 0; | 618 | return 0; |
| 723 | } | 619 | } |
| @@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
| 1354 | } | 1250 | } |
| 1355 | /* Now transfer the whole frame. */ | 1251 | /* Now transfer the whole frame. */ |
| 1356 | wmb(); | 1252 | wmb(); |
| 1357 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
| 1358 | ring->alloc_dmabase, | ||
| 1359 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
| 1360 | ops->poke_tx(ring, next_slot(ring, slot)); | 1253 | ops->poke_tx(ring, next_slot(ring, slot)); |
| 1361 | return 0; | 1254 | return 0; |
| 1362 | 1255 | ||
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index e607b392314c..f7ab37c4cdbc 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
| @@ -157,6 +157,7 @@ struct b43_dmadesc_generic { | |||
| 157 | } __attribute__ ((__packed__)); | 157 | } __attribute__ ((__packed__)); |
| 158 | 158 | ||
| 159 | /* Misc DMA constants */ | 159 | /* Misc DMA constants */ |
| 160 | #define B43_DMA_RINGMEMSIZE PAGE_SIZE | ||
| 160 | #define B43_DMA0_RX_FRAMEOFFSET 30 | 161 | #define B43_DMA0_RX_FRAMEOFFSET 30 |
| 161 | 162 | ||
| 162 | /* DMA engine tuning knobs */ | 163 | /* DMA engine tuning knobs */ |
| @@ -246,12 +247,6 @@ struct b43_dmaring { | |||
| 246 | /* The QOS priority assigned to this ring. Only used for TX rings. | 247 | /* The QOS priority assigned to this ring. Only used for TX rings. |
| 247 | * This is the mac80211 "queue" value. */ | 248 | * This is the mac80211 "queue" value. */ |
| 248 | u8 queue_prio; | 249 | u8 queue_prio; |
| 249 | /* Pointers and size of the originally allocated and mapped memory | ||
| 250 | * region for the descriptor ring. */ | ||
| 251 | void *alloc_descbase; | ||
| 252 | dma_addr_t alloc_dmabase; | ||
| 253 | unsigned int alloc_descsize; | ||
| 254 | /* Pointer to our wireless device. */ | ||
| 255 | struct b43_wldev *dev; | 250 | struct b43_wldev *dev; |
| 256 | #ifdef CONFIG_B43_DEBUG | 251 | #ifdef CONFIG_B43_DEBUG |
| 257 | /* Maximum number of used slots. */ | 252 | /* Maximum number of used slots. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e413bd35bc41..234891d8cc10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
| @@ -681,19 +681,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
| 681 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | 681 | snr = rx_stats_sig_avg / rx_stats_noise_diff; |
| 682 | rx_status.noise = rx_status.signal - | 682 | rx_status.noise = rx_status.signal - |
| 683 | iwl3945_calc_db_from_ratio(snr); | 683 | iwl3945_calc_db_from_ratio(snr); |
| 684 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, | ||
| 685 | rx_status.noise); | ||
| 686 | |||
| 687 | /* If noise info not available, calculate signal quality indicator (%) | ||
| 688 | * using just the dBm signal level. */ | ||
| 689 | } else { | 684 | } else { |
| 690 | rx_status.noise = priv->last_rx_noise; | 685 | rx_status.noise = priv->last_rx_noise; |
| 691 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); | ||
| 692 | } | 686 | } |
| 693 | 687 | ||
| 694 | 688 | ||
| 695 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", | 689 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", |
| 696 | rx_status.signal, rx_status.noise, rx_status.qual, | 690 | rx_status.signal, rx_status.noise, |
| 697 | rx_stats_sig_avg, rx_stats_noise_diff); | 691 | rx_stats_sig_avg, rx_stats_noise_diff); |
| 698 | 692 | ||
| 699 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 693 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ecc23ec1f6a4..531fa125f5a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
| @@ -222,7 +222,6 @@ struct iwl3945_ibss_seq { | |||
| 222 | * | 222 | * |
| 223 | *****************************************************************************/ | 223 | *****************************************************************************/ |
| 224 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); | 224 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); |
| 225 | extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); | ||
| 226 | extern void iwl3945_rx_replenish(void *data); | 225 | extern void iwl3945_rx_replenish(void *data); |
| 227 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 226 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
| 228 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 227 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index fe511cbf012e..b93e49158196 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
| @@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { | |||
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | /* mbps, mcs */ | 152 | /* mbps, mcs */ |
| 153 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 153 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
| 154 | { "1", "BPSK DSSS"}, | 154 | { "1", "BPSK DSSS"}, |
| 155 | { "2", "QPSK DSSS"}, | 155 | { "2", "QPSK DSSS"}, |
| 156 | {"5.5", "BPSK CCK"}, | 156 | {"5.5", "BPSK CCK"}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f5c87e72660a..6f36b6e79f5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
| @@ -650,47 +650,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
| 650 | } | 650 | } |
| 651 | EXPORT_SYMBOL(iwl_reply_statistics); | 651 | EXPORT_SYMBOL(iwl_reply_statistics); |
| 652 | 652 | ||
| 653 | #define PERFECT_RSSI (-20) /* dBm */ | ||
| 654 | #define WORST_RSSI (-95) /* dBm */ | ||
| 655 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
| 656 | |||
| 657 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
| 658 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
| 659 | * about formulas used below. */ | ||
| 660 | static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
| 661 | { | ||
| 662 | int sig_qual; | ||
| 663 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
| 664 | |||
| 665 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
| 666 | * as indicator; formula is (signal dbm - noise dbm). | ||
| 667 | * SNR at or above 40 is a great signal (100%). | ||
| 668 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
| 669 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
| 670 | if (noise_dbm) { | ||
| 671 | if (rssi_dbm - noise_dbm >= 40) | ||
| 672 | return 100; | ||
| 673 | else if (rssi_dbm < noise_dbm) | ||
| 674 | return 0; | ||
| 675 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
| 676 | |||
| 677 | /* Else use just the signal level. | ||
| 678 | * This formula is a least squares fit of data points collected and | ||
| 679 | * compared with a reference system that had a percentage (%) display | ||
| 680 | * for signal quality. */ | ||
| 681 | } else | ||
| 682 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
| 683 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
| 684 | (RSSI_RANGE * RSSI_RANGE); | ||
| 685 | |||
| 686 | if (sig_qual > 100) | ||
| 687 | sig_qual = 100; | ||
| 688 | else if (sig_qual < 1) | ||
| 689 | sig_qual = 0; | ||
| 690 | |||
| 691 | return sig_qual; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* Calc max signal level (dBm) among 3 possible receivers */ | 653 | /* Calc max signal level (dBm) among 3 possible receivers */ |
| 695 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | 654 | static inline int iwl_calc_rssi(struct iwl_priv *priv, |
| 696 | struct iwl_rx_phy_res *rx_resp) | 655 | struct iwl_rx_phy_res *rx_resp) |
| @@ -1101,11 +1060,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
| 1101 | if (iwl_is_associated(priv) && | 1060 | if (iwl_is_associated(priv) && |
| 1102 | !test_bit(STATUS_SCANNING, &priv->status)) { | 1061 | !test_bit(STATUS_SCANNING, &priv->status)) { |
| 1103 | rx_status.noise = priv->last_rx_noise; | 1062 | rx_status.noise = priv->last_rx_noise; |
| 1104 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, | ||
| 1105 | rx_status.noise); | ||
| 1106 | } else { | 1063 | } else { |
| 1107 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 1064 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
| 1108 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); | ||
| 1109 | } | 1065 | } |
| 1110 | 1066 | ||
| 1111 | /* Reset beacon noise level if not associated. */ | 1067 | /* Reset beacon noise level if not associated. */ |
| @@ -1118,8 +1074,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
| 1118 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | 1074 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); |
| 1119 | #endif | 1075 | #endif |
| 1120 | iwl_dbg_log_rx_data_frame(priv, len, header); | 1076 | iwl_dbg_log_rx_data_frame(priv, len, header); |
| 1121 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", | 1077 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", |
| 1122 | rx_status.signal, rx_status.noise, rx_status.qual, | 1078 | rx_status.signal, rx_status.noise, |
| 1123 | (unsigned long long)rx_status.mactime); | 1079 | (unsigned long long)rx_status.mactime); |
| 1124 | 1080 | ||
| 1125 | /* | 1081 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e5d8fa38432e..f8e4e4b18d02 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
| @@ -1299,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) | |||
| 1299 | return (int)ratio2dB[sig_ratio]; | 1299 | return (int)ratio2dB[sig_ratio]; |
| 1300 | } | 1300 | } |
| 1301 | 1301 | ||
| 1302 | #define PERFECT_RSSI (-20) /* dBm */ | ||
| 1303 | #define WORST_RSSI (-95) /* dBm */ | ||
| 1304 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
| 1305 | |||
| 1306 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
| 1307 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
| 1308 | * about formulas used below. */ | ||
| 1309 | int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
| 1310 | { | ||
| 1311 | int sig_qual; | ||
| 1312 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
| 1313 | |||
| 1314 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
| 1315 | * as indicator; formula is (signal dbm - noise dbm). | ||
| 1316 | * SNR at or above 40 is a great signal (100%). | ||
| 1317 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
| 1318 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
| 1319 | if (noise_dbm) { | ||
| 1320 | if (rssi_dbm - noise_dbm >= 40) | ||
| 1321 | return 100; | ||
| 1322 | else if (rssi_dbm < noise_dbm) | ||
| 1323 | return 0; | ||
| 1324 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
| 1325 | |||
| 1326 | /* Else use just the signal level. | ||
| 1327 | * This formula is a least squares fit of data points collected and | ||
| 1328 | * compared with a reference system that had a percentage (%) display | ||
| 1329 | * for signal quality. */ | ||
| 1330 | } else | ||
| 1331 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
| 1332 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
| 1333 | (RSSI_RANGE * RSSI_RANGE); | ||
| 1334 | |||
| 1335 | if (sig_qual > 100) | ||
| 1336 | sig_qual = 100; | ||
| 1337 | else if (sig_qual < 1) | ||
| 1338 | sig_qual = 0; | ||
| 1339 | |||
| 1340 | return sig_qual; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | /** | 1302 | /** |
| 1344 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode | 1303 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode |
| 1345 | * | 1304 | * |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79ffa3b98d73..842811142bef 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
| @@ -268,7 +268,7 @@ struct iwm_priv { | |||
| 268 | 268 | ||
| 269 | struct sk_buff_head rx_list; | 269 | struct sk_buff_head rx_list; |
| 270 | struct list_head rx_tickets; | 270 | struct list_head rx_tickets; |
| 271 | struct list_head rx_packets[IWM_RX_ID_HASH]; | 271 | struct list_head rx_packets[IWM_RX_ID_HASH + 1]; |
| 272 | struct workqueue_struct *rx_wq; | 272 | struct workqueue_struct *rx_wq; |
| 273 | struct work_struct rx_worker; | 273 | struct work_struct rx_worker; |
| 274 | 274 | ||
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index c6a6c042b82f..b0b1c7841500 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
| @@ -567,11 +567,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) | |||
| 567 | chan_count = lbs_scan_create_channel_list(priv, chan_list); | 567 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
| 568 | 568 | ||
| 569 | netif_stop_queue(priv->dev); | 569 | netif_stop_queue(priv->dev); |
| 570 | netif_carrier_off(priv->dev); | 570 | if (priv->mesh_dev) |
| 571 | if (priv->mesh_dev) { | ||
| 572 | netif_stop_queue(priv->mesh_dev); | 571 | netif_stop_queue(priv->mesh_dev); |
| 573 | netif_carrier_off(priv->mesh_dev); | ||
| 574 | } | ||
| 575 | 572 | ||
| 576 | /* Prepare to continue an interrupted scan */ | 573 | /* Prepare to continue an interrupted scan */ |
| 577 | lbs_deb_scan("chan_count %d, scan_channel %d\n", | 574 | lbs_deb_scan("chan_count %d, scan_channel %d\n", |
| @@ -635,16 +632,13 @@ out2: | |||
| 635 | priv->scan_channel = 0; | 632 | priv->scan_channel = 0; |
| 636 | 633 | ||
| 637 | out: | 634 | out: |
| 638 | if (priv->connect_status == LBS_CONNECTED) { | 635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) |
| 639 | netif_carrier_on(priv->dev); | 636 | netif_wake_queue(priv->dev); |
| 640 | if (!priv->tx_pending_len) | 637 | |
| 641 | netif_wake_queue(priv->dev); | 638 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && |
| 642 | } | 639 | !priv->tx_pending_len) |
| 643 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { | 640 | netif_wake_queue(priv->mesh_dev); |
| 644 | netif_carrier_on(priv->mesh_dev); | 641 | |
| 645 | if (!priv->tx_pending_len) | ||
| 646 | netif_wake_queue(priv->mesh_dev); | ||
| 647 | } | ||
| 648 | kfree(chan_list); | 642 | kfree(chan_list); |
| 649 | 643 | ||
| 650 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 644 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 019431d2f8a9..26a1abd5bb03 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
| @@ -495,7 +495,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) | |||
| 495 | stats.band = IEEE80211_BAND_2GHZ; | 495 | stats.band = IEEE80211_BAND_2GHZ; |
| 496 | stats.signal = prxpd->snr; | 496 | stats.signal = prxpd->snr; |
| 497 | stats.noise = prxpd->nf; | 497 | stats.noise = prxpd->nf; |
| 498 | stats.qual = prxpd->snr - prxpd->nf; | ||
| 499 | /* Marvell rate index has a hole at value 4 */ | 498 | /* Marvell rate index has a hole at value 4 */ |
| 500 | if (prxpd->rx_rate > 4) | 499 | if (prxpd->rx_rate > 4) |
| 501 | --prxpd->rx_rate; | 500 | --prxpd->rx_rate; |
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 7698fdd6a3a2..31ca241f7753 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #define MAX_RID_LEN 1024 | 23 | #define MAX_RID_LEN 1024 |
| 24 | 24 | ||
| 25 | /* Helper routine to record keys | 25 | /* Helper routine to record keys |
| 26 | * Do not call from interrupt context */ | 26 | * It is called under orinoco_lock so it may not sleep */ |
| 27 | static int orinoco_set_key(struct orinoco_private *priv, int index, | 27 | static int orinoco_set_key(struct orinoco_private *priv, int index, |
| 28 | enum orinoco_alg alg, const u8 *key, int key_len, | 28 | enum orinoco_alg alg, const u8 *key, int key_len, |
| 29 | const u8 *seq, int seq_len) | 29 | const u8 *seq, int seq_len) |
| @@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, | |||
| 32 | kzfree(priv->keys[index].seq); | 32 | kzfree(priv->keys[index].seq); |
| 33 | 33 | ||
| 34 | if (key_len) { | 34 | if (key_len) { |
| 35 | priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); | 35 | priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); |
| 36 | if (!priv->keys[index].key) | 36 | if (!priv->keys[index].key) |
| 37 | goto nomem; | 37 | goto nomem; |
| 38 | } else | 38 | } else |
| 39 | priv->keys[index].key = NULL; | 39 | priv->keys[index].key = NULL; |
| 40 | 40 | ||
| 41 | if (seq_len) { | 41 | if (seq_len) { |
| 42 | priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); | 42 | priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); |
| 43 | if (!priv->keys[index].seq) | 43 | if (!priv->keys[index].seq) |
| 44 | goto free_key; | 44 | goto free_key; |
| 45 | } else | 45 | } else |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index af85d18cdbe7..ab95346cf6a3 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
| @@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 922 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | 922 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, |
| 923 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | 923 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, |
| 924 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, | 924 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, |
| 925 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
| 925 | /* Logitec */ | 926 | /* Logitec */ |
| 926 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | 927 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, |
| 927 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | 928 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index a1a3dd15c664..8a40a1439984 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
| @@ -132,7 +132,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
| 132 | 132 | ||
| 133 | rx_status.antenna = (flags2 >> 15) & 1; | 133 | rx_status.antenna = (flags2 >> 15) & 1; |
| 134 | /* TODO: improve signal/rssi reporting */ | 134 | /* TODO: improve signal/rssi reporting */ |
| 135 | rx_status.qual = flags2 & 0xFF; | ||
| 136 | rx_status.signal = (flags2 >> 8) & 0x7F; | 135 | rx_status.signal = (flags2 >> 8) & 0x7F; |
| 137 | /* XXX: is this correct? */ | 136 | /* XXX: is this correct? */ |
| 138 | rx_status.rate_idx = (flags >> 20) & 0xF; | 137 | rx_status.rate_idx = (flags >> 20) & 0xF; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 2e733e7bdfd4..28a808674080 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
| @@ -256,7 +256,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
| 256 | } | 256 | } |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | if (loop >= INIT_LOOP) { | 259 | if (loop > INIT_LOOP) { |
| 260 | wl1251_error("timeout waiting for the hardware to " | 260 | wl1251_error("timeout waiting for the hardware to " |
| 261 | "complete initialization"); | 261 | "complete initialization"); |
| 262 | return -EIO; | 262 | return -EIO; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 886a9bc39cc1..c3385b3d246c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
| @@ -777,7 +777,7 @@ out: | |||
| 777 | return ret; | 777 | return ret; |
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | static int wl1271_build_basic_rates(char *rates, u8 band) | 780 | static int wl1271_build_basic_rates(u8 *rates, u8 band) |
| 781 | { | 781 | { |
| 782 | u8 index = 0; | 782 | u8 index = 0; |
| 783 | 783 | ||
| @@ -804,7 +804,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band) | |||
| 804 | return index; | 804 | return index; |
| 805 | } | 805 | } |
| 806 | 806 | ||
| 807 | static int wl1271_build_extended_rates(char *rates, u8 band) | 807 | static int wl1271_build_extended_rates(u8 *rates, u8 band) |
| 808 | { | 808 | { |
| 809 | u8 index = 0; | 809 | u8 index = 0; |
| 810 | 810 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index dfa1b9bc22c8..7ca95c414fa8 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
| @@ -1325,151 +1325,11 @@ int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | |||
| 1325 | return r; | 1325 | return r; |
| 1326 | } | 1326 | } |
| 1327 | 1327 | ||
| 1328 | static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size) | ||
| 1329 | { | ||
| 1330 | static const u16 constants[] = { | ||
| 1331 | 715, 655, 585, 540, 470, 410, 360, 315, | ||
| 1332 | 270, 235, 205, 175, 150, 125, 105, 85, | ||
| 1333 | 65, 50, 40, 25, 15 | ||
| 1334 | }; | ||
| 1335 | |||
| 1336 | int i; | ||
| 1337 | u32 x; | ||
| 1338 | |||
| 1339 | /* It seems that their quality parameter is somehow per signal | ||
| 1340 | * and is now transferred per bit. | ||
| 1341 | */ | ||
| 1342 | switch (zd_rate) { | ||
| 1343 | case ZD_OFDM_RATE_6M: | ||
| 1344 | case ZD_OFDM_RATE_12M: | ||
| 1345 | case ZD_OFDM_RATE_24M: | ||
| 1346 | size *= 2; | ||
| 1347 | break; | ||
| 1348 | case ZD_OFDM_RATE_9M: | ||
| 1349 | case ZD_OFDM_RATE_18M: | ||
| 1350 | case ZD_OFDM_RATE_36M: | ||
| 1351 | case ZD_OFDM_RATE_54M: | ||
| 1352 | size *= 4; | ||
| 1353 | size /= 3; | ||
| 1354 | break; | ||
| 1355 | case ZD_OFDM_RATE_48M: | ||
| 1356 | size *= 3; | ||
| 1357 | size /= 2; | ||
| 1358 | break; | ||
| 1359 | default: | ||
| 1360 | return -EINVAL; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | x = (10000 * status_quality)/size; | ||
| 1364 | for (i = 0; i < ARRAY_SIZE(constants); i++) { | ||
| 1365 | if (x > constants[i]) | ||
| 1366 | break; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | switch (zd_rate) { | ||
| 1370 | case ZD_OFDM_RATE_6M: | ||
| 1371 | case ZD_OFDM_RATE_9M: | ||
| 1372 | i += 3; | ||
| 1373 | break; | ||
| 1374 | case ZD_OFDM_RATE_12M: | ||
| 1375 | case ZD_OFDM_RATE_18M: | ||
| 1376 | i += 5; | ||
| 1377 | break; | ||
| 1378 | case ZD_OFDM_RATE_24M: | ||
| 1379 | case ZD_OFDM_RATE_36M: | ||
| 1380 | i += 9; | ||
| 1381 | break; | ||
| 1382 | case ZD_OFDM_RATE_48M: | ||
| 1383 | case ZD_OFDM_RATE_54M: | ||
| 1384 | i += 15; | ||
| 1385 | break; | ||
| 1386 | default: | ||
| 1387 | return -EINVAL; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | return i; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size) | ||
| 1394 | { | ||
| 1395 | int r; | ||
| 1396 | |||
| 1397 | r = ofdm_qual_db(status_quality, zd_rate, size); | ||
| 1398 | ZD_ASSERT(r >= 0); | ||
| 1399 | if (r < 0) | ||
| 1400 | r = 0; | ||
| 1401 | |||
| 1402 | r = (r * 100)/29; | ||
| 1403 | return r <= 100 ? r : 100; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static unsigned int log10times100(unsigned int x) | ||
| 1407 | { | ||
| 1408 | static const u8 log10[] = { | ||
| 1409 | 0, | ||
| 1410 | 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, | ||
| 1411 | 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, | ||
| 1412 | 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, | ||
| 1413 | 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, | ||
| 1414 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, | ||
| 1415 | 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, | ||
| 1416 | 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, | ||
| 1417 | 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, | ||
| 1418 | 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, | ||
| 1419 | 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, | ||
| 1420 | 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, | ||
| 1421 | 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, | ||
| 1422 | 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, | ||
| 1423 | 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, | ||
| 1424 | 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, | ||
| 1425 | 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, | ||
| 1426 | 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, | ||
| 1427 | 223, 223, 223, 224, 224, 224, 224, | ||
| 1428 | }; | ||
| 1429 | |||
| 1430 | return x < ARRAY_SIZE(log10) ? log10[x] : 225; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | enum { | ||
| 1434 | MAX_CCK_EVM_DB = 45, | ||
| 1435 | }; | ||
| 1436 | |||
| 1437 | static int cck_evm_db(u8 status_quality) | ||
| 1438 | { | ||
| 1439 | return (20 * log10times100(status_quality)) / 100; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | static int cck_snr_db(u8 status_quality) | ||
| 1443 | { | ||
| 1444 | int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); | ||
| 1445 | ZD_ASSERT(r >= 0); | ||
| 1446 | return r; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | static int cck_qual_percent(u8 status_quality) | ||
| 1450 | { | ||
| 1451 | int r; | ||
| 1452 | |||
| 1453 | r = cck_snr_db(status_quality); | ||
| 1454 | r = (100*r)/17; | ||
| 1455 | return r <= 100 ? r : 100; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) | 1328 | static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) |
| 1459 | { | 1329 | { |
| 1460 | return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); | 1330 | return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); |
| 1461 | } | 1331 | } |
| 1462 | 1332 | ||
| 1463 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
| 1464 | const struct rx_status *status) | ||
| 1465 | { | ||
| 1466 | return (status->frame_status&ZD_RX_OFDM) ? | ||
| 1467 | ofdm_qual_percent(status->signal_quality_ofdm, | ||
| 1468 | zd_rate_from_ofdm_plcp_header(rx_frame), | ||
| 1469 | size) : | ||
| 1470 | cck_qual_percent(status->signal_quality_cck); | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | /** | 1333 | /** |
| 1474 | * zd_rx_rate - report zd-rate | 1334 | * zd_rx_rate - report zd-rate |
| 1475 | * @rx_frame - received frame | 1335 | * @rx_frame - received frame |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 9fd8f3508d66..f8bbf7d302ae 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
| @@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) | |||
| 929 | 929 | ||
| 930 | struct rx_status; | 930 | struct rx_status; |
| 931 | 931 | ||
| 932 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
| 933 | const struct rx_status *status); | ||
| 934 | |||
| 935 | u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); | 932 | u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); |
| 936 | 933 | ||
| 937 | struct zd_mc_hash { | 934 | struct zd_mc_hash { |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index cf51e8f8174b..8ebf5c33955d 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
| @@ -828,9 +828,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
| 828 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; | 828 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; |
| 829 | stats.band = IEEE80211_BAND_2GHZ; | 829 | stats.band = IEEE80211_BAND_2GHZ; |
| 830 | stats.signal = status->signal_strength; | 830 | stats.signal = status->signal_strength; |
| 831 | stats.qual = zd_rx_qual_percent(buffer, | ||
| 832 | length - sizeof(struct rx_status), | ||
| 833 | status); | ||
| 834 | 831 | ||
| 835 | rate = zd_rx_rate(buffer, status); | 832 | rate = zd_rx_rate(buffer, status); |
| 836 | 833 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 538d6b761887..0bf369752274 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -547,7 +547,6 @@ enum mac80211_rx_flags { | |||
| 547 | * unspecified depending on the hardware capabilities flags | 547 | * unspecified depending on the hardware capabilities flags |
| 548 | * @IEEE80211_HW_SIGNAL_* | 548 | * @IEEE80211_HW_SIGNAL_* |
| 549 | * @noise: noise when receiving this frame, in dBm. | 549 | * @noise: noise when receiving this frame, in dBm. |
| 550 | * @qual: overall signal quality indication, in percent (0-100). | ||
| 551 | * @antenna: antenna used | 550 | * @antenna: antenna used |
| 552 | * @rate_idx: index of data rate into band's supported rates or MCS index if | 551 | * @rate_idx: index of data rate into band's supported rates or MCS index if |
| 553 | * HT rates are use (RX_FLAG_HT) | 552 | * HT rates are use (RX_FLAG_HT) |
| @@ -559,7 +558,6 @@ struct ieee80211_rx_status { | |||
| 559 | int freq; | 558 | int freq; |
| 560 | int signal; | 559 | int signal; |
| 561 | int noise; | 560 | int noise; |
| 562 | int __deprecated qual; | ||
| 563 | int antenna; | 561 | int antenna; |
| 564 | int rate_idx; | 562 | int rate_idx; |
| 565 | int flag; | 563 | int flag; |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 10d13856f86c..1f2db647bb5c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -382,6 +382,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
| 382 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 382 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
| 383 | u8 *bssid,u8 *addr, u32 supp_rates) | 383 | u8 *bssid,u8 *addr, u32 supp_rates) |
| 384 | { | 384 | { |
| 385 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
| 385 | struct ieee80211_local *local = sdata->local; | 386 | struct ieee80211_local *local = sdata->local; |
| 386 | struct sta_info *sta; | 387 | struct sta_info *sta; |
| 387 | int band = local->hw.conf.channel->band; | 388 | int band = local->hw.conf.channel->band; |
| @@ -397,6 +398,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
| 397 | return NULL; | 398 | return NULL; |
| 398 | } | 399 | } |
| 399 | 400 | ||
| 401 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) | ||
| 402 | return NULL; | ||
| 403 | |||
| 400 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) | 404 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) |
| 401 | return NULL; | 405 | return NULL; |
| 402 | 406 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8834cc93c716..27ceaefd7bc8 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1419,6 +1419,10 @@ static bool need_dynamic_ps(struct ieee80211_local *local) | |||
| 1419 | if (!local->ps_sdata) | 1419 | if (!local->ps_sdata) |
| 1420 | return false; | 1420 | return false; |
| 1421 | 1421 | ||
| 1422 | /* No point if we're going to suspend */ | ||
| 1423 | if (local->quiescing) | ||
| 1424 | return false; | ||
| 1425 | |||
| 1422 | return true; | 1426 | return true; |
| 1423 | } | 1427 | } |
| 1424 | 1428 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 78a6e924c7e1..dc76267e436e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -1039,7 +1039,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1039 | 1039 | ||
| 1040 | /* restart hardware */ | 1040 | /* restart hardware */ |
| 1041 | if (local->open_count) { | 1041 | if (local->open_count) { |
| 1042 | /* | ||
| 1043 | * Upon resume hardware can sometimes be goofy due to | ||
| 1044 | * various platform / driver / bus issues, so restarting | ||
| 1045 | * the device may at times not work immediately. Propagate | ||
| 1046 | * the error. | ||
| 1047 | */ | ||
| 1042 | res = drv_start(local); | 1048 | res = drv_start(local); |
| 1049 | if (res) { | ||
| 1050 | WARN(local->suspended, "Harware became unavailable " | ||
| 1051 | "upon resume. This is could be a software issue" | ||
| 1052 | "prior to suspend or a harware issue\n"); | ||
| 1053 | return res; | ||
| 1054 | } | ||
| 1043 | 1055 | ||
| 1044 | ieee80211_led_radio(local, true); | 1056 | ieee80211_led_radio(local, true); |
| 1045 | } | 1057 | } |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1001db4912f7..82e6002c8d67 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
| @@ -93,7 +93,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
| 93 | } | 93 | } |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | WARN_ON(!bss); | 96 | /* |
| 97 | * We might be coming here because the driver reported | ||
| 98 | * a successful association at the same time as the | ||
| 99 | * user requested a deauth. In that case, we will have | ||
| 100 | * removed the BSS from the auth_bsses list due to the | ||
| 101 | * deauth request when the assoc response makes it. If | ||
| 102 | * the two code paths acquire the lock the other way | ||
| 103 | * around, that's just the standard situation of a | ||
| 104 | * deauth being requested while connected. | ||
| 105 | */ | ||
| 106 | if (!bss) | ||
| 107 | goto out; | ||
| 97 | } else if (wdev->conn) { | 108 | } else if (wdev->conn) { |
| 98 | cfg80211_sme_failed_assoc(wdev); | 109 | cfg80211_sme_failed_assoc(wdev); |
| 99 | /* | 110 | /* |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 12dfa62aad18..0c2cbbebca95 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -601,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
| 601 | struct cfg80211_registered_device *rdev; | 601 | struct cfg80211_registered_device *rdev; |
| 602 | struct wiphy *wiphy; | 602 | struct wiphy *wiphy; |
| 603 | struct iw_scan_req *wreq = NULL; | 603 | struct iw_scan_req *wreq = NULL; |
| 604 | struct cfg80211_scan_request *creq; | 604 | struct cfg80211_scan_request *creq = NULL; |
| 605 | int i, err, n_channels = 0; | 605 | int i, err, n_channels = 0; |
| 606 | enum ieee80211_band band; | 606 | enum ieee80211_band band; |
| 607 | 607 | ||
| @@ -694,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
| 694 | /* translate "Scan for SSID" request */ | 694 | /* translate "Scan for SSID" request */ |
| 695 | if (wreq) { | 695 | if (wreq) { |
| 696 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 696 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
| 697 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) | 697 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { |
| 698 | return -EINVAL; | 698 | err = -EINVAL; |
| 699 | goto out; | ||
| 700 | } | ||
| 699 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); | 701 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); |
| 700 | creq->ssids[0].ssid_len = wreq->essid_len; | 702 | creq->ssids[0].ssid_len = wreq->essid_len; |
| 701 | } | 703 | } |
| @@ -707,12 +709,15 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
| 707 | err = rdev->ops->scan(wiphy, dev, creq); | 709 | err = rdev->ops->scan(wiphy, dev, creq); |
| 708 | if (err) { | 710 | if (err) { |
| 709 | rdev->scan_req = NULL; | 711 | rdev->scan_req = NULL; |
| 710 | kfree(creq); | 712 | /* creq will be freed below */ |
| 711 | } else { | 713 | } else { |
| 712 | nl80211_send_scan_start(rdev, dev); | 714 | nl80211_send_scan_start(rdev, dev); |
| 715 | /* creq now owned by driver */ | ||
| 716 | creq = NULL; | ||
| 713 | dev_hold(dev); | 717 | dev_hold(dev); |
| 714 | } | 718 | } |
| 715 | out: | 719 | out: |
| 720 | kfree(creq); | ||
| 716 | cfg80211_unlock_rdev(rdev); | 721 | cfg80211_unlock_rdev(rdev); |
| 717 | return err; | 722 | return err; |
| 718 | } | 723 | } |
