diff options
author | David S. Miller <davem@davemloft.net> | 2010-06-11 14:34:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-11 14:34:06 -0400 |
commit | 14599f1e341ee219abdd15f4eee5872d6f2d29f1 (patch) | |
tree | 3875181429010e58416ab34e6c06ef42de52e756 /drivers/net/wireless/iwlwifi | |
parent | d8d1f30b95a635dbd610dcc5eb641aca8f4768cf (diff) | |
parent | 832c10fd733893f86c63bde1c65b005d5a2fe346 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
drivers/net/wireless/wl12xx/wl1271.h
drivers/net/wireless/wl12xx/wl1271_cmd.h
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
27 files changed, 1666 insertions, 1089 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index dc8ed152766..6491e27baac 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -30,9 +30,11 @@ config IWLWIFI_DEBUG | |||
30 | 30 | ||
31 | config IWLWIFI_DEBUGFS | 31 | config IWLWIFI_DEBUGFS |
32 | bool "iwlagn debugfs support" | 32 | bool "iwlagn debugfs support" |
33 | depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS | 33 | depends on IWLWIFI && MAC80211_DEBUGFS |
34 | ---help--- | 34 | ---help--- |
35 | Enable creation of debugfs files for the iwlwifi drivers. | 35 | Enable creation of debugfs files for the iwlwifi drivers. This |
36 | is a low-impact option that allows getting insight into the | ||
37 | driver's state at runtime. | ||
36 | 38 | ||
37 | config IWLWIFI_DEVICE_TRACING | 39 | config IWLWIFI_DEVICE_TRACING |
38 | bool "iwlwifi device access tracing" | 40 | bool "iwlwifi device access tracing" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 6be2992f8f2..dba91e0233b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -158,6 +158,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
158 | BIT(IWL_CALIB_TX_IQ_PERD) | | 158 | BIT(IWL_CALIB_TX_IQ_PERD) | |
159 | BIT(IWL_CALIB_BASE_BAND); | 159 | BIT(IWL_CALIB_BASE_BAND); |
160 | 160 | ||
161 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
162 | |||
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c index 6a9c64a50e3..ef0835b01b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c | |||
@@ -28,6 +28,28 @@ | |||
28 | 28 | ||
29 | #include "iwl-3945-debugfs.h" | 29 | #include "iwl-3945-debugfs.h" |
30 | 30 | ||
31 | |||
32 | static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
33 | { | ||
34 | int p = 0; | ||
35 | |||
36 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
37 | le32_to_cpu(priv->_3945.statistics.flag)); | ||
38 | if (le32_to_cpu(priv->_3945.statistics.flag) & | ||
39 | UCODE_STATISTICS_CLEAR_MSK) | ||
40 | p += scnprintf(buf + p, bufsz - p, | ||
41 | "\tStatistics have been cleared\n"); | ||
42 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
43 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
44 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
45 | ? "2.4 GHz" : "5.2 GHz"); | ||
46 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
47 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
48 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
49 | ? "enabled" : "disabled"); | ||
50 | return p; | ||
51 | } | ||
52 | |||
31 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | 53 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, |
32 | char __user *user_buf, | 54 | char __user *user_buf, |
33 | size_t count, loff_t *ppos) | 55 | size_t count, loff_t *ppos) |
@@ -70,7 +92,7 @@ ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | |||
70 | max_cck = &priv->_3945.max_delta.rx.cck; | 92 | max_cck = &priv->_3945.max_delta.rx.cck; |
71 | max_general = &priv->_3945.max_delta.rx.general; | 93 | max_general = &priv->_3945.max_delta.rx.general; |
72 | 94 | ||
73 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 95 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
74 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 96 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
75 | "acumulative delta max\n", | 97 | "acumulative delta max\n", |
76 | "Statistics_Rx - OFDM:"); | 98 | "Statistics_Rx - OFDM:"); |
@@ -331,7 +353,7 @@ ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | |||
331 | accum_tx = &priv->_3945.accum_statistics.tx; | 353 | accum_tx = &priv->_3945.accum_statistics.tx; |
332 | delta_tx = &priv->_3945.delta_statistics.tx; | 354 | delta_tx = &priv->_3945.delta_statistics.tx; |
333 | max_tx = &priv->_3945.max_delta.tx; | 355 | max_tx = &priv->_3945.max_delta.tx; |
334 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 356 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
335 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 357 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
336 | "acumulative delta max\n", | 358 | "acumulative delta max\n", |
337 | "Statistics_Tx:"); | 359 | "Statistics_Tx:"); |
@@ -438,7 +460,7 @@ ssize_t iwl3945_ucode_general_stats_read(struct file *file, | |||
438 | accum_div = &priv->_3945.accum_statistics.general.div; | 460 | accum_div = &priv->_3945.accum_statistics.general.div; |
439 | delta_div = &priv->_3945.delta_statistics.general.div; | 461 | delta_div = &priv->_3945.delta_statistics.general.div; |
440 | max_div = &priv->_3945.max_delta.general.div; | 462 | max_div = &priv->_3945.max_delta.general.div; |
441 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 463 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
442 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 464 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
443 | "acumulative delta max\n", | 465 | "acumulative delta max\n", |
444 | "Statistics_General:"); | 466 | "Statistics_General:"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 068f7f8435c..0fa1d51c9c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -279,8 +279,8 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
279 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 279 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
280 | 280 | ||
281 | tx_info = &txq->txb[txq->q.read_ptr]; | 281 | tx_info = &txq->txb[txq->q.read_ptr]; |
282 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); | 282 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); |
283 | tx_info->skb[0] = NULL; | 283 | tx_info->skb = NULL; |
284 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 284 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
285 | } | 285 | } |
286 | 286 | ||
@@ -315,7 +315,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
315 | return; | 315 | return; |
316 | } | 316 | } |
317 | 317 | ||
318 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 318 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
319 | ieee80211_tx_info_clear_status(info); | 319 | ieee80211_tx_info_clear_status(info); |
320 | 320 | ||
321 | /* Fill the MRR chain with some info about on-chip retransmissions */ | 321 | /* Fill the MRR chain with some info about on-chip retransmissions */ |
@@ -352,7 +352,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
352 | * RX handler implementations | 352 | * RX handler implementations |
353 | * | 353 | * |
354 | *****************************************************************************/ | 354 | *****************************************************************************/ |
355 | #ifdef CONFIG_IWLWIFI_DEBUG | 355 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
356 | /* | 356 | /* |
357 | * based on the assumption of all statistics counter are in DWORD | 357 | * based on the assumption of all statistics counter are in DWORD |
358 | * FIXME: This function is for debugging, do not deal with | 358 | * FIXME: This function is for debugging, do not deal with |
@@ -460,7 +460,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
460 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 460 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
461 | (int)sizeof(struct iwl3945_notif_statistics), | 461 | (int)sizeof(struct iwl3945_notif_statistics), |
462 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 462 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
463 | #ifdef CONFIG_IWLWIFI_DEBUG | 463 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | 464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); |
465 | #endif | 465 | #endif |
466 | iwl_recover_from_statistics(priv, pkt); | 466 | iwl_recover_from_statistics(priv, pkt); |
@@ -475,7 +475,7 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, | |||
475 | __le32 *flag = (__le32 *)&pkt->u.raw; | 475 | __le32 *flag = (__le32 *)&pkt->u.raw; |
476 | 476 | ||
477 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { | 477 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { |
478 | #ifdef CONFIG_IWLWIFI_DEBUG | 478 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
479 | memset(&priv->_3945.accum_statistics, 0, | 479 | memset(&priv->_3945.accum_statistics, 0, |
480 | sizeof(struct iwl3945_notif_statistics)); | 480 | sizeof(struct iwl3945_notif_statistics)); |
481 | memset(&priv->_3945.delta_statistics, 0, | 481 | memset(&priv->_3945.delta_statistics, 0, |
@@ -494,158 +494,6 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, | |||
494 | * Misc. internal state and helper functions | 494 | * Misc. internal state and helper functions |
495 | * | 495 | * |
496 | ******************************************************************************/ | 496 | ******************************************************************************/ |
497 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
498 | |||
499 | /** | ||
500 | * iwl3945_report_frame - dump frame to syslog during debug sessions | ||
501 | * | ||
502 | * You may hack this function to show different aspects of received frames, | ||
503 | * including selective frame dumps. | ||
504 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
505 | */ | ||
506 | static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
507 | struct iwl_rx_packet *pkt, | ||
508 | struct ieee80211_hdr *header, int group100) | ||
509 | { | ||
510 | u32 to_us; | ||
511 | u32 print_summary = 0; | ||
512 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
513 | u32 hundred = 0; | ||
514 | u32 dataframe = 0; | ||
515 | __le16 fc; | ||
516 | u16 seq_ctl; | ||
517 | u16 channel; | ||
518 | u16 phy_flags; | ||
519 | u16 length; | ||
520 | u16 status; | ||
521 | u16 bcn_tmr; | ||
522 | u32 tsf_low; | ||
523 | u64 tsf; | ||
524 | u8 rssi; | ||
525 | u8 agc; | ||
526 | u16 sig_avg; | ||
527 | u16 noise_diff; | ||
528 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
529 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
530 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
531 | u8 *data = IWL_RX_DATA(pkt); | ||
532 | |||
533 | /* MAC header */ | ||
534 | fc = header->frame_control; | ||
535 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
536 | |||
537 | /* metadata */ | ||
538 | channel = le16_to_cpu(rx_hdr->channel); | ||
539 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
540 | length = le16_to_cpu(rx_hdr->len); | ||
541 | |||
542 | /* end-of-frame status and timestamp */ | ||
543 | status = le32_to_cpu(rx_end->status); | ||
544 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
545 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
546 | tsf = le64_to_cpu(rx_end->timestamp); | ||
547 | |||
548 | /* signal statistics */ | ||
549 | rssi = rx_stats->rssi; | ||
550 | agc = rx_stats->agc; | ||
551 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
552 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
553 | |||
554 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
555 | |||
556 | /* if data frame is to us and all is good, | ||
557 | * (optionally) print summary for only 1 out of every 100 */ | ||
558 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
559 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
560 | dataframe = 1; | ||
561 | if (!group100) | ||
562 | print_summary = 1; /* print each frame */ | ||
563 | else if (priv->framecnt_to_us < 100) { | ||
564 | priv->framecnt_to_us++; | ||
565 | print_summary = 0; | ||
566 | } else { | ||
567 | priv->framecnt_to_us = 0; | ||
568 | print_summary = 1; | ||
569 | hundred = 1; | ||
570 | } | ||
571 | } else { | ||
572 | /* print summary for all other frames */ | ||
573 | print_summary = 1; | ||
574 | } | ||
575 | |||
576 | if (print_summary) { | ||
577 | char *title; | ||
578 | int rate; | ||
579 | |||
580 | if (hundred) | ||
581 | title = "100Frames"; | ||
582 | else if (ieee80211_has_retry(fc)) | ||
583 | title = "Retry"; | ||
584 | else if (ieee80211_is_assoc_resp(fc)) | ||
585 | title = "AscRsp"; | ||
586 | else if (ieee80211_is_reassoc_resp(fc)) | ||
587 | title = "RasRsp"; | ||
588 | else if (ieee80211_is_probe_resp(fc)) { | ||
589 | title = "PrbRsp"; | ||
590 | print_dump = 1; /* dump frame contents */ | ||
591 | } else if (ieee80211_is_beacon(fc)) { | ||
592 | title = "Beacon"; | ||
593 | print_dump = 1; /* dump frame contents */ | ||
594 | } else if (ieee80211_is_atim(fc)) | ||
595 | title = "ATIM"; | ||
596 | else if (ieee80211_is_auth(fc)) | ||
597 | title = "Auth"; | ||
598 | else if (ieee80211_is_deauth(fc)) | ||
599 | title = "DeAuth"; | ||
600 | else if (ieee80211_is_disassoc(fc)) | ||
601 | title = "DisAssoc"; | ||
602 | else | ||
603 | title = "Frame"; | ||
604 | |||
605 | rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | ||
606 | if (rate == -1) | ||
607 | rate = 0; | ||
608 | else | ||
609 | rate = iwl3945_rates[rate].ieee / 2; | ||
610 | |||
611 | /* print frame summary. | ||
612 | * MAC addresses show just the last byte (for brevity), | ||
613 | * but you can hack it to show more, if you'd like to. */ | ||
614 | if (dataframe) | ||
615 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
616 | "len=%u, rssi=%d, chnl=%d, rate=%d,\n", | ||
617 | title, le16_to_cpu(fc), header->addr1[5], | ||
618 | length, rssi, channel, rate); | ||
619 | else { | ||
620 | /* src/dst addresses assume managed mode */ | ||
621 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, " | ||
622 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
623 | "phy=0x%02x, chnl=%d\n", | ||
624 | title, le16_to_cpu(fc), header->addr1[5], | ||
625 | header->addr3[5], rssi, | ||
626 | tsf_low - priv->scan_start_tsf, | ||
627 | phy_flags, channel); | ||
628 | } | ||
629 | } | ||
630 | if (print_dump) | ||
631 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | ||
632 | } | ||
633 | |||
634 | static void iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
635 | struct iwl_rx_packet *pkt, | ||
636 | struct ieee80211_hdr *header, int group100) | ||
637 | { | ||
638 | if (iwl_get_debug_level(priv) & IWL_DL_RX) | ||
639 | _iwl3945_dbg_report_frame(priv, pkt, header, group100); | ||
640 | } | ||
641 | |||
642 | #else | ||
643 | static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
644 | struct iwl_rx_packet *pkt, | ||
645 | struct ieee80211_hdr *header, int group100) | ||
646 | { | ||
647 | } | ||
648 | #endif | ||
649 | 497 | ||
650 | /* This is necessary only for a number of statistics, see the caller. */ | 498 | /* This is necessary only for a number of statistics, see the caller. */ |
651 | static int iwl3945_is_network_packet(struct iwl_priv *priv, | 499 | static int iwl3945_is_network_packet(struct iwl_priv *priv, |
@@ -777,8 +625,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
777 | rx_status.signal, rx_status.signal, | 625 | rx_status.signal, rx_status.signal, |
778 | rx_status.rate_idx); | 626 | rx_status.rate_idx); |
779 | 627 | ||
780 | /* Set "1" to report good data frames in groups of 100 */ | ||
781 | iwl3945_dbg_report_frame(priv, pkt, header, 1); | ||
782 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); | 628 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); |
783 | 629 | ||
784 | if (network_packet) { | 630 | if (network_packet) { |
@@ -850,25 +696,28 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
850 | /* Unmap tx_cmd */ | 696 | /* Unmap tx_cmd */ |
851 | if (counter) | 697 | if (counter) |
852 | pci_unmap_single(dev, | 698 | pci_unmap_single(dev, |
853 | pci_unmap_addr(&txq->meta[index], mapping), | 699 | dma_unmap_addr(&txq->meta[index], mapping), |
854 | pci_unmap_len(&txq->meta[index], len), | 700 | dma_unmap_len(&txq->meta[index], len), |
855 | PCI_DMA_TODEVICE); | 701 | PCI_DMA_TODEVICE); |
856 | 702 | ||
857 | /* unmap chunks if any */ | 703 | /* unmap chunks if any */ |
858 | 704 | ||
859 | for (i = 1; i < counter; i++) { | 705 | for (i = 1; i < counter; i++) |
860 | pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), | 706 | pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), |
861 | le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); | 707 | le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); |
862 | if (txq->txb[txq->q.read_ptr].skb[0]) { | 708 | |
863 | struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0]; | 709 | /* free SKB */ |
864 | if (txq->txb[txq->q.read_ptr].skb[0]) { | 710 | if (txq->txb) { |
865 | /* Can be called from interrupt context */ | 711 | struct sk_buff *skb; |
866 | dev_kfree_skb_any(skb); | 712 | |
867 | txq->txb[txq->q.read_ptr].skb[0] = NULL; | 713 | skb = txq->txb[txq->q.read_ptr].skb; |
868 | } | 714 | |
715 | /* can be called from irqs-disabled context */ | ||
716 | if (skb) { | ||
717 | dev_kfree_skb_any(skb); | ||
718 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
869 | } | 719 | } |
870 | } | 720 | } |
871 | return ; | ||
872 | } | 721 | } |
873 | 722 | ||
874 | /** | 723 | /** |
@@ -947,8 +796,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
947 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); | 796 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
948 | } | 797 | } |
949 | 798 | ||
950 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | 799 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate) |
951 | u16 tx_rate, u8 flags) | ||
952 | { | 800 | { |
953 | unsigned long flags_spin; | 801 | unsigned long flags_spin; |
954 | struct iwl_station_entry *station; | 802 | struct iwl_station_entry *station; |
@@ -962,10 +810,9 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | |||
962 | station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; | 810 | station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; |
963 | station->sta.rate_n_flags = cpu_to_le16(tx_rate); | 811 | station->sta.rate_n_flags = cpu_to_le16(tx_rate); |
964 | station->sta.mode = STA_CONTROL_MODIFY_MSK; | 812 | station->sta.mode = STA_CONTROL_MODIFY_MSK; |
965 | 813 | iwl_send_add_sta(priv, &station->sta, CMD_ASYNC); | |
966 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 814 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
967 | 815 | ||
968 | iwl_send_add_sta(priv, &station->sta, flags); | ||
969 | IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", | 816 | IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", |
970 | sta_id, tx_rate); | 817 | sta_id, tx_rate); |
971 | return sta_id; | 818 | return sta_id; |
@@ -2473,8 +2320,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, | |||
2473 | 2320 | ||
2474 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, | 2321 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, |
2475 | (priv->band == IEEE80211_BAND_5GHZ) ? | 2322 | (priv->band == IEEE80211_BAND_5GHZ) ? |
2476 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | 2323 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP); |
2477 | CMD_ASYNC); | ||
2478 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); | 2324 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); |
2479 | 2325 | ||
2480 | return 0; | 2326 | return 0; |
@@ -2590,6 +2436,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2590 | 2436 | ||
2591 | priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; | 2437 | priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; |
2592 | priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; | 2438 | priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; |
2439 | priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; | ||
2593 | 2440 | ||
2594 | return 0; | 2441 | return 0; |
2595 | } | 2442 | } |
@@ -2852,6 +2699,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2852 | .isr = iwl_isr_legacy, | 2699 | .isr = iwl_isr_legacy, |
2853 | .config_ap = iwl3945_config_ap, | 2700 | .config_ap = iwl3945_config_ap, |
2854 | .manage_ibss_station = iwl3945_manage_ibss_station, | 2701 | .manage_ibss_station = iwl3945_manage_ibss_station, |
2702 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
2855 | .check_plcp_health = iwl3945_good_plcp_health, | 2703 | .check_plcp_health = iwl3945_good_plcp_health, |
2856 | 2704 | ||
2857 | .debugfs_ops = { | 2705 | .debugfs_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d3afddae8d9..83e6a42ca2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | |||
346 | { | 346 | { |
347 | struct iwl_chain_noise_data *data = &(priv->chain_noise_data); | 347 | struct iwl_chain_noise_data *data = &(priv->chain_noise_data); |
348 | 348 | ||
349 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | 349 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
350 | iwl_is_associated(priv)) { | ||
350 | struct iwl_calib_diff_gain_cmd cmd; | 351 | struct iwl_calib_diff_gain_cmd cmd; |
351 | 352 | ||
353 | /* clear data for chain noise calibration algorithm */ | ||
354 | data->chain_noise_a = 0; | ||
355 | data->chain_noise_b = 0; | ||
356 | data->chain_noise_c = 0; | ||
357 | data->chain_signal_a = 0; | ||
358 | data->chain_signal_b = 0; | ||
359 | data->chain_signal_c = 0; | ||
360 | data->beacon_count = 0; | ||
361 | |||
352 | memset(&cmd, 0, sizeof(cmd)); | 362 | memset(&cmd, 0, sizeof(cmd)); |
353 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; | 363 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; |
354 | cmd.diff_gain_a = 0; | 364 | cmd.diff_gain_a = 0; |
@@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
419 | /* Mark so we run this algo only once! */ | 429 | /* Mark so we run this algo only once! */ |
420 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | 430 | data->state = IWL_CHAIN_NOISE_CALIBRATED; |
421 | } | 431 | } |
422 | data->chain_noise_a = 0; | ||
423 | data->chain_noise_b = 0; | ||
424 | data->chain_noise_c = 0; | ||
425 | data->chain_signal_a = 0; | ||
426 | data->chain_signal_b = 0; | ||
427 | data->chain_signal_c = 0; | ||
428 | data->beacon_count = 0; | ||
429 | } | 432 | } |
430 | 433 | ||
431 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 434 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
@@ -669,6 +672,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
669 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | 672 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
670 | 673 | ||
671 | priv->hw_params.sens = &iwl4965_sensitivity; | 674 | priv->hw_params.sens = &iwl4965_sensitivity; |
675 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
672 | 676 | ||
673 | return 0; | 677 | return 0; |
674 | } | 678 | } |
@@ -1441,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1441 | return ret; | 1445 | return ret; |
1442 | } | 1446 | } |
1443 | 1447 | ||
1444 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1448 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, |
1449 | struct ieee80211_channel_switch *ch_switch) | ||
1445 | { | 1450 | { |
1446 | int rc; | 1451 | int rc; |
1447 | u8 band = 0; | 1452 | u8 band = 0; |
@@ -1449,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1449 | u8 ctrl_chan_high = 0; | 1454 | u8 ctrl_chan_high = 0; |
1450 | struct iwl4965_channel_switch_cmd cmd; | 1455 | struct iwl4965_channel_switch_cmd cmd; |
1451 | const struct iwl_channel_info *ch_info; | 1456 | const struct iwl_channel_info *ch_info; |
1452 | 1457 | u32 switch_time_in_usec, ucode_switch_time; | |
1458 | u16 ch; | ||
1459 | u32 tsf_low; | ||
1460 | u8 switch_count; | ||
1461 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
1462 | struct ieee80211_vif *vif = priv->vif; | ||
1453 | band = priv->band == IEEE80211_BAND_2GHZ; | 1463 | band = priv->band == IEEE80211_BAND_2GHZ; |
1454 | 1464 | ||
1455 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
1456 | |||
1457 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); | 1465 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); |
1458 | 1466 | ||
1459 | if (is_ht40 && | 1467 | if (is_ht40 && |
@@ -1462,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1462 | 1470 | ||
1463 | cmd.band = band; | 1471 | cmd.band = band; |
1464 | cmd.expect_beacon = 0; | 1472 | cmd.expect_beacon = 0; |
1465 | cmd.channel = cpu_to_le16(channel); | 1473 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
1474 | cmd.channel = cpu_to_le16(ch); | ||
1466 | cmd.rxon_flags = priv->staging_rxon.flags; | 1475 | cmd.rxon_flags = priv->staging_rxon.flags; |
1467 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1468 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1477 | switch_count = ch_switch->count; |
1478 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
1479 | /* | ||
1480 | * calculate the ucode channel switch time | ||
1481 | * adding TSF as one of the factor for when to switch | ||
1482 | */ | ||
1483 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
1484 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
1485 | beacon_interval)) { | ||
1486 | switch_count -= (priv->ucode_beacon_time - | ||
1487 | tsf_low) / beacon_interval; | ||
1488 | } else | ||
1489 | switch_count = 0; | ||
1490 | } | ||
1491 | if (switch_count <= 1) | ||
1492 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
1493 | else { | ||
1494 | switch_time_in_usec = | ||
1495 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
1496 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
1497 | switch_time_in_usec, | ||
1498 | beacon_interval); | ||
1499 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
1500 | priv->ucode_beacon_time, | ||
1501 | ucode_switch_time, | ||
1502 | beacon_interval); | ||
1503 | } | ||
1504 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
1505 | cmd.switch_time); | ||
1506 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
1469 | if (ch_info) | 1507 | if (ch_info) |
1470 | cmd.expect_beacon = is_channel_radar(ch_info); | 1508 | cmd.expect_beacon = is_channel_radar(ch_info); |
1471 | else { | 1509 | else { |
1472 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 1510 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
1473 | priv->active_rxon.channel, channel); | 1511 | priv->active_rxon.channel, ch); |
1474 | return -EFAULT; | 1512 | return -EFAULT; |
1475 | } | 1513 | } |
1476 | 1514 | ||
1477 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, | 1515 | rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40, |
1478 | ctrl_chan_high, &cmd.tx_power); | 1516 | ctrl_chan_high, &cmd.tx_power); |
1479 | if (rc) { | 1517 | if (rc) { |
1480 | IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); | 1518 | IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); |
1481 | return rc; | 1519 | return rc; |
1482 | } | 1520 | } |
1483 | 1521 | ||
1484 | priv->switch_rxon.channel = cpu_to_le16(channel); | 1522 | priv->switch_rxon.channel = cmd.channel; |
1485 | priv->switch_rxon.switch_in_progress = true; | 1523 | priv->switch_rxon.switch_in_progress = true; |
1486 | 1524 | ||
1487 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1525 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); |
@@ -1870,7 +1908,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1870 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | 1908 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", |
1871 | agg->frame_count, agg->start_idx, idx); | 1909 | agg->frame_count, agg->start_idx, idx); |
1872 | 1910 | ||
1873 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1911 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); |
1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1912 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1913 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1876 | info->flags |= iwl_tx_status_to_mac80211(status); | 1914 | info->flags |= iwl_tx_status_to_mac80211(status); |
@@ -2026,6 +2064,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2026 | int sta_id; | 2064 | int sta_id; |
2027 | int freed; | 2065 | int freed; |
2028 | u8 *qc = NULL; | 2066 | u8 *qc = NULL; |
2067 | unsigned long flags; | ||
2029 | 2068 | ||
2030 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | 2069 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { |
2031 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | 2070 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " |
@@ -2035,7 +2074,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2035 | return; | 2074 | return; |
2036 | } | 2075 | } |
2037 | 2076 | ||
2038 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 2077 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
2039 | memset(&info->status, 0, sizeof(info->status)); | 2078 | memset(&info->status, 0, sizeof(info->status)); |
2040 | 2079 | ||
2041 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); | 2080 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); |
@@ -2050,10 +2089,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2050 | return; | 2089 | return; |
2051 | } | 2090 | } |
2052 | 2091 | ||
2092 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2053 | if (txq->sched_retry) { | 2093 | if (txq->sched_retry) { |
2054 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); | 2094 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); |
2055 | struct iwl_ht_agg *agg = NULL; | 2095 | struct iwl_ht_agg *agg = NULL; |
2056 | |||
2057 | WARN_ON(!qc); | 2096 | WARN_ON(!qc); |
2058 | 2097 | ||
2059 | agg = &priv->stations[sta_id].tid[tid].agg; | 2098 | agg = &priv->stations[sta_id].tid[tid].agg; |
@@ -2110,6 +2149,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2110 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | 2149 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
2111 | 2150 | ||
2112 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 2151 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
2152 | |||
2153 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2113 | } | 2154 | } |
2114 | 2155 | ||
2115 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2156 | static int iwl4965_calc_rssi(struct iwl_priv *priv, |
@@ -2285,7 +2326,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2285 | * Force use of chains B and C for scan RX on 5 GHz band | 2326 | * Force use of chains B and C for scan RX on 5 GHz band |
2286 | * because the device has off-channel reception on chain A. | 2327 | * because the device has off-channel reception on chain A. |
2287 | */ | 2328 | */ |
2288 | .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, | 2329 | .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, |
2289 | }; | 2330 | }; |
2290 | 2331 | ||
2291 | /* Module firmware */ | 2332 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a28af7eb67e..32710a801cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -208,6 +208,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
208 | BIT(IWL_CALIB_TX_IQ_PERD) | | 208 | BIT(IWL_CALIB_TX_IQ_PERD) | |
209 | BIT(IWL_CALIB_BASE_BAND); | 209 | BIT(IWL_CALIB_BASE_BAND); |
210 | 210 | ||
211 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
212 | |||
211 | return 0; | 213 | return 0; |
212 | } | 214 | } |
213 | 215 | ||
@@ -252,6 +254,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
252 | BIT(IWL_CALIB_TX_IQ) | | 254 | BIT(IWL_CALIB_TX_IQ) | |
253 | BIT(IWL_CALIB_BASE_BAND); | 255 | BIT(IWL_CALIB_BASE_BAND); |
254 | 256 | ||
257 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
258 | |||
255 | return 0; | 259 | return 0; |
256 | } | 260 | } |
257 | 261 | ||
@@ -267,33 +271,69 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
267 | iwl_tt_handler(priv); | 271 | iwl_tt_handler(priv); |
268 | } | 272 | } |
269 | 273 | ||
270 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 274 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, |
275 | struct ieee80211_channel_switch *ch_switch) | ||
271 | { | 276 | { |
272 | struct iwl5000_channel_switch_cmd cmd; | 277 | struct iwl5000_channel_switch_cmd cmd; |
273 | const struct iwl_channel_info *ch_info; | 278 | const struct iwl_channel_info *ch_info; |
279 | u32 switch_time_in_usec, ucode_switch_time; | ||
280 | u16 ch; | ||
281 | u32 tsf_low; | ||
282 | u8 switch_count; | ||
283 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
284 | struct ieee80211_vif *vif = priv->vif; | ||
274 | struct iwl_host_cmd hcmd = { | 285 | struct iwl_host_cmd hcmd = { |
275 | .id = REPLY_CHANNEL_SWITCH, | 286 | .id = REPLY_CHANNEL_SWITCH, |
276 | .len = sizeof(cmd), | 287 | .len = sizeof(cmd), |
277 | .flags = CMD_SIZE_HUGE, | 288 | .flags = CMD_SYNC, |
278 | .data = &cmd, | 289 | .data = &cmd, |
279 | }; | 290 | }; |
280 | 291 | ||
281 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
282 | priv->active_rxon.channel, channel); | ||
283 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 292 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
284 | cmd.channel = cpu_to_le16(channel); | 293 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
294 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
295 | priv->active_rxon.channel, ch); | ||
296 | cmd.channel = cpu_to_le16(ch); | ||
285 | cmd.rxon_flags = priv->staging_rxon.flags; | 297 | cmd.rxon_flags = priv->staging_rxon.flags; |
286 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 298 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
287 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 299 | switch_count = ch_switch->count; |
288 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 300 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
301 | /* | ||
302 | * calculate the ucode channel switch time | ||
303 | * adding TSF as one of the factor for when to switch | ||
304 | */ | ||
305 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
306 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
307 | beacon_interval)) { | ||
308 | switch_count -= (priv->ucode_beacon_time - | ||
309 | tsf_low) / beacon_interval; | ||
310 | } else | ||
311 | switch_count = 0; | ||
312 | } | ||
313 | if (switch_count <= 1) | ||
314 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
315 | else { | ||
316 | switch_time_in_usec = | ||
317 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
318 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
319 | switch_time_in_usec, | ||
320 | beacon_interval); | ||
321 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
322 | priv->ucode_beacon_time, | ||
323 | ucode_switch_time, | ||
324 | beacon_interval); | ||
325 | } | ||
326 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
327 | cmd.switch_time); | ||
328 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
289 | if (ch_info) | 329 | if (ch_info) |
290 | cmd.expect_beacon = is_channel_radar(ch_info); | 330 | cmd.expect_beacon = is_channel_radar(ch_info); |
291 | else { | 331 | else { |
292 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 332 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
293 | priv->active_rxon.channel, channel); | 333 | priv->active_rxon.channel, ch); |
294 | return -EFAULT; | 334 | return -EFAULT; |
295 | } | 335 | } |
296 | priv->switch_rxon.channel = cpu_to_le16(channel); | 336 | priv->switch_rxon.channel = cmd.channel; |
297 | priv->switch_rxon.switch_in_progress = true; | 337 | priv->switch_rxon.switch_in_progress = true; |
298 | 338 | ||
299 | return iwl_send_cmd_sync(priv, &hcmd); | 339 | return iwl_send_cmd_sync(priv, &hcmd); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9fbf54cd3e1..afdeec56b13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -71,6 +71,10 @@ | |||
71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" | 71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" |
72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) | 72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) |
73 | 73 | ||
74 | #define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-" | ||
75 | #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" | ||
76 | #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) | ||
77 | |||
74 | 78 | ||
75 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | 79 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) |
76 | { | 80 | { |
@@ -183,6 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
183 | BIT(IWL_CALIB_TX_IQ) | | 187 | BIT(IWL_CALIB_TX_IQ) | |
184 | BIT(IWL_CALIB_BASE_BAND); | 188 | BIT(IWL_CALIB_BASE_BAND); |
185 | 189 | ||
190 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
191 | |||
186 | return 0; | 192 | return 0; |
187 | } | 193 | } |
188 | 194 | ||
@@ -228,37 +234,74 @@ static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) | |||
228 | BIT(IWL_CALIB_TX_IQ) | | 234 | BIT(IWL_CALIB_TX_IQ) | |
229 | BIT(IWL_CALIB_BASE_BAND); | 235 | BIT(IWL_CALIB_BASE_BAND); |
230 | 236 | ||
237 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
238 | |||
231 | return 0; | 239 | return 0; |
232 | } | 240 | } |
233 | 241 | ||
234 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 242 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, |
243 | struct ieee80211_channel_switch *ch_switch) | ||
235 | { | 244 | { |
236 | struct iwl6000_channel_switch_cmd cmd; | 245 | struct iwl6000_channel_switch_cmd cmd; |
237 | const struct iwl_channel_info *ch_info; | 246 | const struct iwl_channel_info *ch_info; |
247 | u32 switch_time_in_usec, ucode_switch_time; | ||
248 | u16 ch; | ||
249 | u32 tsf_low; | ||
250 | u8 switch_count; | ||
251 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
252 | struct ieee80211_vif *vif = priv->vif; | ||
238 | struct iwl_host_cmd hcmd = { | 253 | struct iwl_host_cmd hcmd = { |
239 | .id = REPLY_CHANNEL_SWITCH, | 254 | .id = REPLY_CHANNEL_SWITCH, |
240 | .len = sizeof(cmd), | 255 | .len = sizeof(cmd), |
241 | .flags = CMD_SIZE_HUGE, | 256 | .flags = CMD_SYNC, |
242 | .data = &cmd, | 257 | .data = &cmd, |
243 | }; | 258 | }; |
244 | 259 | ||
245 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
246 | priv->active_rxon.channel, channel); | ||
247 | |||
248 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 260 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
249 | cmd.channel = cpu_to_le16(channel); | 261 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
262 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | ||
263 | priv->active_rxon.channel, ch); | ||
264 | cmd.channel = cpu_to_le16(ch); | ||
250 | cmd.rxon_flags = priv->staging_rxon.flags; | 265 | cmd.rxon_flags = priv->staging_rxon.flags; |
251 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 266 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
252 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 267 | switch_count = ch_switch->count; |
253 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 268 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
269 | /* | ||
270 | * calculate the ucode channel switch time | ||
271 | * adding TSF as one of the factor for when to switch | ||
272 | */ | ||
273 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
274 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
275 | beacon_interval)) { | ||
276 | switch_count -= (priv->ucode_beacon_time - | ||
277 | tsf_low) / beacon_interval; | ||
278 | } else | ||
279 | switch_count = 0; | ||
280 | } | ||
281 | if (switch_count <= 1) | ||
282 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
283 | else { | ||
284 | switch_time_in_usec = | ||
285 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
286 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
287 | switch_time_in_usec, | ||
288 | beacon_interval); | ||
289 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
290 | priv->ucode_beacon_time, | ||
291 | ucode_switch_time, | ||
292 | beacon_interval); | ||
293 | } | ||
294 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
295 | cmd.switch_time); | ||
296 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
254 | if (ch_info) | 297 | if (ch_info) |
255 | cmd.expect_beacon = is_channel_radar(ch_info); | 298 | cmd.expect_beacon = is_channel_radar(ch_info); |
256 | else { | 299 | else { |
257 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 300 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
258 | priv->active_rxon.channel, channel); | 301 | priv->active_rxon.channel, ch); |
259 | return -EFAULT; | 302 | return -EFAULT; |
260 | } | 303 | } |
261 | priv->switch_rxon.channel = cpu_to_le16(channel); | 304 | priv->switch_rxon.channel = cmd.channel; |
262 | priv->switch_rxon.switch_in_progress = true; | 305 | priv->switch_rxon.switch_in_progress = true; |
263 | 306 | ||
264 | return iwl_send_cmd_sync(priv, &hcmd); | 307 | return iwl_send_cmd_sync(priv, &hcmd); |
@@ -335,6 +378,25 @@ static const struct iwl_ops iwl6000_ops = { | |||
335 | .led = &iwlagn_led_ops, | 378 | .led = &iwlagn_led_ops, |
336 | }; | 379 | }; |
337 | 380 | ||
381 | static void do_not_send_bt_config(struct iwl_priv *priv) | ||
382 | { | ||
383 | } | ||
384 | |||
385 | static struct iwl_hcmd_ops iwl6000g2b_hcmd = { | ||
386 | .rxon_assoc = iwlagn_send_rxon_assoc, | ||
387 | .commit_rxon = iwl_commit_rxon, | ||
388 | .set_rxon_chain = iwl_set_rxon_chain, | ||
389 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
390 | .send_bt_config = do_not_send_bt_config, | ||
391 | }; | ||
392 | |||
393 | static const struct iwl_ops iwl6000g2b_ops = { | ||
394 | .lib = &iwl6000_lib, | ||
395 | .hcmd = &iwl6000g2b_hcmd, | ||
396 | .utils = &iwlagn_hcmd_utils, | ||
397 | .led = &iwlagn_led_ops, | ||
398 | }; | ||
399 | |||
338 | static struct iwl_lib_ops iwl6050_lib = { | 400 | static struct iwl_lib_ops iwl6050_lib = { |
339 | .set_hw_params = iwl6050_hw_set_hw_params, | 401 | .set_hw_params = iwl6050_hw_set_hw_params, |
340 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | 402 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
@@ -445,6 +507,268 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { | |||
445 | .chain_noise_calib_by_driver = true, | 507 | .chain_noise_calib_by_driver = true, |
446 | }; | 508 | }; |
447 | 509 | ||
510 | struct iwl_cfg iwl6000g2a_2abg_cfg = { | ||
511 | .name = "6000 Series 2x2 ABG Gen2a", | ||
512 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
513 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
514 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
515 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
516 | .ops = &iwl6000_ops, | ||
517 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
518 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
519 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
520 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
521 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
522 | .mod_params = &iwlagn_mod_params, | ||
523 | .valid_tx_ant = ANT_AB, | ||
524 | .valid_rx_ant = ANT_AB, | ||
525 | .pll_cfg_val = 0, | ||
526 | .set_l0s = true, | ||
527 | .use_bsm = false, | ||
528 | .pa_type = IWL_PA_SYSTEM, | ||
529 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
530 | .shadow_ram_support = true, | ||
531 | .led_compensation = 51, | ||
532 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
533 | .supports_idle = true, | ||
534 | .adv_thermal_throttle = true, | ||
535 | .support_ct_kill_exit = true, | ||
536 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
537 | .chain_noise_scale = 1000, | ||
538 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
539 | .max_event_log_size = 512, | ||
540 | }; | ||
541 | |||
542 | struct iwl_cfg iwl6000g2a_2bg_cfg = { | ||
543 | .name = "6000 Series 2x2 BG Gen2a", | ||
544 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
545 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
546 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
547 | .sku = IWL_SKU_G, | ||
548 | .ops = &iwl6000_ops, | ||
549 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
550 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
551 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
552 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
553 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
554 | .mod_params = &iwlagn_mod_params, | ||
555 | .valid_tx_ant = ANT_AB, | ||
556 | .valid_rx_ant = ANT_AB, | ||
557 | .pll_cfg_val = 0, | ||
558 | .set_l0s = true, | ||
559 | .use_bsm = false, | ||
560 | .pa_type = IWL_PA_SYSTEM, | ||
561 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
562 | .shadow_ram_support = true, | ||
563 | .led_compensation = 51, | ||
564 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
565 | .supports_idle = true, | ||
566 | .adv_thermal_throttle = true, | ||
567 | .support_ct_kill_exit = true, | ||
568 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
569 | .chain_noise_scale = 1000, | ||
570 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
571 | .max_event_log_size = 512, | ||
572 | }; | ||
573 | |||
574 | struct iwl_cfg iwl6000g2b_2agn_cfg = { | ||
575 | .name = "6000 Series 2x2 AGN Gen2b", | ||
576 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
577 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
578 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
579 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
580 | .ops = &iwl6000g2b_ops, | ||
581 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
582 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
583 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
584 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
585 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
586 | .mod_params = &iwlagn_mod_params, | ||
587 | .valid_tx_ant = ANT_AB, | ||
588 | .valid_rx_ant = ANT_AB, | ||
589 | .pll_cfg_val = 0, | ||
590 | .set_l0s = true, | ||
591 | .use_bsm = false, | ||
592 | .pa_type = IWL_PA_SYSTEM, | ||
593 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
594 | .shadow_ram_support = true, | ||
595 | .ht_greenfield_support = true, | ||
596 | .led_compensation = 51, | ||
597 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
598 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
599 | .supports_idle = true, | ||
600 | .adv_thermal_throttle = true, | ||
601 | .support_ct_kill_exit = true, | ||
602 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
603 | .chain_noise_scale = 1000, | ||
604 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
605 | .max_event_log_size = 512, | ||
606 | }; | ||
607 | |||
608 | struct iwl_cfg iwl6000g2b_2abg_cfg = { | ||
609 | .name = "6000 Series 2x2 ABG Gen2b", | ||
610 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
611 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
612 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
613 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
614 | .ops = &iwl6000g2b_ops, | ||
615 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
616 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
617 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
618 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
619 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
620 | .mod_params = &iwlagn_mod_params, | ||
621 | .valid_tx_ant = ANT_AB, | ||
622 | .valid_rx_ant = ANT_AB, | ||
623 | .pll_cfg_val = 0, | ||
624 | .set_l0s = true, | ||
625 | .use_bsm = false, | ||
626 | .pa_type = IWL_PA_SYSTEM, | ||
627 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
628 | .shadow_ram_support = true, | ||
629 | .led_compensation = 51, | ||
630 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
631 | .supports_idle = true, | ||
632 | .adv_thermal_throttle = true, | ||
633 | .support_ct_kill_exit = true, | ||
634 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
635 | .chain_noise_scale = 1000, | ||
636 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
637 | .max_event_log_size = 512, | ||
638 | }; | ||
639 | |||
640 | struct iwl_cfg iwl6000g2b_2bgn_cfg = { | ||
641 | .name = "6000 Series 2x2 BGN Gen2b", | ||
642 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
643 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
644 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
645 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
646 | .ops = &iwl6000g2b_ops, | ||
647 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
648 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
649 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
650 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
651 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
652 | .mod_params = &iwlagn_mod_params, | ||
653 | .valid_tx_ant = ANT_AB, | ||
654 | .valid_rx_ant = ANT_AB, | ||
655 | .pll_cfg_val = 0, | ||
656 | .set_l0s = true, | ||
657 | .use_bsm = false, | ||
658 | .pa_type = IWL_PA_SYSTEM, | ||
659 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
660 | .shadow_ram_support = true, | ||
661 | .ht_greenfield_support = true, | ||
662 | .led_compensation = 51, | ||
663 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
664 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
665 | .supports_idle = true, | ||
666 | .adv_thermal_throttle = true, | ||
667 | .support_ct_kill_exit = true, | ||
668 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
669 | .chain_noise_scale = 1000, | ||
670 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
671 | .max_event_log_size = 512, | ||
672 | }; | ||
673 | |||
674 | struct iwl_cfg iwl6000g2b_2bg_cfg = { | ||
675 | .name = "6000 Series 2x2 BG Gen2b", | ||
676 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
677 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
678 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
679 | .sku = IWL_SKU_G, | ||
680 | .ops = &iwl6000g2b_ops, | ||
681 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
682 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
683 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
684 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
685 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
686 | .mod_params = &iwlagn_mod_params, | ||
687 | .valid_tx_ant = ANT_AB, | ||
688 | .valid_rx_ant = ANT_AB, | ||
689 | .pll_cfg_val = 0, | ||
690 | .set_l0s = true, | ||
691 | .use_bsm = false, | ||
692 | .pa_type = IWL_PA_SYSTEM, | ||
693 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
694 | .shadow_ram_support = true, | ||
695 | .led_compensation = 51, | ||
696 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
697 | .supports_idle = true, | ||
698 | .adv_thermal_throttle = true, | ||
699 | .support_ct_kill_exit = true, | ||
700 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
701 | .chain_noise_scale = 1000, | ||
702 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
703 | .max_event_log_size = 512, | ||
704 | }; | ||
705 | |||
706 | struct iwl_cfg iwl6000g2b_bgn_cfg = { | ||
707 | .name = "6000 Series 1x2 BGN Gen2b", | ||
708 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
709 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
710 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
711 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
712 | .ops = &iwl6000g2b_ops, | ||
713 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
714 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
715 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
716 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
717 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
718 | .mod_params = &iwlagn_mod_params, | ||
719 | .valid_tx_ant = ANT_A, | ||
720 | .valid_rx_ant = ANT_AB, | ||
721 | .pll_cfg_val = 0, | ||
722 | .set_l0s = true, | ||
723 | .use_bsm = false, | ||
724 | .pa_type = IWL_PA_SYSTEM, | ||
725 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
726 | .shadow_ram_support = true, | ||
727 | .ht_greenfield_support = true, | ||
728 | .led_compensation = 51, | ||
729 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
730 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
731 | .supports_idle = true, | ||
732 | .adv_thermal_throttle = true, | ||
733 | .support_ct_kill_exit = true, | ||
734 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
735 | .chain_noise_scale = 1000, | ||
736 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
737 | .max_event_log_size = 512, | ||
738 | }; | ||
739 | |||
740 | struct iwl_cfg iwl6000g2b_bg_cfg = { | ||
741 | .name = "6000 Series 1x2 BG Gen2b", | ||
742 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
743 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
744 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
745 | .sku = IWL_SKU_G, | ||
746 | .ops = &iwl6000g2b_ops, | ||
747 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
748 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
749 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
750 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
751 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
752 | .mod_params = &iwlagn_mod_params, | ||
753 | .valid_tx_ant = ANT_A, | ||
754 | .valid_rx_ant = ANT_AB, | ||
755 | .pll_cfg_val = 0, | ||
756 | .set_l0s = true, | ||
757 | .use_bsm = false, | ||
758 | .pa_type = IWL_PA_SYSTEM, | ||
759 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
760 | .shadow_ram_support = true, | ||
761 | .led_compensation = 51, | ||
762 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
763 | .supports_idle = true, | ||
764 | .adv_thermal_throttle = true, | ||
765 | .support_ct_kill_exit = true, | ||
766 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
767 | .chain_noise_scale = 1000, | ||
768 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
769 | .max_event_log_size = 512, | ||
770 | }; | ||
771 | |||
448 | /* | 772 | /* |
449 | * "i": Internal configuration, use internal Power Amplifier | 773 | * "i": Internal configuration, use internal Power Amplifier |
450 | */ | 774 | */ |
@@ -667,3 +991,4 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
667 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 991 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
668 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); | 992 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); |
669 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 993 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
994 | MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 48c023b4ca3..3d08dc8af14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -28,6 +28,27 @@ | |||
28 | 28 | ||
29 | #include "iwl-agn-debugfs.h" | 29 | #include "iwl-agn-debugfs.h" |
30 | 30 | ||
31 | static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
32 | { | ||
33 | int p = 0; | ||
34 | |||
35 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
36 | le32_to_cpu(priv->statistics.flag)); | ||
37 | if (le32_to_cpu(priv->statistics.flag) & | ||
38 | UCODE_STATISTICS_CLEAR_MSK) | ||
39 | p += scnprintf(buf + p, bufsz - p, | ||
40 | "\tStatistics have been cleared\n"); | ||
41 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
42 | (le32_to_cpu(priv->statistics.flag) & | ||
43 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
44 | ? "2.4 GHz" : "5.2 GHz"); | ||
45 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
46 | (le32_to_cpu(priv->statistics.flag) & | ||
47 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
48 | ? "enabled" : "disabled"); | ||
49 | return p; | ||
50 | } | ||
51 | |||
31 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | 52 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, |
32 | size_t count, loff_t *ppos) | 53 | size_t count, loff_t *ppos) |
33 | { | 54 | { |
@@ -75,7 +96,7 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
75 | max_general = &priv->max_delta.rx.general; | 96 | max_general = &priv->max_delta.rx.general; |
76 | max_ht = &priv->max_delta.rx.ofdm_ht; | 97 | max_ht = &priv->max_delta.rx.ofdm_ht; |
77 | 98 | ||
78 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 99 | pos += iwl_statistics_flag(priv, buf, bufsz); |
79 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 100 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
80 | "acumulative delta max\n", | 101 | "acumulative delta max\n", |
81 | "Statistics_Rx - OFDM:"); | 102 | "Statistics_Rx - OFDM:"); |
@@ -543,7 +564,7 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
543 | accum_tx = &priv->accum_statistics.tx; | 564 | accum_tx = &priv->accum_statistics.tx; |
544 | delta_tx = &priv->delta_statistics.tx; | 565 | delta_tx = &priv->delta_statistics.tx; |
545 | max_tx = &priv->max_delta.tx; | 566 | max_tx = &priv->max_delta.tx; |
546 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 567 | pos += iwl_statistics_flag(priv, buf, bufsz); |
547 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 568 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
548 | "acumulative delta max\n", | 569 | "acumulative delta max\n", |
549 | "Statistics_Tx:"); | 570 | "Statistics_Tx:"); |
@@ -768,7 +789,7 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
768 | accum_div = &priv->accum_statistics.general.div; | 789 | accum_div = &priv->accum_statistics.general.div; |
769 | delta_div = &priv->delta_statistics.general.div; | 790 | delta_div = &priv->delta_statistics.general.div; |
770 | max_div = &priv->max_delta.general.div; | 791 | max_div = &priv->max_delta.general.div; |
771 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 792 | pos += iwl_statistics_flag(priv, buf, bufsz); |
772 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 793 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
773 | "acumulative delta max\n", | 794 | "acumulative delta max\n", |
774 | "Statistics_General:"); | 795 | "Statistics_General:"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 44ef5d93bef..3f765ba15cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
38 | #include "iwl-agn.h" | 38 | #include "iwl-agn.h" |
39 | 39 | ||
40 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | 40 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv) |
41 | { | 41 | { |
42 | int ret = 0; | 42 | int ret = 0; |
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | 43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; |
@@ -84,7 +84,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | |||
84 | return ret; | 84 | return ret; |
85 | } | 85 | } |
86 | 86 | ||
87 | static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | 87 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) |
88 | { | 88 | { |
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | 89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { |
90 | .valid = cpu_to_le32(valid_tx_ant), | 90 | .valid = cpu_to_le32(valid_tx_ant), |
@@ -176,14 +176,6 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, | |||
176 | data->radio_write = 1; | 176 | data->radio_write = 1; |
177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | 177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; |
178 | } | 178 | } |
179 | |||
180 | data->chain_noise_a = 0; | ||
181 | data->chain_noise_b = 0; | ||
182 | data->chain_noise_c = 0; | ||
183 | data->chain_signal_a = 0; | ||
184 | data->chain_signal_b = 0; | ||
185 | data->chain_signal_c = 0; | ||
186 | data->beacon_count = 0; | ||
187 | } | 179 | } |
188 | 180 | ||
189 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | 181 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) |
@@ -191,10 +183,20 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | |||
191 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 183 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
192 | int ret; | 184 | int ret; |
193 | 185 | ||
194 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | 186 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
187 | iwl_is_associated(priv)) { | ||
195 | struct iwl_calib_chain_noise_reset_cmd cmd; | 188 | struct iwl_calib_chain_noise_reset_cmd cmd; |
196 | memset(&cmd, 0, sizeof(cmd)); | ||
197 | 189 | ||
190 | /* clear data for chain noise calibration algorithm */ | ||
191 | data->chain_noise_a = 0; | ||
192 | data->chain_noise_b = 0; | ||
193 | data->chain_noise_c = 0; | ||
194 | data->chain_signal_a = 0; | ||
195 | data->chain_signal_b = 0; | ||
196 | data->chain_signal_c = 0; | ||
197 | data->beacon_count = 0; | ||
198 | |||
199 | memset(&cmd, 0, sizeof(cmd)); | ||
198 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | 200 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; |
199 | cmd.hdr.first_group = 0; | 201 | cmd.hdr.first_group = 0; |
200 | cmd.hdr.groups_num = 1; | 202 | cmd.hdr.groups_num = 1; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 1004cfc403b..548f51d92de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -77,7 +77,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | 77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", |
78 | agg->frame_count, agg->start_idx, idx); | 78 | agg->frame_count, agg->start_idx, idx); |
79 | 79 | ||
80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); |
81 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 81 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
83 | info->flags |= iwl_tx_status_to_mac80211(status); | 83 | info->flags |= iwl_tx_status_to_mac80211(status); |
@@ -93,6 +93,12 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
93 | } else { | 93 | } else { |
94 | /* Two or more frames were attempted; expect block-ack */ | 94 | /* Two or more frames were attempted; expect block-ack */ |
95 | u64 bitmap = 0; | 95 | u64 bitmap = 0; |
96 | |||
97 | /* | ||
98 | * Start is the lowest frame sent. It may not be the first | ||
99 | * frame in the batch; we figure this out dynamically during | ||
100 | * the following loop. | ||
101 | */ | ||
96 | int start = agg->start_idx; | 102 | int start = agg->start_idx; |
97 | 103 | ||
98 | /* Construct bit-map of pending frames within Tx window */ | 104 | /* Construct bit-map of pending frames within Tx window */ |
@@ -131,25 +137,58 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
131 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | 137 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", |
132 | i, idx, SEQ_TO_SN(sc)); | 138 | i, idx, SEQ_TO_SN(sc)); |
133 | 139 | ||
140 | /* | ||
141 | * sh -> how many frames ahead of the starting frame is | ||
142 | * the current one? | ||
143 | * | ||
144 | * Note that all frames sent in the batch must be in a | ||
145 | * 64-frame window, so this number should be in [0,63]. | ||
146 | * If outside of this window, then we've found a new | ||
147 | * "first" frame in the batch and need to change start. | ||
148 | */ | ||
134 | sh = idx - start; | 149 | sh = idx - start; |
135 | if (sh > 64) { | 150 | |
136 | sh = (start - idx) + 0xff; | 151 | /* |
152 | * If >= 64, out of window. start must be at the front | ||
153 | * of the circular buffer, idx must be near the end of | ||
154 | * the buffer, and idx is the new "first" frame. Shift | ||
155 | * the indices around. | ||
156 | */ | ||
157 | if (sh >= 64) { | ||
158 | /* Shift bitmap by start - idx, wrapped */ | ||
159 | sh = 0x100 - idx + start; | ||
137 | bitmap = bitmap << sh; | 160 | bitmap = bitmap << sh; |
161 | /* Now idx is the new start so sh = 0 */ | ||
138 | sh = 0; | 162 | sh = 0; |
139 | start = idx; | 163 | start = idx; |
140 | } else if (sh < -64) | 164 | /* |
141 | sh = 0xff - (start - idx); | 165 | * If <= -64 then wraps the 256-pkt circular buffer |
142 | else if (sh < 0) { | 166 | * (e.g., start = 255 and idx = 0, sh should be 1) |
167 | */ | ||
168 | } else if (sh <= -64) { | ||
169 | sh = 0x100 - start + idx; | ||
170 | /* | ||
171 | * If < 0 but > -64, out of window. idx is before start | ||
172 | * but not wrapped. Shift the indices around. | ||
173 | */ | ||
174 | } else if (sh < 0) { | ||
175 | /* Shift by how far start is ahead of idx */ | ||
143 | sh = start - idx; | 176 | sh = start - idx; |
144 | start = idx; | ||
145 | bitmap = bitmap << sh; | 177 | bitmap = bitmap << sh; |
178 | /* Now idx is the new start so sh = 0 */ | ||
179 | start = idx; | ||
146 | sh = 0; | 180 | sh = 0; |
147 | } | 181 | } |
182 | /* Sequence number start + sh was sent in this batch */ | ||
148 | bitmap |= 1ULL << sh; | 183 | bitmap |= 1ULL << sh; |
149 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | 184 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", |
150 | start, (unsigned long long)bitmap); | 185 | start, (unsigned long long)bitmap); |
151 | } | 186 | } |
152 | 187 | ||
188 | /* | ||
189 | * Store the bitmap and possibly the new start, if we wrapped | ||
190 | * the buffer above | ||
191 | */ | ||
153 | agg->bitmap = bitmap; | 192 | agg->bitmap = bitmap; |
154 | agg->start_idx = start; | 193 | agg->start_idx = start; |
155 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | 194 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", |
@@ -184,6 +223,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
184 | int tid; | 223 | int tid; |
185 | int sta_id; | 224 | int sta_id; |
186 | int freed; | 225 | int freed; |
226 | unsigned long flags; | ||
187 | 227 | ||
188 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | 228 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { |
189 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | 229 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " |
@@ -193,15 +233,16 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
193 | return; | 233 | return; |
194 | } | 234 | } |
195 | 235 | ||
196 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 236 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
197 | memset(&info->status, 0, sizeof(info->status)); | 237 | memset(&info->status, 0, sizeof(info->status)); |
198 | 238 | ||
199 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | 239 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; |
200 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | 240 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; |
201 | 241 | ||
242 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
202 | if (txq->sched_retry) { | 243 | if (txq->sched_retry) { |
203 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); | 244 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); |
204 | struct iwl_ht_agg *agg = NULL; | 245 | struct iwl_ht_agg *agg; |
205 | 246 | ||
206 | agg = &priv->stations[sta_id].tid[tid].agg; | 247 | agg = &priv->stations[sta_id].tid[tid].agg; |
207 | 248 | ||
@@ -256,6 +297,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
256 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | 297 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
257 | 298 | ||
258 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 299 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
300 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
259 | } | 301 | } |
260 | 302 | ||
261 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | 303 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) |
@@ -755,132 +797,6 @@ static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
755 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | 797 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); |
756 | } | 798 | } |
757 | 799 | ||
758 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
759 | /** | ||
760 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
761 | * | ||
762 | * You may hack this function to show different aspects of received frames, | ||
763 | * including selective frame dumps. | ||
764 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
765 | * All beacon and probe response frames are printed. | ||
766 | */ | ||
767 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
768 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
769 | struct ieee80211_hdr *header, int group100) | ||
770 | { | ||
771 | u32 to_us; | ||
772 | u32 print_summary = 0; | ||
773 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
774 | u32 hundred = 0; | ||
775 | u32 dataframe = 0; | ||
776 | __le16 fc; | ||
777 | u16 seq_ctl; | ||
778 | u16 channel; | ||
779 | u16 phy_flags; | ||
780 | u32 rate_n_flags; | ||
781 | u32 tsf_low; | ||
782 | int rssi; | ||
783 | |||
784 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
785 | return; | ||
786 | |||
787 | /* MAC header */ | ||
788 | fc = header->frame_control; | ||
789 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
790 | |||
791 | /* metadata */ | ||
792 | channel = le16_to_cpu(phy_res->channel); | ||
793 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
794 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
795 | |||
796 | /* signal statistics */ | ||
797 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
798 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
799 | |||
800 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
801 | |||
802 | /* if data frame is to us and all is good, | ||
803 | * (optionally) print summary for only 1 out of every 100 */ | ||
804 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
805 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
806 | dataframe = 1; | ||
807 | if (!group100) | ||
808 | print_summary = 1; /* print each frame */ | ||
809 | else if (priv->framecnt_to_us < 100) { | ||
810 | priv->framecnt_to_us++; | ||
811 | print_summary = 0; | ||
812 | } else { | ||
813 | priv->framecnt_to_us = 0; | ||
814 | print_summary = 1; | ||
815 | hundred = 1; | ||
816 | } | ||
817 | } else { | ||
818 | /* print summary for all other frames */ | ||
819 | print_summary = 1; | ||
820 | } | ||
821 | |||
822 | if (print_summary) { | ||
823 | char *title; | ||
824 | int rate_idx; | ||
825 | u32 bitrate; | ||
826 | |||
827 | if (hundred) | ||
828 | title = "100Frames"; | ||
829 | else if (ieee80211_has_retry(fc)) | ||
830 | title = "Retry"; | ||
831 | else if (ieee80211_is_assoc_resp(fc)) | ||
832 | title = "AscRsp"; | ||
833 | else if (ieee80211_is_reassoc_resp(fc)) | ||
834 | title = "RasRsp"; | ||
835 | else if (ieee80211_is_probe_resp(fc)) { | ||
836 | title = "PrbRsp"; | ||
837 | print_dump = 1; /* dump frame contents */ | ||
838 | } else if (ieee80211_is_beacon(fc)) { | ||
839 | title = "Beacon"; | ||
840 | print_dump = 1; /* dump frame contents */ | ||
841 | } else if (ieee80211_is_atim(fc)) | ||
842 | title = "ATIM"; | ||
843 | else if (ieee80211_is_auth(fc)) | ||
844 | title = "Auth"; | ||
845 | else if (ieee80211_is_deauth(fc)) | ||
846 | title = "DeAuth"; | ||
847 | else if (ieee80211_is_disassoc(fc)) | ||
848 | title = "DisAssoc"; | ||
849 | else | ||
850 | title = "Frame"; | ||
851 | |||
852 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
853 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
854 | bitrate = 0; | ||
855 | WARN_ON_ONCE(1); | ||
856 | } else { | ||
857 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
858 | } | ||
859 | |||
860 | /* print frame summary. | ||
861 | * MAC addresses show just the last byte (for brevity), | ||
862 | * but you can hack it to show more, if you'd like to. */ | ||
863 | if (dataframe) | ||
864 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
865 | "len=%u, rssi=%d, chnl=%d, rate=%u,\n", | ||
866 | title, le16_to_cpu(fc), header->addr1[5], | ||
867 | length, rssi, channel, bitrate); | ||
868 | else { | ||
869 | /* src/dst addresses assume managed mode */ | ||
870 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
871 | "len=%u, rssi=%d, tim=%lu usec, " | ||
872 | "phy=0x%02x, chnl=%d\n", | ||
873 | title, le16_to_cpu(fc), header->addr1[5], | ||
874 | header->addr3[5], length, rssi, | ||
875 | tsf_low - priv->scan_start_tsf, | ||
876 | phy_flags, channel); | ||
877 | } | ||
878 | } | ||
879 | if (print_dump) | ||
880 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
881 | } | ||
882 | #endif | ||
883 | |||
884 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | 800 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) |
885 | { | 801 | { |
886 | u32 decrypt_out = 0; | 802 | u32 decrypt_out = 0; |
@@ -1060,11 +976,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1060 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | 976 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ |
1061 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | 977 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); |
1062 | 978 | ||
1063 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1064 | /* Set "1" to report good data frames in groups of 100 */ | ||
1065 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1066 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1067 | #endif | ||
1068 | iwl_dbg_log_rx_data_frame(priv, len, header); | 979 | iwl_dbg_log_rx_data_frame(priv, len, header); |
1069 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | 980 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", |
1070 | rx_status.signal, (unsigned long long)rx_status.mactime); | 981 | rx_status.signal, (unsigned long long)rx_status.mactime); |
@@ -1119,10 +1030,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | |||
1119 | struct iwl_scan_channel *scan_ch) | 1030 | struct iwl_scan_channel *scan_ch) |
1120 | { | 1031 | { |
1121 | const struct ieee80211_supported_band *sband; | 1032 | const struct ieee80211_supported_band *sband; |
1122 | const struct iwl_channel_info *ch_info; | ||
1123 | u16 passive_dwell = 0; | 1033 | u16 passive_dwell = 0; |
1124 | u16 active_dwell = 0; | 1034 | u16 active_dwell = 0; |
1125 | int i, added = 0; | 1035 | int added = 0; |
1126 | u16 channel = 0; | 1036 | u16 channel = 0; |
1127 | 1037 | ||
1128 | sband = iwl_get_hw_mode(priv, band); | 1038 | sband = iwl_get_hw_mode(priv, band); |
@@ -1137,32 +1047,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | |||
1137 | if (passive_dwell <= active_dwell) | 1047 | if (passive_dwell <= active_dwell) |
1138 | passive_dwell = active_dwell + 1; | 1048 | passive_dwell = active_dwell + 1; |
1139 | 1049 | ||
1140 | /* only scan single channel, good enough to reset the RF */ | 1050 | channel = iwl_get_single_channel_number(priv, band); |
1141 | /* pick the first valid not in-use channel */ | ||
1142 | if (band == IEEE80211_BAND_5GHZ) { | ||
1143 | for (i = 14; i < priv->channel_count; i++) { | ||
1144 | if (priv->channel_info[i].channel != | ||
1145 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
1146 | channel = priv->channel_info[i].channel; | ||
1147 | ch_info = iwl_get_channel_info(priv, | ||
1148 | band, channel); | ||
1149 | if (is_channel_valid(ch_info)) | ||
1150 | break; | ||
1151 | } | ||
1152 | } | ||
1153 | } else { | ||
1154 | for (i = 0; i < 14; i++) { | ||
1155 | if (priv->channel_info[i].channel != | ||
1156 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
1157 | channel = | ||
1158 | priv->channel_info[i].channel; | ||
1159 | ch_info = iwl_get_channel_info(priv, | ||
1160 | band, channel); | ||
1161 | if (is_channel_valid(ch_info)) | ||
1162 | break; | ||
1163 | } | ||
1164 | } | ||
1165 | } | ||
1166 | if (channel) { | 1051 | if (channel) { |
1167 | scan_ch->channel = cpu_to_le16(channel); | 1052 | scan_ch->channel = cpu_to_le16(channel); |
1168 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 1053 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
@@ -1278,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1278 | bool is_active = false; | 1163 | bool is_active = false; |
1279 | int chan_mod; | 1164 | int chan_mod; |
1280 | u8 active_chains; | 1165 | u8 active_chains; |
1166 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | ||
1281 | 1167 | ||
1282 | conf = ieee80211_get_hw_conf(priv->hw); | 1168 | conf = ieee80211_get_hw_conf(priv->hw); |
1283 | 1169 | ||
@@ -1429,11 +1315,14 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1429 | 1315 | ||
1430 | band = priv->scan_band; | 1316 | band = priv->scan_band; |
1431 | 1317 | ||
1432 | if (priv->cfg->scan_antennas[band]) | 1318 | if (priv->cfg->scan_rx_antennas[band]) |
1433 | rx_ant = priv->cfg->scan_antennas[band]; | 1319 | rx_ant = priv->cfg->scan_rx_antennas[band]; |
1434 | 1320 | ||
1435 | priv->scan_tx_ant[band] = | 1321 | if (priv->cfg->scan_tx_antennas[band]) |
1436 | iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); | 1322 | scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; |
1323 | |||
1324 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], | ||
1325 | scan_tx_antennas); | ||
1437 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | 1326 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); |
1438 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 1327 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
1439 | 1328 | ||
@@ -1459,13 +1348,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1459 | if (!priv->is_internal_short_scan) { | 1348 | if (!priv->is_internal_short_scan) { |
1460 | cmd_len = iwl_fill_probe_req(priv, | 1349 | cmd_len = iwl_fill_probe_req(priv, |
1461 | (struct ieee80211_mgmt *)scan->data, | 1350 | (struct ieee80211_mgmt *)scan->data, |
1351 | vif->addr, | ||
1462 | priv->scan_request->ie, | 1352 | priv->scan_request->ie, |
1463 | priv->scan_request->ie_len, | 1353 | priv->scan_request->ie_len, |
1464 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 1354 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
1465 | } else { | 1355 | } else { |
1356 | /* use bcast addr, will not be transmitted but must be valid */ | ||
1466 | cmd_len = iwl_fill_probe_req(priv, | 1357 | cmd_len = iwl_fill_probe_req(priv, |
1467 | (struct ieee80211_mgmt *)scan->data, | 1358 | (struct ieee80211_mgmt *)scan->data, |
1468 | NULL, 0, | 1359 | iwl_bcast_addr, NULL, 0, |
1469 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 1360 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
1470 | 1361 | ||
1471 | } | 1362 | } |
@@ -1528,3 +1419,18 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
1528 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | 1419 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, |
1529 | vif->bss_conf.bssid); | 1420 | vif->bss_conf.bssid); |
1530 | } | 1421 | } |
1422 | |||
1423 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
1424 | int sta_id, int tid, int freed) | ||
1425 | { | ||
1426 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | ||
1427 | |||
1428 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | ||
1429 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
1430 | else { | ||
1431 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", | ||
1432 | priv->stations[sta_id].tid[tid].tfds_in_queue, | ||
1433 | freed); | ||
1434 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | ||
1435 | } | ||
1436 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cf4a95bae4f..40933a5de02 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -313,8 +313,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
313 | */ | 313 | */ |
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | 314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", |
315 | tid); | 315 | tid); |
316 | ieee80211_stop_tx_ba_session(sta, tid, | 316 | ieee80211_stop_tx_ba_session(sta, tid); |
317 | WLAN_BACK_INITIATOR); | ||
318 | } | 317 | } |
319 | } else | 318 | } else |
320 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); | 319 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c402bfc83f3..10a0acdb9dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -469,7 +469,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
469 | } | 469 | } |
470 | 470 | ||
471 | /* Set up antennas */ | 471 | /* Set up antennas */ |
472 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | 472 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
473 | priv->hw_params.valid_tx_ant); | ||
473 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 474 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
474 | 475 | ||
475 | /* Set the rate in the TX cmd */ | 476 | /* Set the rate in the TX cmd */ |
@@ -567,10 +568,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
567 | hdr_len = ieee80211_hdrlen(fc); | 568 | hdr_len = ieee80211_hdrlen(fc); |
568 | 569 | ||
569 | /* Find index into station table for destination station */ | 570 | /* Find index into station table for destination station */ |
570 | if (!info->control.sta) | 571 | sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); |
571 | sta_id = priv->hw_params.bcast_sta_id; | ||
572 | else | ||
573 | sta_id = iwl_sta_id(info->control.sta); | ||
574 | if (sta_id == IWL_INVALID_STATION) { | 572 | if (sta_id == IWL_INVALID_STATION) { |
575 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 573 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
576 | hdr->addr1); | 574 | hdr->addr1); |
@@ -598,11 +596,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
598 | } | 596 | } |
599 | 597 | ||
600 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | 598 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); |
599 | |||
600 | /* irqs already disabled/saved above when locking priv->lock */ | ||
601 | spin_lock(&priv->sta_lock); | ||
602 | |||
601 | if (ieee80211_is_data_qos(fc)) { | 603 | if (ieee80211_is_data_qos(fc)) { |
602 | qc = ieee80211_get_qos_ctl(hdr); | 604 | qc = ieee80211_get_qos_ctl(hdr); |
603 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 605 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
604 | if (unlikely(tid >= MAX_TID_COUNT)) | 606 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { |
607 | spin_unlock(&priv->sta_lock); | ||
605 | goto drop_unlock; | 608 | goto drop_unlock; |
609 | } | ||
606 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | 610 | seq_number = priv->stations[sta_id].tid[tid].seq_number; |
607 | seq_number &= IEEE80211_SCTL_SEQ; | 611 | seq_number &= IEEE80211_SCTL_SEQ; |
608 | hdr->seq_ctrl = hdr->seq_ctrl & | 612 | hdr->seq_ctrl = hdr->seq_ctrl & |
@@ -620,15 +624,22 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
620 | swq_id = txq->swq_id; | 624 | swq_id = txq->swq_id; |
621 | q = &txq->q; | 625 | q = &txq->q; |
622 | 626 | ||
623 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | 627 | if (unlikely(iwl_queue_space(q) < q->high_mark)) { |
628 | spin_unlock(&priv->sta_lock); | ||
624 | goto drop_unlock; | 629 | goto drop_unlock; |
630 | } | ||
625 | 631 | ||
626 | if (ieee80211_is_data_qos(fc)) | 632 | if (ieee80211_is_data_qos(fc)) { |
627 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | 633 | priv->stations[sta_id].tid[tid].tfds_in_queue++; |
634 | if (!ieee80211_has_morefrags(fc)) | ||
635 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
636 | } | ||
637 | |||
638 | spin_unlock(&priv->sta_lock); | ||
628 | 639 | ||
629 | /* Set up driver data for this TFD */ | 640 | /* Set up driver data for this TFD */ |
630 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 641 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
631 | txq->txb[q->write_ptr].skb[0] = skb; | 642 | txq->txb[q->write_ptr].skb = skb; |
632 | 643 | ||
633 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 644 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
634 | out_cmd = txq->cmd[q->write_ptr]; | 645 | out_cmd = txq->cmd[q->write_ptr]; |
@@ -694,8 +705,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
694 | txcmd_phys = pci_map_single(priv->pci_dev, | 705 | txcmd_phys = pci_map_single(priv->pci_dev, |
695 | &out_cmd->hdr, len, | 706 | &out_cmd->hdr, len, |
696 | PCI_DMA_BIDIRECTIONAL); | 707 | PCI_DMA_BIDIRECTIONAL); |
697 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | 708 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
698 | pci_unmap_len_set(out_meta, len, len); | 709 | dma_unmap_len_set(out_meta, len, len); |
699 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 710 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
700 | * first entry */ | 711 | * first entry */ |
701 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 712 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
@@ -703,8 +714,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
703 | 714 | ||
704 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 715 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
705 | txq->need_update = 1; | 716 | txq->need_update = 1; |
706 | if (qc) | ||
707 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
708 | } else { | 717 | } else { |
709 | wait_write_ptr = 1; | 718 | wait_write_ptr = 1; |
710 | txq->need_update = 0; | 719 | txq->need_update = 0; |
@@ -1009,6 +1018,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1009 | if (ret) | 1018 | if (ret) |
1010 | return ret; | 1019 | return ret; |
1011 | 1020 | ||
1021 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1022 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1012 | if (tid_data->tfds_in_queue == 0) { | 1023 | if (tid_data->tfds_in_queue == 0) { |
1013 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1024 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1014 | tid_data->agg.state = IWL_AGG_ON; | 1025 | tid_data->agg.state = IWL_AGG_ON; |
@@ -1018,6 +1029,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1018 | tid_data->tfds_in_queue); | 1029 | tid_data->tfds_in_queue); |
1019 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 1030 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
1020 | } | 1031 | } |
1032 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1021 | return ret; | 1033 | return ret; |
1022 | } | 1034 | } |
1023 | 1035 | ||
@@ -1040,11 +1052,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1040 | return -ENXIO; | 1052 | return -ENXIO; |
1041 | } | 1053 | } |
1042 | 1054 | ||
1055 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1056 | |||
1043 | if (priv->stations[sta_id].tid[tid].agg.state == | 1057 | if (priv->stations[sta_id].tid[tid].agg.state == |
1044 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | 1058 | IWL_EMPTYING_HW_QUEUE_ADDBA) { |
1045 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | 1059 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); |
1046 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1060 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1047 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1061 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1062 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1048 | return 0; | 1063 | return 0; |
1049 | } | 1064 | } |
1050 | 1065 | ||
@@ -1062,13 +1077,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1062 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | 1077 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); |
1063 | priv->stations[sta_id].tid[tid].agg.state = | 1078 | priv->stations[sta_id].tid[tid].agg.state = |
1064 | IWL_EMPTYING_HW_QUEUE_DELBA; | 1079 | IWL_EMPTYING_HW_QUEUE_DELBA; |
1080 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1065 | return 0; | 1081 | return 0; |
1066 | } | 1082 | } |
1067 | 1083 | ||
1068 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1084 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1069 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1085 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1070 | 1086 | ||
1071 | spin_lock_irqsave(&priv->lock, flags); | 1087 | /* do not restore/save irqs */ |
1088 | spin_unlock(&priv->sta_lock); | ||
1089 | spin_lock(&priv->lock); | ||
1090 | |||
1072 | /* | 1091 | /* |
1073 | * the only reason this call can fail is queue number out of range, | 1092 | * the only reason this call can fail is queue number out of range, |
1074 | * which can happen if uCode is reloaded and all the station | 1093 | * which can happen if uCode is reloaded and all the station |
@@ -1092,6 +1111,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1092 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | 1111 | u8 *addr = priv->stations[sta_id].sta.sta.addr; |
1093 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | 1112 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; |
1094 | 1113 | ||
1114 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | ||
1115 | |||
1095 | switch (priv->stations[sta_id].tid[tid].agg.state) { | 1116 | switch (priv->stations[sta_id].tid[tid].agg.state) { |
1096 | case IWL_EMPTYING_HW_QUEUE_DELBA: | 1117 | case IWL_EMPTYING_HW_QUEUE_DELBA: |
1097 | /* We are reclaiming the last packet of the */ | 1118 | /* We are reclaiming the last packet of the */ |
@@ -1116,6 +1137,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1116 | } | 1137 | } |
1117 | break; | 1138 | break; |
1118 | } | 1139 | } |
1140 | |||
1119 | return 0; | 1141 | return 0; |
1120 | } | 1142 | } |
1121 | 1143 | ||
@@ -1157,12 +1179,12 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1157 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1179 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1158 | 1180 | ||
1159 | tx_info = &txq->txb[txq->q.read_ptr]; | 1181 | tx_info = &txq->txb[txq->q.read_ptr]; |
1160 | iwlagn_tx_status(priv, tx_info->skb[0]); | 1182 | iwlagn_tx_status(priv, tx_info->skb); |
1161 | 1183 | ||
1162 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | 1184 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; |
1163 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | 1185 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) |
1164 | nfreed++; | 1186 | nfreed++; |
1165 | tx_info->skb[0] = NULL; | 1187 | tx_info->skb = NULL; |
1166 | 1188 | ||
1167 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1189 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) |
1168 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | 1190 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); |
@@ -1186,7 +1208,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1186 | int i, sh, ack; | 1208 | int i, sh, ack; |
1187 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | 1209 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); |
1188 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1210 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
1189 | u64 bitmap; | 1211 | u64 bitmap, sent_bitmap; |
1190 | int successes = 0; | 1212 | int successes = 0; |
1191 | struct ieee80211_tx_info *info; | 1213 | struct ieee80211_tx_info *info; |
1192 | 1214 | ||
@@ -1214,24 +1236,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1214 | 1236 | ||
1215 | /* check for success or failure according to the | 1237 | /* check for success or failure according to the |
1216 | * transmitted bitmap and block-ack bitmap */ | 1238 | * transmitted bitmap and block-ack bitmap */ |
1217 | bitmap &= agg->bitmap; | 1239 | sent_bitmap = bitmap & agg->bitmap; |
1218 | 1240 | ||
1219 | /* For each frame attempted in aggregation, | 1241 | /* For each frame attempted in aggregation, |
1220 | * update driver's record of tx frame's status. */ | 1242 | * update driver's record of tx frame's status. */ |
1221 | for (i = 0; i < agg->frame_count ; i++) { | 1243 | i = 0; |
1222 | ack = bitmap & (1ULL << i); | 1244 | while (sent_bitmap) { |
1223 | successes += !!ack; | 1245 | ack = sent_bitmap & 1ULL; |
1246 | successes += ack; | ||
1224 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | 1247 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", |
1225 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | 1248 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, |
1226 | agg->start_idx + i); | 1249 | agg->start_idx + i); |
1250 | sent_bitmap >>= 1; | ||
1251 | ++i; | ||
1227 | } | 1252 | } |
1228 | 1253 | ||
1229 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | 1254 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); |
1230 | memset(&info->status, 0, sizeof(info->status)); | 1255 | memset(&info->status, 0, sizeof(info->status)); |
1231 | info->flags |= IEEE80211_TX_STAT_ACK; | 1256 | info->flags |= IEEE80211_TX_STAT_ACK; |
1232 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 1257 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
1233 | info->status.ampdu_ack_len = successes; | 1258 | info->status.ampdu_ack_len = successes; |
1234 | info->status.ampdu_ack_map = bitmap; | ||
1235 | info->status.ampdu_len = agg->frame_count; | 1259 | info->status.ampdu_len = agg->frame_count; |
1236 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | 1260 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); |
1237 | 1261 | ||
@@ -1279,6 +1303,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1279 | int index; | 1303 | int index; |
1280 | int sta_id; | 1304 | int sta_id; |
1281 | int tid; | 1305 | int tid; |
1306 | unsigned long flags; | ||
1282 | 1307 | ||
1283 | /* "flow" corresponds to Tx queue */ | 1308 | /* "flow" corresponds to Tx queue */ |
1284 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1309 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
@@ -1301,7 +1326,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1301 | /* Find index just before block-ack window */ | 1326 | /* Find index just before block-ack window */ |
1302 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | 1327 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); |
1303 | 1328 | ||
1304 | /* TODO: Need to get this copy more safely - now good for debug */ | 1329 | spin_lock_irqsave(&priv->sta_lock, flags); |
1305 | 1330 | ||
1306 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | 1331 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " |
1307 | "sta_id = %d\n", | 1332 | "sta_id = %d\n", |
@@ -1337,4 +1362,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1337 | 1362 | ||
1338 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | 1363 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); |
1339 | } | 1364 | } |
1365 | |||
1366 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1340 | } | 1367 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 637286c396f..6f77441cb65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -423,3 +423,126 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
423 | 423 | ||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | |||
427 | |||
428 | /** | ||
429 | * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
430 | * using sample data 100 bytes apart. If these sample points are good, | ||
431 | * it's a pretty good bet that everything between them is good, too. | ||
432 | */ | ||
433 | static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) | ||
434 | { | ||
435 | u32 val; | ||
436 | int ret = 0; | ||
437 | u32 errcnt = 0; | ||
438 | u32 i; | ||
439 | |||
440 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
441 | |||
442 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
443 | /* read data comes through single port, auto-incr addr */ | ||
444 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
445 | * if IWL_DL_IO is set */ | ||
446 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
447 | i + IWLAGN_RTC_INST_LOWER_BOUND); | ||
448 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
449 | if (val != le32_to_cpu(*image)) { | ||
450 | ret = -EIO; | ||
451 | errcnt++; | ||
452 | if (errcnt >= 3) | ||
453 | break; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | /** | ||
461 | * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, | ||
462 | * looking at all data. | ||
463 | */ | ||
464 | static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, | ||
465 | u32 len) | ||
466 | { | ||
467 | u32 val; | ||
468 | u32 save_len = len; | ||
469 | int ret = 0; | ||
470 | u32 errcnt; | ||
471 | |||
472 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
473 | |||
474 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
475 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
476 | |||
477 | errcnt = 0; | ||
478 | for (; len > 0; len -= sizeof(u32), image++) { | ||
479 | /* read data comes through single port, auto-incr addr */ | ||
480 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
481 | * if IWL_DL_IO is set */ | ||
482 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
483 | if (val != le32_to_cpu(*image)) { | ||
484 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
485 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
486 | save_len - len, val, le32_to_cpu(*image)); | ||
487 | ret = -EIO; | ||
488 | errcnt++; | ||
489 | if (errcnt >= 20) | ||
490 | break; | ||
491 | } | ||
492 | } | ||
493 | |||
494 | if (!errcnt) | ||
495 | IWL_DEBUG_INFO(priv, | ||
496 | "ucode image in INSTRUCTION memory is good\n"); | ||
497 | |||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | /** | ||
502 | * iwl_verify_ucode - determine which instruction image is in SRAM, | ||
503 | * and verify its contents | ||
504 | */ | ||
505 | int iwl_verify_ucode(struct iwl_priv *priv) | ||
506 | { | ||
507 | __le32 *image; | ||
508 | u32 len; | ||
509 | int ret; | ||
510 | |||
511 | /* Try bootstrap */ | ||
512 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
513 | len = priv->ucode_boot.len; | ||
514 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
515 | if (!ret) { | ||
516 | IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* Try initialize */ | ||
521 | image = (__le32 *)priv->ucode_init.v_addr; | ||
522 | len = priv->ucode_init.len; | ||
523 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
524 | if (!ret) { | ||
525 | IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* Try runtime/protocol */ | ||
530 | image = (__le32 *)priv->ucode_code.v_addr; | ||
531 | len = priv->ucode_code.len; | ||
532 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
533 | if (!ret) { | ||
534 | IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); | ||
539 | |||
540 | /* Since nothing seems to match, show first several data entries in | ||
541 | * instruction SRAM, so maybe visual inspection will give a clue. | ||
542 | * Selection of bootstrap image (vs. other images) is arbitrary. */ | ||
543 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
544 | len = priv->ucode_boot.len; | ||
545 | ret = iwl_verify_inst_full(priv, image, len); | ||
546 | |||
547 | return ret; | ||
548 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index aef4f71f198..69e17d78288 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | 120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { |
121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | 121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", |
122 | le16_to_cpu(priv->switch_rxon.channel)); | 122 | le16_to_cpu(priv->switch_rxon.channel)); |
123 | priv->switch_rxon.switch_in_progress = false; | 123 | iwl_chswitch_done(priv, false); |
124 | } | 124 | } |
125 | 125 | ||
126 | /* If we don't need to send a full RXON, we can use | 126 | /* If we don't need to send a full RXON, we can use |
@@ -367,7 +367,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
367 | 367 | ||
368 | /* Set up packet rate and flags */ | 368 | /* Set up packet rate and flags */ |
369 | rate = iwl_rate_get_lowest_plcp(priv); | 369 | rate = iwl_rate_get_lowest_plcp(priv); |
370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | 370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
371 | priv->hw_params.valid_tx_ant); | ||
371 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 372 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
372 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | 373 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) |
373 | rate_flags |= RATE_MCS_CCK_MSK; | 374 | rate_flags |= RATE_MCS_CCK_MSK; |
@@ -474,18 +475,25 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
474 | /* Unmap tx_cmd */ | 475 | /* Unmap tx_cmd */ |
475 | if (num_tbs) | 476 | if (num_tbs) |
476 | pci_unmap_single(dev, | 477 | pci_unmap_single(dev, |
477 | pci_unmap_addr(&txq->meta[index], mapping), | 478 | dma_unmap_addr(&txq->meta[index], mapping), |
478 | pci_unmap_len(&txq->meta[index], len), | 479 | dma_unmap_len(&txq->meta[index], len), |
479 | PCI_DMA_BIDIRECTIONAL); | 480 | PCI_DMA_BIDIRECTIONAL); |
480 | 481 | ||
481 | /* Unmap chunks, if any. */ | 482 | /* Unmap chunks, if any. */ |
482 | for (i = 1; i < num_tbs; i++) { | 483 | for (i = 1; i < num_tbs; i++) |
483 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | 484 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), |
484 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | 485 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); |
485 | 486 | ||
486 | if (txq->txb) { | 487 | /* free SKB */ |
487 | dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); | 488 | if (txq->txb) { |
488 | txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; | 489 | struct sk_buff *skb; |
490 | |||
491 | skb = txq->txb[txq->q.read_ptr].skb; | ||
492 | |||
493 | /* can be called from irqs-disabled context */ | ||
494 | if (skb) { | ||
495 | dev_kfree_skb_any(skb); | ||
496 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
489 | } | 497 | } |
490 | } | 498 | } |
491 | } | 499 | } |
@@ -1466,7 +1474,12 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1466 | " expected_ack_cnt = %d\n", | 1474 | " expected_ack_cnt = %d\n", |
1467 | actual_ack_cnt_delta, expected_ack_cnt_delta); | 1475 | actual_ack_cnt_delta, expected_ack_cnt_delta); |
1468 | 1476 | ||
1469 | #ifdef CONFIG_IWLWIFI_DEBUG | 1477 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1478 | /* | ||
1479 | * This is ifdef'ed on DEBUGFS because otherwise the | ||
1480 | * statistics aren't available. If DEBUGFS is set but | ||
1481 | * DEBUG is not, these will just compile out. | ||
1482 | */ | ||
1470 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | 1483 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", |
1471 | priv->delta_statistics.tx.rx_detected_cnt); | 1484 | priv->delta_statistics.tx.rx_detected_cnt); |
1472 | IWL_DEBUG_RADIO(priv, | 1485 | IWL_DEBUG_RADIO(priv, |
@@ -1484,6 +1497,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1484 | } | 1497 | } |
1485 | 1498 | ||
1486 | 1499 | ||
1500 | /***************************************************************************** | ||
1501 | * | ||
1502 | * sysfs attributes | ||
1503 | * | ||
1504 | *****************************************************************************/ | ||
1505 | |||
1506 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1507 | |||
1508 | /* | ||
1509 | * The following adds a new attribute to the sysfs representation | ||
1510 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) | ||
1511 | * used for controlling the debug level. | ||
1512 | * | ||
1513 | * See the level definitions in iwl for details. | ||
1514 | * | ||
1515 | * The debug_level being managed using sysfs below is a per device debug | ||
1516 | * level that is used instead of the global debug level if it (the per | ||
1517 | * device debug level) is set. | ||
1518 | */ | ||
1519 | static ssize_t show_debug_level(struct device *d, | ||
1520 | struct device_attribute *attr, char *buf) | ||
1521 | { | ||
1522 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1523 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); | ||
1524 | } | ||
1525 | static ssize_t store_debug_level(struct device *d, | ||
1526 | struct device_attribute *attr, | ||
1527 | const char *buf, size_t count) | ||
1528 | { | ||
1529 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1530 | unsigned long val; | ||
1531 | int ret; | ||
1532 | |||
1533 | ret = strict_strtoul(buf, 0, &val); | ||
1534 | if (ret) | ||
1535 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | ||
1536 | else { | ||
1537 | priv->debug_level = val; | ||
1538 | if (iwl_alloc_traffic_mem(priv)) | ||
1539 | IWL_ERR(priv, | ||
1540 | "Not enough memory to generate traffic log\n"); | ||
1541 | } | ||
1542 | return strnlen(buf, count); | ||
1543 | } | ||
1544 | |||
1545 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
1546 | show_debug_level, store_debug_level); | ||
1547 | |||
1548 | |||
1549 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
1550 | |||
1551 | |||
1552 | static ssize_t show_temperature(struct device *d, | ||
1553 | struct device_attribute *attr, char *buf) | ||
1554 | { | ||
1555 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1556 | |||
1557 | if (!iwl_is_alive(priv)) | ||
1558 | return -EAGAIN; | ||
1559 | |||
1560 | return sprintf(buf, "%d\n", priv->temperature); | ||
1561 | } | ||
1562 | |||
1563 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
1564 | |||
1565 | static ssize_t show_tx_power(struct device *d, | ||
1566 | struct device_attribute *attr, char *buf) | ||
1567 | { | ||
1568 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1569 | |||
1570 | if (!iwl_is_ready_rf(priv)) | ||
1571 | return sprintf(buf, "off\n"); | ||
1572 | else | ||
1573 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
1574 | } | ||
1575 | |||
1576 | static ssize_t store_tx_power(struct device *d, | ||
1577 | struct device_attribute *attr, | ||
1578 | const char *buf, size_t count) | ||
1579 | { | ||
1580 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1581 | unsigned long val; | ||
1582 | int ret; | ||
1583 | |||
1584 | ret = strict_strtoul(buf, 10, &val); | ||
1585 | if (ret) | ||
1586 | IWL_INFO(priv, "%s is not in decimal form.\n", buf); | ||
1587 | else { | ||
1588 | ret = iwl_set_tx_power(priv, val, false); | ||
1589 | if (ret) | ||
1590 | IWL_ERR(priv, "failed setting tx power (0x%d).\n", | ||
1591 | ret); | ||
1592 | else | ||
1593 | ret = count; | ||
1594 | } | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | ||
1599 | |||
1600 | static ssize_t show_rts_ht_protection(struct device *d, | ||
1601 | struct device_attribute *attr, char *buf) | ||
1602 | { | ||
1603 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1604 | |||
1605 | return sprintf(buf, "%s\n", | ||
1606 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | ||
1607 | } | ||
1608 | |||
1609 | static ssize_t store_rts_ht_protection(struct device *d, | ||
1610 | struct device_attribute *attr, | ||
1611 | const char *buf, size_t count) | ||
1612 | { | ||
1613 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1614 | unsigned long val; | ||
1615 | int ret; | ||
1616 | |||
1617 | ret = strict_strtoul(buf, 10, &val); | ||
1618 | if (ret) | ||
1619 | IWL_INFO(priv, "Input is not in decimal form.\n"); | ||
1620 | else { | ||
1621 | if (!iwl_is_associated(priv)) | ||
1622 | priv->cfg->use_rts_for_ht = val ? true : false; | ||
1623 | else | ||
1624 | IWL_ERR(priv, "Sta associated with AP - " | ||
1625 | "Change protection mechanism is not allowed\n"); | ||
1626 | ret = count; | ||
1627 | } | ||
1628 | return ret; | ||
1629 | } | ||
1630 | |||
1631 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
1632 | show_rts_ht_protection, store_rts_ht_protection); | ||
1633 | |||
1634 | |||
1635 | static struct attribute *iwl_sysfs_entries[] = { | ||
1636 | &dev_attr_temperature.attr, | ||
1637 | &dev_attr_tx_power.attr, | ||
1638 | &dev_attr_rts_ht_protection.attr, | ||
1639 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1640 | &dev_attr_debug_level.attr, | ||
1641 | #endif | ||
1642 | NULL | ||
1643 | }; | ||
1644 | |||
1645 | static struct attribute_group iwl_attribute_group = { | ||
1646 | .name = NULL, /* put in device directory */ | ||
1647 | .attrs = iwl_sysfs_entries, | ||
1648 | }; | ||
1649 | |||
1487 | /****************************************************************************** | 1650 | /****************************************************************************** |
1488 | * | 1651 | * |
1489 | * uCode download functions | 1652 | * uCode download functions |
@@ -1544,6 +1707,9 @@ struct iwlagn_firmware_pieces { | |||
1544 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | 1707 | size_t inst_size, data_size, init_size, init_data_size, boot_size; |
1545 | 1708 | ||
1546 | u32 build; | 1709 | u32 build; |
1710 | |||
1711 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1712 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1547 | }; | 1713 | }; |
1548 | 1714 | ||
1549 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | 1715 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, |
@@ -1721,6 +1887,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1721 | capa->max_probe_length = | 1887 | capa->max_probe_length = |
1722 | le32_to_cpup((__le32 *)tlv_data); | 1888 | le32_to_cpup((__le32 *)tlv_data); |
1723 | break; | 1889 | break; |
1890 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
1891 | if (tlv_len != 4) | ||
1892 | return -EINVAL; | ||
1893 | pieces->init_evtlog_ptr = | ||
1894 | le32_to_cpup((__le32 *)tlv_data); | ||
1895 | break; | ||
1896 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
1897 | if (tlv_len != 4) | ||
1898 | return -EINVAL; | ||
1899 | pieces->init_evtlog_size = | ||
1900 | le32_to_cpup((__le32 *)tlv_data); | ||
1901 | break; | ||
1902 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
1903 | if (tlv_len != 4) | ||
1904 | return -EINVAL; | ||
1905 | pieces->init_errlog_ptr = | ||
1906 | le32_to_cpup((__le32 *)tlv_data); | ||
1907 | break; | ||
1908 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
1909 | if (tlv_len != 4) | ||
1910 | return -EINVAL; | ||
1911 | pieces->inst_evtlog_ptr = | ||
1912 | le32_to_cpup((__le32 *)tlv_data); | ||
1913 | break; | ||
1914 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
1915 | if (tlv_len != 4) | ||
1916 | return -EINVAL; | ||
1917 | pieces->inst_evtlog_size = | ||
1918 | le32_to_cpup((__le32 *)tlv_data); | ||
1919 | break; | ||
1920 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
1921 | if (tlv_len != 4) | ||
1922 | return -EINVAL; | ||
1923 | pieces->inst_errlog_ptr = | ||
1924 | le32_to_cpup((__le32 *)tlv_data); | ||
1925 | break; | ||
1724 | default: | 1926 | default: |
1725 | break; | 1927 | break; |
1726 | } | 1928 | } |
@@ -1913,6 +2115,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1913 | goto err_pci_alloc; | 2115 | goto err_pci_alloc; |
1914 | } | 2116 | } |
1915 | 2117 | ||
2118 | /* Now that we can no longer fail, copy information */ | ||
2119 | |||
2120 | /* | ||
2121 | * The (size - 16) / 12 formula is based on the information recorded | ||
2122 | * for each event, which is of mode 1 (including timestamp) for all | ||
2123 | * new microcodes that include this information. | ||
2124 | */ | ||
2125 | priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
2126 | if (pieces.init_evtlog_size) | ||
2127 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
2128 | else | ||
2129 | priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; | ||
2130 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; | ||
2131 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
2132 | if (pieces.inst_evtlog_size) | ||
2133 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
2134 | else | ||
2135 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | ||
2136 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
2137 | |||
1916 | /* Copy images into buffers for card's bus-master reads ... */ | 2138 | /* Copy images into buffers for card's bus-master reads ... */ |
1917 | 2139 | ||
1918 | /* Runtime instructions (first block of data in file) */ | 2140 | /* Runtime instructions (first block of data in file) */ |
@@ -1965,6 +2187,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1965 | if (err) | 2187 | if (err) |
1966 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | 2188 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); |
1967 | 2189 | ||
2190 | err = sysfs_create_group(&priv->pci_dev->dev.kobj, | ||
2191 | &iwl_attribute_group); | ||
2192 | if (err) { | ||
2193 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
2194 | goto out_unbind; | ||
2195 | } | ||
2196 | |||
1968 | /* We have our copies now, allow OS release its copies */ | 2197 | /* We have our copies now, allow OS release its copies */ |
1969 | release_firmware(ucode_raw); | 2198 | release_firmware(ucode_raw); |
1970 | complete(&priv->_agn.firmware_loading_complete); | 2199 | complete(&priv->_agn.firmware_loading_complete); |
@@ -2038,10 +2267,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2038 | u32 blink1, blink2, ilink1, ilink2; | 2267 | u32 blink1, blink2, ilink1, ilink2; |
2039 | u32 pc, hcmd; | 2268 | u32 pc, hcmd; |
2040 | 2269 | ||
2041 | if (priv->ucode_type == UCODE_INIT) | 2270 | if (priv->ucode_type == UCODE_INIT) { |
2042 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 2271 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
2043 | else | 2272 | if (!base) |
2273 | base = priv->_agn.init_errlog_ptr; | ||
2274 | } else { | ||
2044 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 2275 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
2276 | if (!base) | ||
2277 | base = priv->_agn.inst_errlog_ptr; | ||
2278 | } | ||
2045 | 2279 | ||
2046 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2280 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2047 | IWL_ERR(priv, | 2281 | IWL_ERR(priv, |
@@ -2101,10 +2335,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
2101 | 2335 | ||
2102 | if (num_events == 0) | 2336 | if (num_events == 0) |
2103 | return pos; | 2337 | return pos; |
2104 | if (priv->ucode_type == UCODE_INIT) | 2338 | |
2339 | if (priv->ucode_type == UCODE_INIT) { | ||
2105 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2340 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2106 | else | 2341 | if (!base) |
2342 | base = priv->_agn.init_evtlog_ptr; | ||
2343 | } else { | ||
2107 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2344 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2345 | if (!base) | ||
2346 | base = priv->_agn.inst_evtlog_ptr; | ||
2347 | } | ||
2108 | 2348 | ||
2109 | if (mode == 0) | 2349 | if (mode == 0) |
2110 | event_size = 2 * sizeof(u32); | 2350 | event_size = 2 * sizeof(u32); |
@@ -2206,13 +2446,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2206 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 2446 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
2207 | u32 next_entry; /* index of next entry to be written by uCode */ | 2447 | u32 next_entry; /* index of next entry to be written by uCode */ |
2208 | u32 size; /* # entries that we'll print */ | 2448 | u32 size; /* # entries that we'll print */ |
2449 | u32 logsize; | ||
2209 | int pos = 0; | 2450 | int pos = 0; |
2210 | size_t bufsz = 0; | 2451 | size_t bufsz = 0; |
2211 | 2452 | ||
2212 | if (priv->ucode_type == UCODE_INIT) | 2453 | if (priv->ucode_type == UCODE_INIT) { |
2213 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2454 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2214 | else | 2455 | logsize = priv->_agn.init_evtlog_size; |
2456 | if (!base) | ||
2457 | base = priv->_agn.init_evtlog_ptr; | ||
2458 | } else { | ||
2215 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2459 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2460 | logsize = priv->_agn.inst_evtlog_size; | ||
2461 | if (!base) | ||
2462 | base = priv->_agn.inst_evtlog_ptr; | ||
2463 | } | ||
2216 | 2464 | ||
2217 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2465 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2218 | IWL_ERR(priv, | 2466 | IWL_ERR(priv, |
@@ -2227,16 +2475,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2227 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2475 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
2228 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2476 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
2229 | 2477 | ||
2230 | if (capacity > priv->cfg->max_event_log_size) { | 2478 | if (capacity > logsize) { |
2231 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2479 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
2232 | capacity, priv->cfg->max_event_log_size); | 2480 | capacity, logsize); |
2233 | capacity = priv->cfg->max_event_log_size; | 2481 | capacity = logsize; |
2234 | } | 2482 | } |
2235 | 2483 | ||
2236 | if (next_entry > priv->cfg->max_event_log_size) { | 2484 | if (next_entry > logsize) { |
2237 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2485 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
2238 | next_entry, priv->cfg->max_event_log_size); | 2486 | next_entry, logsize); |
2239 | next_entry = priv->cfg->max_event_log_size; | 2487 | next_entry = logsize; |
2240 | } | 2488 | } |
2241 | 2489 | ||
2242 | size = num_wraps ? capacity : next_entry; | 2490 | size = num_wraps ? capacity : next_entry; |
@@ -2361,8 +2609,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2361 | 2609 | ||
2362 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2610 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2363 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2611 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2364 | |||
2365 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | ||
2366 | } | 2612 | } |
2367 | 2613 | ||
2368 | /* Configure Bluetooth device coexistence support */ | 2614 | /* Configure Bluetooth device coexistence support */ |
@@ -2777,20 +3023,16 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2777 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3023 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2778 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3024 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2779 | 3025 | ||
2780 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3026 | if (vif->bss_conf.use_short_preamble) |
2781 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3027 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2782 | else | 3028 | else |
2783 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3029 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2784 | 3030 | ||
2785 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3031 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2786 | if (vif->bss_conf.assoc_capability & | 3032 | if (vif->bss_conf.use_short_slot) |
2787 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2788 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3033 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2789 | else | 3034 | else |
2790 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3035 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2791 | |||
2792 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2793 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
2794 | } | 3036 | } |
2795 | 3037 | ||
2796 | iwlcore_commit_rxon(priv); | 3038 | iwlcore_commit_rxon(priv); |
@@ -3016,8 +3258,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3016 | 3258 | ||
3017 | priv->staging_rxon.assoc_id = 0; | 3259 | priv->staging_rxon.assoc_id = 0; |
3018 | 3260 | ||
3019 | if (vif->bss_conf.assoc_capability & | 3261 | if (vif->bss_conf.use_short_preamble) |
3020 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3021 | priv->staging_rxon.flags |= | 3262 | priv->staging_rxon.flags |= |
3022 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3263 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3023 | else | 3264 | else |
@@ -3025,17 +3266,12 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3025 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3266 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3026 | 3267 | ||
3027 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3268 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3028 | if (vif->bss_conf.assoc_capability & | 3269 | if (vif->bss_conf.use_short_slot) |
3029 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
3030 | priv->staging_rxon.flags |= | 3270 | priv->staging_rxon.flags |= |
3031 | RXON_FLG_SHORT_SLOT_MSK; | 3271 | RXON_FLG_SHORT_SLOT_MSK; |
3032 | else | 3272 | else |
3033 | priv->staging_rxon.flags &= | 3273 | priv->staging_rxon.flags &= |
3034 | ~RXON_FLG_SHORT_SLOT_MSK; | 3274 | ~RXON_FLG_SHORT_SLOT_MSK; |
3035 | |||
3036 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3037 | priv->staging_rxon.flags &= | ||
3038 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3039 | } | 3275 | } |
3040 | /* restore RXON assoc */ | 3276 | /* restore RXON assoc */ |
3041 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3277 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
@@ -3081,17 +3317,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3081 | return -EOPNOTSUPP; | 3317 | return -EOPNOTSUPP; |
3082 | } | 3318 | } |
3083 | 3319 | ||
3084 | if (sta) { | 3320 | sta_id = iwl_sta_id_or_broadcast(priv, sta); |
3085 | sta_id = iwl_sta_id(sta); | 3321 | if (sta_id == IWL_INVALID_STATION) |
3086 | 3322 | return -EINVAL; | |
3087 | if (sta_id == IWL_INVALID_STATION) { | ||
3088 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3089 | sta->addr); | ||
3090 | return -EINVAL; | ||
3091 | } | ||
3092 | } else { | ||
3093 | sta_id = priv->hw_params.bcast_sta_id; | ||
3094 | } | ||
3095 | 3323 | ||
3096 | mutex_lock(&priv->mutex); | 3324 | mutex_lock(&priv->mutex); |
3097 | iwl_scan_cancel_timeout(priv, 100); | 3325 | iwl_scan_cancel_timeout(priv, 100); |
@@ -3262,141 +3490,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3262 | return 0; | 3490 | return 0; |
3263 | } | 3491 | } |
3264 | 3492 | ||
3265 | /***************************************************************************** | 3493 | static void iwl_mac_channel_switch(struct ieee80211_hw *hw, |
3266 | * | 3494 | struct ieee80211_channel_switch *ch_switch) |
3267 | * sysfs attributes | ||
3268 | * | ||
3269 | *****************************************************************************/ | ||
3270 | |||
3271 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3272 | |||
3273 | /* | ||
3274 | * The following adds a new attribute to the sysfs representation | ||
3275 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) | ||
3276 | * used for controlling the debug level. | ||
3277 | * | ||
3278 | * See the level definitions in iwl for details. | ||
3279 | * | ||
3280 | * The debug_level being managed using sysfs below is a per device debug | ||
3281 | * level that is used instead of the global debug level if it (the per | ||
3282 | * device debug level) is set. | ||
3283 | */ | ||
3284 | static ssize_t show_debug_level(struct device *d, | ||
3285 | struct device_attribute *attr, char *buf) | ||
3286 | { | ||
3287 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3288 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); | ||
3289 | } | ||
3290 | static ssize_t store_debug_level(struct device *d, | ||
3291 | struct device_attribute *attr, | ||
3292 | const char *buf, size_t count) | ||
3293 | { | ||
3294 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3295 | unsigned long val; | ||
3296 | int ret; | ||
3297 | |||
3298 | ret = strict_strtoul(buf, 0, &val); | ||
3299 | if (ret) | ||
3300 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | ||
3301 | else { | ||
3302 | priv->debug_level = val; | ||
3303 | if (iwl_alloc_traffic_mem(priv)) | ||
3304 | IWL_ERR(priv, | ||
3305 | "Not enough memory to generate traffic log\n"); | ||
3306 | } | ||
3307 | return strnlen(buf, count); | ||
3308 | } | ||
3309 | |||
3310 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
3311 | show_debug_level, store_debug_level); | ||
3312 | |||
3313 | |||
3314 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
3315 | |||
3316 | |||
3317 | static ssize_t show_temperature(struct device *d, | ||
3318 | struct device_attribute *attr, char *buf) | ||
3319 | { | 3495 | { |
3320 | struct iwl_priv *priv = dev_get_drvdata(d); | 3496 | struct iwl_priv *priv = hw->priv; |
3321 | 3497 | const struct iwl_channel_info *ch_info; | |
3322 | if (!iwl_is_alive(priv)) | 3498 | struct ieee80211_conf *conf = &hw->conf; |
3323 | return -EAGAIN; | 3499 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
3324 | 3500 | u16 ch; | |
3325 | return sprintf(buf, "%d\n", priv->temperature); | 3501 | unsigned long flags = 0; |
3326 | } | ||
3327 | |||
3328 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
3329 | |||
3330 | static ssize_t show_tx_power(struct device *d, | ||
3331 | struct device_attribute *attr, char *buf) | ||
3332 | { | ||
3333 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3334 | |||
3335 | if (!iwl_is_ready_rf(priv)) | ||
3336 | return sprintf(buf, "off\n"); | ||
3337 | else | ||
3338 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
3339 | } | ||
3340 | 3502 | ||
3341 | static ssize_t store_tx_power(struct device *d, | 3503 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
3342 | struct device_attribute *attr, | ||
3343 | const char *buf, size_t count) | ||
3344 | { | ||
3345 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3346 | unsigned long val; | ||
3347 | int ret; | ||
3348 | 3504 | ||
3349 | ret = strict_strtoul(buf, 10, &val); | 3505 | if (iwl_is_rfkill(priv)) |
3350 | if (ret) | 3506 | goto out_exit; |
3351 | IWL_INFO(priv, "%s is not in decimal form.\n", buf); | ||
3352 | else { | ||
3353 | ret = iwl_set_tx_power(priv, val, false); | ||
3354 | if (ret) | ||
3355 | IWL_ERR(priv, "failed setting tx power (0x%d).\n", | ||
3356 | ret); | ||
3357 | else | ||
3358 | ret = count; | ||
3359 | } | ||
3360 | return ret; | ||
3361 | } | ||
3362 | 3507 | ||
3363 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | 3508 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || |
3509 | test_bit(STATUS_SCANNING, &priv->status)) | ||
3510 | goto out_exit; | ||
3364 | 3511 | ||
3365 | static ssize_t show_rts_ht_protection(struct device *d, | 3512 | if (!iwl_is_associated(priv)) |
3366 | struct device_attribute *attr, char *buf) | 3513 | goto out_exit; |
3367 | { | ||
3368 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3369 | 3514 | ||
3370 | return sprintf(buf, "%s\n", | 3515 | /* channel switch in progress */ |
3371 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | 3516 | if (priv->switch_rxon.switch_in_progress == true) |
3372 | } | 3517 | goto out_exit; |
3373 | 3518 | ||
3374 | static ssize_t store_rts_ht_protection(struct device *d, | 3519 | mutex_lock(&priv->mutex); |
3375 | struct device_attribute *attr, | 3520 | if (priv->cfg->ops->lib->set_channel_switch) { |
3376 | const char *buf, size_t count) | 3521 | |
3377 | { | 3522 | ch = ieee80211_frequency_to_channel( |
3378 | struct iwl_priv *priv = dev_get_drvdata(d); | 3523 | ch_switch->channel->center_freq); |
3379 | unsigned long val; | 3524 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { |
3380 | int ret; | 3525 | ch_info = iwl_get_channel_info(priv, |
3381 | 3526 | conf->channel->band, | |
3382 | ret = strict_strtoul(buf, 10, &val); | 3527 | ch); |
3383 | if (ret) | 3528 | if (!is_channel_valid(ch_info)) { |
3384 | IWL_INFO(priv, "Input is not in decimal form.\n"); | 3529 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); |
3385 | else { | 3530 | goto out; |
3386 | if (!iwl_is_associated(priv)) | 3531 | } |
3387 | priv->cfg->use_rts_for_ht = val ? true : false; | 3532 | spin_lock_irqsave(&priv->lock, flags); |
3388 | else | 3533 | |
3389 | IWL_ERR(priv, "Sta associated with AP - " | 3534 | priv->current_ht_config.smps = conf->smps_mode; |
3390 | "Change protection mechanism is not allowed\n"); | 3535 | |
3391 | ret = count; | 3536 | /* Configure HT40 channels */ |
3537 | ht_conf->is_ht = conf_is_ht(conf); | ||
3538 | if (ht_conf->is_ht) { | ||
3539 | if (conf_is_ht40_minus(conf)) { | ||
3540 | ht_conf->extension_chan_offset = | ||
3541 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
3542 | ht_conf->is_40mhz = true; | ||
3543 | } else if (conf_is_ht40_plus(conf)) { | ||
3544 | ht_conf->extension_chan_offset = | ||
3545 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
3546 | ht_conf->is_40mhz = true; | ||
3547 | } else { | ||
3548 | ht_conf->extension_chan_offset = | ||
3549 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
3550 | ht_conf->is_40mhz = false; | ||
3551 | } | ||
3552 | } else | ||
3553 | ht_conf->is_40mhz = false; | ||
3554 | |||
3555 | /* if we are switching from ht to 2.4 clear flags | ||
3556 | * from any ht related info since 2.4 does not | ||
3557 | * support ht */ | ||
3558 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
3559 | priv->staging_rxon.flags = 0; | ||
3560 | |||
3561 | iwl_set_rxon_channel(priv, conf->channel); | ||
3562 | iwl_set_rxon_ht(priv, ht_conf); | ||
3563 | iwl_set_flags_for_band(priv, conf->channel->band, | ||
3564 | priv->vif); | ||
3565 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3566 | |||
3567 | iwl_set_rate(priv); | ||
3568 | /* | ||
3569 | * at this point, staging_rxon has the | ||
3570 | * configuration for channel switch | ||
3571 | */ | ||
3572 | if (priv->cfg->ops->lib->set_channel_switch(priv, | ||
3573 | ch_switch)) | ||
3574 | priv->switch_rxon.switch_in_progress = false; | ||
3575 | } | ||
3392 | } | 3576 | } |
3393 | return ret; | 3577 | out: |
3578 | mutex_unlock(&priv->mutex); | ||
3579 | out_exit: | ||
3580 | if (!priv->switch_rxon.switch_in_progress) | ||
3581 | ieee80211_chswitch_done(priv->vif, false); | ||
3582 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3394 | } | 3583 | } |
3395 | 3584 | ||
3396 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
3397 | show_rts_ht_protection, store_rts_ht_protection); | ||
3398 | |||
3399 | |||
3400 | /***************************************************************************** | 3585 | /***************************************************************************** |
3401 | * | 3586 | * |
3402 | * driver setup and teardown | 3587 | * driver setup and teardown |
@@ -3550,21 +3735,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3550 | kfree(priv->scan_cmd); | 3735 | kfree(priv->scan_cmd); |
3551 | } | 3736 | } |
3552 | 3737 | ||
3553 | static struct attribute *iwl_sysfs_entries[] = { | ||
3554 | &dev_attr_temperature.attr, | ||
3555 | &dev_attr_tx_power.attr, | ||
3556 | &dev_attr_rts_ht_protection.attr, | ||
3557 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3558 | &dev_attr_debug_level.attr, | ||
3559 | #endif | ||
3560 | NULL | ||
3561 | }; | ||
3562 | |||
3563 | static struct attribute_group iwl_attribute_group = { | ||
3564 | .name = NULL, /* put in device directory */ | ||
3565 | .attrs = iwl_sysfs_entries, | ||
3566 | }; | ||
3567 | |||
3568 | static struct ieee80211_ops iwl_hw_ops = { | 3738 | static struct ieee80211_ops iwl_hw_ops = { |
3569 | .tx = iwl_mac_tx, | 3739 | .tx = iwl_mac_tx, |
3570 | .start = iwl_mac_start, | 3740 | .start = iwl_mac_start, |
@@ -3583,6 +3753,7 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3583 | .sta_notify = iwl_mac_sta_notify, | 3753 | .sta_notify = iwl_mac_sta_notify, |
3584 | .sta_add = iwlagn_mac_sta_add, | 3754 | .sta_add = iwlagn_mac_sta_add, |
3585 | .sta_remove = iwl_mac_sta_remove, | 3755 | .sta_remove = iwl_mac_sta_remove, |
3756 | .channel_switch = iwl_mac_channel_switch, | ||
3586 | }; | 3757 | }; |
3587 | 3758 | ||
3588 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3759 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3593,6 +3764,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3593 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 3764 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
3594 | unsigned long flags; | 3765 | unsigned long flags; |
3595 | u16 pci_cmd; | 3766 | u16 pci_cmd; |
3767 | u8 perm_addr[ETH_ALEN]; | ||
3596 | 3768 | ||
3597 | /************************ | 3769 | /************************ |
3598 | * 1. Allocating HW data | 3770 | * 1. Allocating HW data |
@@ -3622,9 +3794,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3622 | priv->pci_dev = pdev; | 3794 | priv->pci_dev = pdev; |
3623 | priv->inta_mask = CSR_INI_SET_MASK; | 3795 | priv->inta_mask = CSR_INI_SET_MASK; |
3624 | 3796 | ||
3625 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3626 | atomic_set(&priv->restrict_refcnt, 0); | ||
3627 | #endif | ||
3628 | if (iwl_alloc_traffic_mem(priv)) | 3797 | if (iwl_alloc_traffic_mem(priv)) |
3629 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3798 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
3630 | 3799 | ||
@@ -3713,9 +3882,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3713 | goto out_free_eeprom; | 3882 | goto out_free_eeprom; |
3714 | 3883 | ||
3715 | /* extract MAC Address */ | 3884 | /* extract MAC Address */ |
3716 | iwl_eeprom_get_mac(priv, priv->mac_addr); | 3885 | iwl_eeprom_get_mac(priv, perm_addr); |
3717 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); | 3886 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); |
3718 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | 3887 | SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); |
3719 | 3888 | ||
3720 | /************************ | 3889 | /************************ |
3721 | * 5. Setup HW constants | 3890 | * 5. Setup HW constants |
@@ -3750,11 +3919,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3750 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); | 3919 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); |
3751 | goto out_disable_msi; | 3920 | goto out_disable_msi; |
3752 | } | 3921 | } |
3753 | err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); | ||
3754 | if (err) { | ||
3755 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
3756 | goto out_free_irq; | ||
3757 | } | ||
3758 | 3922 | ||
3759 | iwl_setup_deferred_work(priv); | 3923 | iwl_setup_deferred_work(priv); |
3760 | iwl_setup_rx_handlers(priv); | 3924 | iwl_setup_rx_handlers(priv); |
@@ -3788,15 +3952,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3788 | 3952 | ||
3789 | err = iwl_request_firmware(priv, true); | 3953 | err = iwl_request_firmware(priv, true); |
3790 | if (err) | 3954 | if (err) |
3791 | goto out_remove_sysfs; | 3955 | goto out_destroy_workqueue; |
3792 | 3956 | ||
3793 | return 0; | 3957 | return 0; |
3794 | 3958 | ||
3795 | out_remove_sysfs: | 3959 | out_destroy_workqueue: |
3796 | destroy_workqueue(priv->workqueue); | 3960 | destroy_workqueue(priv->workqueue); |
3797 | priv->workqueue = NULL; | 3961 | priv->workqueue = NULL; |
3798 | sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); | ||
3799 | out_free_irq: | ||
3800 | free_irq(priv->pci_dev->irq, priv); | 3962 | free_irq(priv->pci_dev->irq, priv); |
3801 | iwl_free_isr_ict(priv); | 3963 | iwl_free_isr_ict(priv); |
3802 | out_disable_msi: | 3964 | out_disable_msi: |
@@ -3989,6 +4151,47 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3989 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, | 4151 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, |
3990 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, | 4152 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, |
3991 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, | 4153 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, |
4154 | {IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)}, | ||
4155 | {IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)}, | ||
4156 | {IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)}, | ||
4157 | {IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)}, | ||
4158 | {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)}, | ||
4159 | {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)}, | ||
4160 | {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)}, | ||
4161 | {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)}, | ||
4162 | {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)}, | ||
4163 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)}, | ||
4164 | {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)}, | ||
4165 | |||
4166 | /* 6x00 Series Gen2b */ | ||
4167 | {IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)}, | ||
4168 | {IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)}, | ||
4169 | {IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)}, | ||
4170 | {IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)}, | ||
4171 | {IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4172 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4173 | {IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4174 | {IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4175 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4176 | {IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
4177 | {IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4178 | {IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)}, | ||
4179 | {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)}, | ||
4180 | {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)}, | ||
4181 | {IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)}, | ||
4182 | {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)}, | ||
4183 | {IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)}, | ||
4184 | {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)}, | ||
4185 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4186 | {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)}, | ||
4187 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4188 | {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4189 | {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)}, | ||
4190 | {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4191 | {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4192 | {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4193 | {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)}, | ||
4194 | {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
3992 | 4195 | ||
3993 | /* 6x50 WiFi/WiMax Series */ | 4196 | /* 6x50 WiFi/WiMax Series */ |
3994 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 4197 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2d748053358..5c32777b0a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -65,6 +65,33 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | 67 | ||
68 | /* configuration for the _agn devices */ | ||
69 | extern struct iwl_cfg iwl4965_agn_cfg; | ||
70 | extern struct iwl_cfg iwl5300_agn_cfg; | ||
71 | extern struct iwl_cfg iwl5100_agn_cfg; | ||
72 | extern struct iwl_cfg iwl5350_agn_cfg; | ||
73 | extern struct iwl_cfg iwl5100_bgn_cfg; | ||
74 | extern struct iwl_cfg iwl5100_abg_cfg; | ||
75 | extern struct iwl_cfg iwl5150_agn_cfg; | ||
76 | extern struct iwl_cfg iwl5150_abg_cfg; | ||
77 | extern struct iwl_cfg iwl6000g2a_2agn_cfg; | ||
78 | extern struct iwl_cfg iwl6000g2a_2abg_cfg; | ||
79 | extern struct iwl_cfg iwl6000g2a_2bg_cfg; | ||
80 | extern struct iwl_cfg iwl6000g2b_bgn_cfg; | ||
81 | extern struct iwl_cfg iwl6000g2b_bg_cfg; | ||
82 | extern struct iwl_cfg iwl6000g2b_2agn_cfg; | ||
83 | extern struct iwl_cfg iwl6000g2b_2abg_cfg; | ||
84 | extern struct iwl_cfg iwl6000g2b_2bgn_cfg; | ||
85 | extern struct iwl_cfg iwl6000g2b_2bg_cfg; | ||
86 | extern struct iwl_cfg iwl6000i_2agn_cfg; | ||
87 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
88 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
89 | extern struct iwl_cfg iwl6000_3agn_cfg; | ||
90 | extern struct iwl_cfg iwl6050_2agn_cfg; | ||
91 | extern struct iwl_cfg iwl6050_2abg_cfg; | ||
92 | extern struct iwl_cfg iwl1000_bgn_cfg; | ||
93 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
94 | |||
68 | extern struct iwl_mod_params iwlagn_mod_params; | 95 | extern struct iwl_mod_params iwlagn_mod_params; |
69 | extern struct iwl_hcmd_ops iwlagn_hcmd; | 96 | extern struct iwl_hcmd_ops iwlagn_hcmd; |
70 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | 97 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; |
@@ -93,6 +120,8 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
93 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | 120 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, |
94 | u16 ssn_idx, u8 tx_fifo); | 121 | u16 ssn_idx, u8 tx_fifo); |
95 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | 122 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); |
123 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
124 | int sta_id, int tid, int freed); | ||
96 | 125 | ||
97 | /* uCode */ | 126 | /* uCode */ |
98 | int iwlagn_load_ucode(struct iwl_priv *priv); | 127 | int iwlagn_load_ucode(struct iwl_priv *priv); |
@@ -102,6 +131,7 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, | |||
102 | struct iwl_rx_mem_buffer *rxb); | 131 | struct iwl_rx_mem_buffer *rxb); |
103 | void iwlagn_init_alive_start(struct iwl_priv *priv); | 132 | void iwlagn_init_alive_start(struct iwl_priv *priv); |
104 | int iwlagn_alive_notify(struct iwl_priv *priv); | 133 | int iwlagn_alive_notify(struct iwl_priv *priv); |
134 | int iwl_verify_ucode(struct iwl_priv *priv); | ||
105 | 135 | ||
106 | /* lib */ | 136 | /* lib */ |
107 | void iwl_check_abort_status(struct iwl_priv *priv, | 137 | void iwl_check_abort_status(struct iwl_priv *priv, |
@@ -178,4 +208,8 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | |||
178 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 208 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
179 | struct ieee80211_vif *vif, bool add); | 209 | struct ieee80211_vif *vif, bool add); |
180 | 210 | ||
211 | /* hcmd */ | ||
212 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv); | ||
213 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); | ||
214 | |||
181 | #endif /* __iwl_agn_h__ */ | 215 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 73d2d59bc1d..c579965ec55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -95,7 +95,7 @@ enum { | |||
95 | 95 | ||
96 | /* Multi-Station support */ | 96 | /* Multi-Station support */ |
97 | REPLY_ADD_STA = 0x18, | 97 | REPLY_ADD_STA = 0x18, |
98 | REPLY_REMOVE_STA = 0x19, /* not used */ | 98 | REPLY_REMOVE_STA = 0x19, |
99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ | 99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ |
100 | 100 | ||
101 | /* Security */ | 101 | /* Security */ |
@@ -952,7 +952,6 @@ struct iwl_qosparam_cmd { | |||
952 | 952 | ||
953 | /* Special, dedicated locations within device's station table */ | 953 | /* Special, dedicated locations within device's station table */ |
954 | #define IWL_AP_ID 0 | 954 | #define IWL_AP_ID 0 |
955 | #define IWL_MULTICAST_ID 1 | ||
956 | #define IWL_STA_ID 2 | 955 | #define IWL_STA_ID 2 |
957 | #define IWL3945_BROADCAST_ID 24 | 956 | #define IWL3945_BROADCAST_ID 24 |
958 | #define IWL3945_STATION_COUNT 25 | 957 | #define IWL3945_STATION_COUNT 25 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5a7eca8fb78..62c50bc0089 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -141,13 +141,14 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
143 | 143 | ||
144 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | 144 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) |
145 | { | 145 | { |
146 | int i; | 146 | int i; |
147 | u8 ind = ant; | 147 | u8 ind = ant; |
148 | |||
148 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { | 149 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { |
149 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; | 150 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; |
150 | if (priv->hw_params.valid_tx_ant & BIT(ind)) | 151 | if (valid & BIT(ind)) |
151 | return ind; | 152 | return ind; |
152 | } | 153 | } |
153 | return ant; | 154 | return ant; |
@@ -457,7 +458,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
457 | if (!sta_ht_inf->ht_supported) | 458 | if (!sta_ht_inf->ht_supported) |
458 | return 0; | 459 | return 0; |
459 | } | 460 | } |
460 | #ifdef CONFIG_IWLWIFI_DEBUG | 461 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
461 | if (priv->disable_ht40) | 462 | if (priv->disable_ht40) |
462 | return 0; | 463 | return 0; |
463 | #endif | 464 | #endif |
@@ -506,11 +507,11 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
506 | } | 507 | } |
507 | 508 | ||
508 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | 509 | beacon_int = iwl_adjust_beacon_interval(beacon_int, |
509 | priv->hw_params.max_beacon_itrvl * 1024); | 510 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); |
510 | priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); | 511 | priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); |
511 | 512 | ||
512 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ | 513 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ |
513 | interval_tm = beacon_int * 1024; | 514 | interval_tm = beacon_int * TIME_UNIT; |
514 | rem = do_div(tsf, interval_tm); | 515 | rem = do_div(tsf, interval_tm); |
515 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 516 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
516 | 517 | ||
@@ -854,6 +855,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
854 | } | 855 | } |
855 | EXPORT_SYMBOL(iwl_set_rxon_chain); | 856 | EXPORT_SYMBOL(iwl_set_rxon_chain); |
856 | 857 | ||
858 | /* Return valid channel */ | ||
859 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||
860 | enum ieee80211_band band) | ||
861 | { | ||
862 | const struct iwl_channel_info *ch_info; | ||
863 | int i; | ||
864 | u8 channel = 0; | ||
865 | |||
866 | /* only scan single channel, good enough to reset the RF */ | ||
867 | /* pick the first valid not in-use channel */ | ||
868 | if (band == IEEE80211_BAND_5GHZ) { | ||
869 | for (i = 14; i < priv->channel_count; i++) { | ||
870 | if (priv->channel_info[i].channel != | ||
871 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
872 | channel = priv->channel_info[i].channel; | ||
873 | ch_info = iwl_get_channel_info(priv, | ||
874 | band, channel); | ||
875 | if (is_channel_valid(ch_info)) | ||
876 | break; | ||
877 | } | ||
878 | } | ||
879 | } else { | ||
880 | for (i = 0; i < 14; i++) { | ||
881 | if (priv->channel_info[i].channel != | ||
882 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
883 | channel = | ||
884 | priv->channel_info[i].channel; | ||
885 | ch_info = iwl_get_channel_info(priv, | ||
886 | band, channel); | ||
887 | if (is_channel_valid(ch_info)) | ||
888 | break; | ||
889 | } | ||
890 | } | ||
891 | } | ||
892 | |||
893 | return channel; | ||
894 | } | ||
895 | EXPORT_SYMBOL(iwl_get_single_channel_number); | ||
896 | |||
857 | /** | 897 | /** |
858 | * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON | 898 | * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON |
859 | * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz | 899 | * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz |
@@ -893,9 +933,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | |||
893 | } | 933 | } |
894 | EXPORT_SYMBOL(iwl_set_rxon_channel); | 934 | EXPORT_SYMBOL(iwl_set_rxon_channel); |
895 | 935 | ||
896 | static void iwl_set_flags_for_band(struct iwl_priv *priv, | 936 | void iwl_set_flags_for_band(struct iwl_priv *priv, |
897 | enum ieee80211_band band, | 937 | enum ieee80211_band band, |
898 | struct ieee80211_vif *vif) | 938 | struct ieee80211_vif *vif) |
899 | { | 939 | { |
900 | if (band == IEEE80211_BAND_5GHZ) { | 940 | if (band == IEEE80211_BAND_5GHZ) { |
901 | priv->staging_rxon.flags &= | 941 | priv->staging_rxon.flags &= |
@@ -904,19 +944,17 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
904 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 944 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
905 | } else { | 945 | } else { |
906 | /* Copied from iwl_post_associate() */ | 946 | /* Copied from iwl_post_associate() */ |
907 | if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 947 | if (vif && vif->bss_conf.use_short_slot) |
908 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 948 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
909 | else | 949 | else |
910 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 950 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
911 | 951 | ||
912 | if (vif && vif->type == NL80211_IFTYPE_ADHOC) | ||
913 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
914 | |||
915 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; | 952 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; |
916 | priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; | 953 | priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; |
917 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; | 954 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; |
918 | } | 955 | } |
919 | } | 956 | } |
957 | EXPORT_SYMBOL(iwl_set_flags_for_band); | ||
920 | 958 | ||
921 | /* | 959 | /* |
922 | * initialize rxon structure with default values from eeprom | 960 | * initialize rxon structure with default values from eeprom |
@@ -982,15 +1020,17 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
982 | /* clear both MIX and PURE40 mode flag */ | 1020 | /* clear both MIX and PURE40 mode flag */ |
983 | priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | 1021 | priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | |
984 | RXON_FLG_CHANNEL_MODE_PURE_40); | 1022 | RXON_FLG_CHANNEL_MODE_PURE_40); |
985 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | 1023 | |
986 | memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); | 1024 | if (vif) |
1025 | memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN); | ||
1026 | |||
987 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; | 1027 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; |
988 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; | 1028 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; |
989 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; | 1029 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; |
990 | } | 1030 | } |
991 | EXPORT_SYMBOL(iwl_connection_init_rx_config); | 1031 | EXPORT_SYMBOL(iwl_connection_init_rx_config); |
992 | 1032 | ||
993 | static void iwl_set_rate(struct iwl_priv *priv) | 1033 | void iwl_set_rate(struct iwl_priv *priv) |
994 | { | 1034 | { |
995 | const struct ieee80211_supported_band *hw = NULL; | 1035 | const struct ieee80211_supported_band *hw = NULL; |
996 | struct ieee80211_rate *rate; | 1036 | struct ieee80211_rate *rate; |
@@ -1018,6 +1058,21 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1018 | priv->staging_rxon.ofdm_basic_rates = | 1058 | priv->staging_rxon.ofdm_basic_rates = |
1019 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1059 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1020 | } | 1060 | } |
1061 | EXPORT_SYMBOL(iwl_set_rate); | ||
1062 | |||
1063 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | ||
1064 | { | ||
1065 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
1066 | return; | ||
1067 | |||
1068 | if (priv->switch_rxon.switch_in_progress) { | ||
1069 | ieee80211_chswitch_done(priv->vif, is_success); | ||
1070 | mutex_lock(&priv->mutex); | ||
1071 | priv->switch_rxon.switch_in_progress = false; | ||
1072 | mutex_unlock(&priv->mutex); | ||
1073 | } | ||
1074 | } | ||
1075 | EXPORT_SYMBOL(iwl_chswitch_done); | ||
1021 | 1076 | ||
1022 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1077 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1023 | { | 1078 | { |
@@ -1032,11 +1087,12 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1032 | priv->staging_rxon.channel = csa->channel; | 1087 | priv->staging_rxon.channel = csa->channel; |
1033 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | 1088 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", |
1034 | le16_to_cpu(csa->channel)); | 1089 | le16_to_cpu(csa->channel)); |
1035 | } else | 1090 | iwl_chswitch_done(priv, true); |
1091 | } else { | ||
1036 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | 1092 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", |
1037 | le16_to_cpu(csa->channel)); | 1093 | le16_to_cpu(csa->channel)); |
1038 | 1094 | iwl_chswitch_done(priv, false); | |
1039 | priv->switch_rxon.switch_in_progress = false; | 1095 | } |
1040 | } | 1096 | } |
1041 | } | 1097 | } |
1042 | EXPORT_SYMBOL(iwl_rx_csa); | 1098 | EXPORT_SYMBOL(iwl_rx_csa); |
@@ -1463,130 +1519,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1463 | } | 1519 | } |
1464 | EXPORT_SYMBOL(iwl_send_statistics_request); | 1520 | EXPORT_SYMBOL(iwl_send_statistics_request); |
1465 | 1521 | ||
1466 | /** | ||
1467 | * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
1468 | * using sample data 100 bytes apart. If these sample points are good, | ||
1469 | * it's a pretty good bet that everything between them is good, too. | ||
1470 | */ | ||
1471 | static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) | ||
1472 | { | ||
1473 | u32 val; | ||
1474 | int ret = 0; | ||
1475 | u32 errcnt = 0; | ||
1476 | u32 i; | ||
1477 | |||
1478 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
1479 | |||
1480 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
1481 | /* read data comes through single port, auto-incr addr */ | ||
1482 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
1483 | * if IWL_DL_IO is set */ | ||
1484 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
1485 | i + IWL49_RTC_INST_LOWER_BOUND); | ||
1486 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1487 | if (val != le32_to_cpu(*image)) { | ||
1488 | ret = -EIO; | ||
1489 | errcnt++; | ||
1490 | if (errcnt >= 3) | ||
1491 | break; | ||
1492 | } | ||
1493 | } | ||
1494 | |||
1495 | return ret; | ||
1496 | } | ||
1497 | |||
1498 | /** | ||
1499 | * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, | ||
1500 | * looking at all data. | ||
1501 | */ | ||
1502 | static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, | ||
1503 | u32 len) | ||
1504 | { | ||
1505 | u32 val; | ||
1506 | u32 save_len = len; | ||
1507 | int ret = 0; | ||
1508 | u32 errcnt; | ||
1509 | |||
1510 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
1511 | |||
1512 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
1513 | IWL49_RTC_INST_LOWER_BOUND); | ||
1514 | |||
1515 | errcnt = 0; | ||
1516 | for (; len > 0; len -= sizeof(u32), image++) { | ||
1517 | /* read data comes through single port, auto-incr addr */ | ||
1518 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
1519 | * if IWL_DL_IO is set */ | ||
1520 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1521 | if (val != le32_to_cpu(*image)) { | ||
1522 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
1523 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
1524 | save_len - len, val, le32_to_cpu(*image)); | ||
1525 | ret = -EIO; | ||
1526 | errcnt++; | ||
1527 | if (errcnt >= 20) | ||
1528 | break; | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | if (!errcnt) | ||
1533 | IWL_DEBUG_INFO(priv, | ||
1534 | "ucode image in INSTRUCTION memory is good\n"); | ||
1535 | |||
1536 | return ret; | ||
1537 | } | ||
1538 | |||
1539 | /** | ||
1540 | * iwl_verify_ucode - determine which instruction image is in SRAM, | ||
1541 | * and verify its contents | ||
1542 | */ | ||
1543 | int iwl_verify_ucode(struct iwl_priv *priv) | ||
1544 | { | ||
1545 | __le32 *image; | ||
1546 | u32 len; | ||
1547 | int ret; | ||
1548 | |||
1549 | /* Try bootstrap */ | ||
1550 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
1551 | len = priv->ucode_boot.len; | ||
1552 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1553 | if (!ret) { | ||
1554 | IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); | ||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | /* Try initialize */ | ||
1559 | image = (__le32 *)priv->ucode_init.v_addr; | ||
1560 | len = priv->ucode_init.len; | ||
1561 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1562 | if (!ret) { | ||
1563 | IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); | ||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1567 | /* Try runtime/protocol */ | ||
1568 | image = (__le32 *)priv->ucode_code.v_addr; | ||
1569 | len = priv->ucode_code.len; | ||
1570 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1571 | if (!ret) { | ||
1572 | IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); | ||
1573 | return 0; | ||
1574 | } | ||
1575 | |||
1576 | IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); | ||
1577 | |||
1578 | /* Since nothing seems to match, show first several data entries in | ||
1579 | * instruction SRAM, so maybe visual inspection will give a clue. | ||
1580 | * Selection of bootstrap image (vs. other images) is arbitrary. */ | ||
1581 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
1582 | len = priv->ucode_boot.len; | ||
1583 | ret = iwl_verify_inst_full(priv, image, len); | ||
1584 | |||
1585 | return ret; | ||
1586 | } | ||
1587 | EXPORT_SYMBOL(iwl_verify_ucode); | ||
1588 | |||
1589 | |||
1590 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 1522 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
1591 | { | 1523 | { |
1592 | struct iwl_ct_kill_config cmd; | 1524 | struct iwl_ct_kill_config cmd; |
@@ -2007,8 +1939,6 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2007 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1939 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2008 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1940 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2009 | 1941 | ||
2010 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | ||
2011 | |||
2012 | return iwlcore_commit_rxon(priv); | 1942 | return iwlcore_commit_rxon(priv); |
2013 | } | 1943 | } |
2014 | 1944 | ||
@@ -2017,7 +1947,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2017 | struct iwl_priv *priv = hw->priv; | 1947 | struct iwl_priv *priv = hw->priv; |
2018 | int err = 0; | 1948 | int err = 0; |
2019 | 1949 | ||
2020 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); | 1950 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
1951 | vif->type, vif->addr); | ||
2021 | 1952 | ||
2022 | mutex_lock(&priv->mutex); | 1953 | mutex_lock(&priv->mutex); |
2023 | 1954 | ||
@@ -2035,9 +1966,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2035 | priv->vif = vif; | 1966 | priv->vif = vif; |
2036 | priv->iw_mode = vif->type; | 1967 | priv->iw_mode = vif->type; |
2037 | 1968 | ||
2038 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); | ||
2039 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); | ||
2040 | |||
2041 | err = iwl_set_mode(priv, vif); | 1969 | err = iwl_set_mode(priv, vif); |
2042 | if (err) | 1970 | if (err) |
2043 | goto out_err; | 1971 | goto out_err; |
@@ -2071,6 +1999,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2071 | } | 1999 | } |
2072 | if (priv->vif == vif) { | 2000 | if (priv->vif == vif) { |
2073 | priv->vif = NULL; | 2001 | priv->vif = NULL; |
2002 | if (priv->scan_vif == vif) { | ||
2003 | ieee80211_scan_completed(priv->hw, true); | ||
2004 | priv->scan_vif = NULL; | ||
2005 | priv->scan_request = NULL; | ||
2006 | } | ||
2074 | memset(priv->bssid, 0, ETH_ALEN); | 2007 | memset(priv->bssid, 0, ETH_ALEN); |
2075 | } | 2008 | } |
2076 | mutex_unlock(&priv->mutex); | 2009 | mutex_unlock(&priv->mutex); |
@@ -2171,22 +2104,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2171 | 2104 | ||
2172 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); | 2105 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); |
2173 | spin_unlock_irqrestore(&priv->lock, flags); | 2106 | spin_unlock_irqrestore(&priv->lock, flags); |
2174 | if (iwl_is_associated(priv) && | 2107 | |
2175 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2176 | priv->cfg->ops->lib->set_channel_switch) { | ||
2177 | iwl_set_rate(priv); | ||
2178 | /* | ||
2179 | * at this point, staging_rxon has the | ||
2180 | * configuration for channel switch | ||
2181 | */ | ||
2182 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2183 | ch); | ||
2184 | if (!ret) { | ||
2185 | iwl_print_rx_config_cmd(priv); | ||
2186 | goto out; | ||
2187 | } | ||
2188 | priv->switch_rxon.switch_in_progress = false; | ||
2189 | } | ||
2190 | set_ch_out: | 2108 | set_ch_out: |
2191 | /* The list of supported rates and rate mask can be different | 2109 | /* The list of supported rates and rate mask can be different |
2192 | * for each band; since the band may have changed, reset | 2110 | * for each band; since the band may have changed, reset |
@@ -2544,7 +2462,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
2544 | EXPORT_SYMBOL(iwl_update_stats); | 2462 | EXPORT_SYMBOL(iwl_update_stats); |
2545 | #endif | 2463 | #endif |
2546 | 2464 | ||
2547 | const static char *get_csr_string(int cmd) | 2465 | static const char *get_csr_string(int cmd) |
2548 | { | 2466 | { |
2549 | switch (cmd) { | 2467 | switch (cmd) { |
2550 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | 2468 | IWL_CMD(CSR_HW_IF_CONFIG_REG); |
@@ -2615,7 +2533,7 @@ void iwl_dump_csr(struct iwl_priv *priv) | |||
2615 | } | 2533 | } |
2616 | EXPORT_SYMBOL(iwl_dump_csr); | 2534 | EXPORT_SYMBOL(iwl_dump_csr); |
2617 | 2535 | ||
2618 | const static char *get_fh_string(int cmd) | 2536 | static const char *get_fh_string(int cmd) |
2619 | { | 2537 | { |
2620 | switch (cmd) { | 2538 | switch (cmd) { |
2621 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | 2539 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); |
@@ -2837,6 +2755,61 @@ void iwl_bg_monitor_recover(unsigned long data) | |||
2837 | } | 2755 | } |
2838 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | 2756 | EXPORT_SYMBOL(iwl_bg_monitor_recover); |
2839 | 2757 | ||
2758 | |||
2759 | /* | ||
2760 | * extended beacon time format | ||
2761 | * time in usec will be changed into a 32-bit value in extended:internal format | ||
2762 | * the extended part is the beacon counts | ||
2763 | * the internal part is the time in usec within one beacon interval | ||
2764 | */ | ||
2765 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) | ||
2766 | { | ||
2767 | u32 quot; | ||
2768 | u32 rem; | ||
2769 | u32 interval = beacon_interval * TIME_UNIT; | ||
2770 | |||
2771 | if (!interval || !usec) | ||
2772 | return 0; | ||
2773 | |||
2774 | quot = (usec / interval) & | ||
2775 | (iwl_beacon_time_mask_high(priv, | ||
2776 | priv->hw_params.beacon_time_tsf_bits) >> | ||
2777 | priv->hw_params.beacon_time_tsf_bits); | ||
2778 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | ||
2779 | priv->hw_params.beacon_time_tsf_bits); | ||
2780 | |||
2781 | return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; | ||
2782 | } | ||
2783 | EXPORT_SYMBOL(iwl_usecs_to_beacons); | ||
2784 | |||
2785 | /* base is usually what we get from ucode with each received frame, | ||
2786 | * the same as HW timer counter counting down | ||
2787 | */ | ||
2788 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
2789 | u32 addon, u32 beacon_interval) | ||
2790 | { | ||
2791 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | ||
2792 | priv->hw_params.beacon_time_tsf_bits); | ||
2793 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | ||
2794 | priv->hw_params.beacon_time_tsf_bits); | ||
2795 | u32 interval = beacon_interval * TIME_UNIT; | ||
2796 | u32 res = (base & iwl_beacon_time_mask_high(priv, | ||
2797 | priv->hw_params.beacon_time_tsf_bits)) + | ||
2798 | (addon & iwl_beacon_time_mask_high(priv, | ||
2799 | priv->hw_params.beacon_time_tsf_bits)); | ||
2800 | |||
2801 | if (base_low > addon_low) | ||
2802 | res += base_low - addon_low; | ||
2803 | else if (base_low < addon_low) { | ||
2804 | res += interval + base_low - addon_low; | ||
2805 | res += (1 << priv->hw_params.beacon_time_tsf_bits); | ||
2806 | } else | ||
2807 | res += (1 << priv->hw_params.beacon_time_tsf_bits); | ||
2808 | |||
2809 | return cpu_to_le32(res); | ||
2810 | } | ||
2811 | EXPORT_SYMBOL(iwl_add_beacon_time); | ||
2812 | |||
2840 | #ifdef CONFIG_PM | 2813 | #ifdef CONFIG_PM |
2841 | 2814 | ||
2842 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 2815 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7e5a5ba41fd..76288c56a7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -79,6 +79,8 @@ struct iwl_cmd; | |||
79 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ | 79 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ |
80 | .driver_data = (kernel_ulong_t)&(cfg) | 80 | .driver_data = (kernel_ulong_t)&(cfg) |
81 | 81 | ||
82 | #define TIME_UNIT 1024 | ||
83 | |||
82 | #define IWL_SKU_G 0x1 | 84 | #define IWL_SKU_G 0x1 |
83 | #define IWL_SKU_A 0x2 | 85 | #define IWL_SKU_A 0x2 |
84 | #define IWL_SKU_N 0x8 | 86 | #define IWL_SKU_N 0x8 |
@@ -173,7 +175,8 @@ struct iwl_lib_ops { | |||
173 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 175 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
174 | void (*dump_csr)(struct iwl_priv *priv); | 176 | void (*dump_csr)(struct iwl_priv *priv); |
175 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); | 177 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); |
176 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 178 | int (*set_channel_switch)(struct iwl_priv *priv, |
179 | struct ieee80211_channel_switch *ch_switch); | ||
177 | /* power management */ | 180 | /* power management */ |
178 | struct iwl_apm_ops apm_ops; | 181 | struct iwl_apm_ops apm_ops; |
179 | 182 | ||
@@ -325,7 +328,8 @@ struct iwl_cfg { | |||
325 | const bool ucode_tracing; | 328 | const bool ucode_tracing; |
326 | const bool sensitivity_calib_by_driver; | 329 | const bool sensitivity_calib_by_driver; |
327 | const bool chain_noise_calib_by_driver; | 330 | const bool chain_noise_calib_by_driver; |
328 | u8 scan_antennas[IEEE80211_NUM_BANDS]; | 331 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; |
332 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; | ||
329 | }; | 333 | }; |
330 | 334 | ||
331 | /*************************** | 335 | /*************************** |
@@ -343,11 +347,17 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); | |||
343 | int iwl_full_rxon_required(struct iwl_priv *priv); | 347 | int iwl_full_rxon_required(struct iwl_priv *priv); |
344 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 348 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
345 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | 349 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); |
350 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
351 | enum ieee80211_band band, | ||
352 | struct ieee80211_vif *vif); | ||
353 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||
354 | enum ieee80211_band band); | ||
346 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | 355 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
347 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 356 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
348 | struct ieee80211_sta_ht_cap *sta_ht_inf); | 357 | struct ieee80211_sta_ht_cap *sta_ht_inf); |
349 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 358 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
350 | struct ieee80211_vif *vif); | 359 | struct ieee80211_vif *vif); |
360 | void iwl_set_rate(struct iwl_priv *priv); | ||
351 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | 361 | int iwl_set_decrypted_flag(struct iwl_priv *priv, |
352 | struct ieee80211_hdr *hdr, | 362 | struct ieee80211_hdr *hdr, |
353 | u32 decrypt_res, | 363 | u32 decrypt_res, |
@@ -459,6 +469,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
459 | struct iwl_rx_mem_buffer *rxb); | 469 | struct iwl_rx_mem_buffer *rxb); |
460 | void iwl_reply_statistics(struct iwl_priv *priv, | 470 | void iwl_reply_statistics(struct iwl_priv *priv, |
461 | struct iwl_rx_mem_buffer *rxb); | 471 | struct iwl_rx_mem_buffer *rxb); |
472 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | ||
462 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 473 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
463 | 474 | ||
464 | /* TX helpers */ | 475 | /* TX helpers */ |
@@ -472,8 +483,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
472 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 483 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
473 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 484 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
474 | struct iwl_tx_queue *txq); | 485 | struct iwl_tx_queue *txq); |
475 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
476 | int sta_id, int tid, int freed); | ||
477 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 486 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
478 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 487 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
479 | int slots_num, u32 txq_id); | 488 | int slots_num, u32 txq_id); |
@@ -493,7 +502,7 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | |||
493 | 502 | ||
494 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 503 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
495 | 504 | ||
496 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); | 505 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); |
497 | 506 | ||
498 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) | 507 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) |
499 | { | 508 | { |
@@ -526,7 +535,7 @@ void iwl_bg_start_internal_scan(struct work_struct *work); | |||
526 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | 535 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); |
527 | int iwl_force_reset(struct iwl_priv *priv, int mode); | 536 | int iwl_force_reset(struct iwl_priv *priv, int mode); |
528 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 537 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
529 | const u8 *ie, int ie_len, int left); | 538 | const u8 *ta, const u8 *ie, int ie_len, int left); |
530 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 539 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
531 | u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 540 | u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
532 | enum ieee80211_band band, | 541 | enum ieee80211_band band, |
@@ -593,6 +602,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | |||
593 | } | 602 | } |
594 | 603 | ||
595 | void iwl_bg_monitor_recover(unsigned long data); | 604 | void iwl_bg_monitor_recover(unsigned long data); |
605 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); | ||
606 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
607 | u32 addon, u32 beacon_interval); | ||
596 | 608 | ||
597 | #ifdef CONFIG_PM | 609 | #ifdef CONFIG_PM |
598 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); | 610 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); |
@@ -691,7 +703,6 @@ extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | |||
691 | extern void iwl_send_bt_config(struct iwl_priv *priv); | 703 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
692 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 704 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
693 | u8 flags, bool clear); | 705 | u8 flags, bool clear); |
694 | extern int iwl_verify_ucode(struct iwl_priv *priv); | ||
695 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 706 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
696 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); | 707 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
697 | void iwl_apm_stop(struct iwl_priv *priv); | 708 | void iwl_apm_stop(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 9659c5d01df..d9f21bb9d75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -106,27 +106,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
106 | .open = iwl_dbgfs_open_file_generic, \ | 106 | .open = iwl_dbgfs_open_file_generic, \ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
110 | { | ||
111 | int p = 0; | ||
112 | |||
113 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
114 | le32_to_cpu(priv->statistics.flag)); | ||
115 | if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) | ||
116 | p += scnprintf(buf + p, bufsz - p, | ||
117 | "\tStatistics have been cleared\n"); | ||
118 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
119 | (le32_to_cpu(priv->statistics.flag) & | ||
120 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
121 | ? "2.4 GHz" : "5.2 GHz"); | ||
122 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
123 | (le32_to_cpu(priv->statistics.flag) & | ||
124 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
125 | ? "enabled" : "disabled"); | ||
126 | return p; | ||
127 | } | ||
128 | EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); | ||
129 | |||
130 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | 109 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, |
131 | char __user *user_buf, | 110 | char __user *user_buf, |
132 | size_t count, loff_t *ppos) { | 111 | size_t count, loff_t *ppos) { |
@@ -330,45 +309,35 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
330 | 309 | ||
331 | for (i = 0; i < max_sta; i++) { | 310 | for (i = 0; i < max_sta; i++) { |
332 | station = &priv->stations[i]; | 311 | station = &priv->stations[i]; |
333 | if (station->used) { | 312 | if (!station->used) |
334 | pos += scnprintf(buf + pos, bufsz - pos, | 313 | continue; |
335 | "station %d:\ngeneral data:\n", i+1); | 314 | pos += scnprintf(buf + pos, bufsz - pos, |
336 | pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", | 315 | "station %d - addr: %pM, flags: %#x\n", |
337 | station->sta.sta.sta_id); | 316 | i, station->sta.sta.addr, |
338 | pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", | 317 | station->sta.station_flags_msk); |
339 | station->sta.mode); | 318 | pos += scnprintf(buf + pos, bufsz - pos, |
340 | pos += scnprintf(buf + pos, bufsz - pos, | 319 | "TID\tseq_num\ttxq_id\tframes\ttfds\t"); |
341 | "flags: 0x%x\n", | 320 | pos += scnprintf(buf + pos, bufsz - pos, |
342 | station->sta.station_flags_msk); | 321 | "start_idx\tbitmap\t\t\trate_n_flags\n"); |
343 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | ||
344 | pos += scnprintf(buf + pos, bufsz - pos, | ||
345 | "seq_num\t\ttxq_id"); | ||
346 | pos += scnprintf(buf + pos, bufsz - pos, | ||
347 | "\tframe_count\twait_for_ba\t"); | ||
348 | pos += scnprintf(buf + pos, bufsz - pos, | ||
349 | "start_idx\tbitmap0\t"); | ||
350 | pos += scnprintf(buf + pos, bufsz - pos, | ||
351 | "bitmap1\trate_n_flags"); | ||
352 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
353 | 322 | ||
354 | for (j = 0; j < MAX_TID_COUNT; j++) { | 323 | for (j = 0; j < MAX_TID_COUNT; j++) { |
355 | pos += scnprintf(buf + pos, bufsz - pos, | 324 | pos += scnprintf(buf + pos, bufsz - pos, |
356 | "[%d]:\t\t%u", j, | 325 | "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", |
357 | station->tid[j].seq_number); | 326 | j, station->tid[j].seq_number, |
358 | pos += scnprintf(buf + pos, bufsz - pos, | 327 | station->tid[j].agg.txq_id, |
359 | "\t%u\t\t%u\t\t%u\t\t", | 328 | station->tid[j].agg.frame_count, |
360 | station->tid[j].agg.txq_id, | 329 | station->tid[j].tfds_in_queue, |
361 | station->tid[j].agg.frame_count, | 330 | station->tid[j].agg.start_idx, |
362 | station->tid[j].agg.wait_for_ba); | 331 | station->tid[j].agg.bitmap, |
332 | station->tid[j].agg.rate_n_flags); | ||
333 | |||
334 | if (station->tid[j].agg.wait_for_ba) | ||
363 | pos += scnprintf(buf + pos, bufsz - pos, | 335 | pos += scnprintf(buf + pos, bufsz - pos, |
364 | "%u\t%llu\t%u", | 336 | " - waitforba"); |
365 | station->tid[j].agg.start_idx, | ||
366 | (unsigned long long)station->tid[j].agg.bitmap, | ||
367 | station->tid[j].agg.rate_n_flags); | ||
368 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
369 | } | ||
370 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 337 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
371 | } | 338 | } |
339 | |||
340 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
372 | } | 341 | } |
373 | 342 | ||
374 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 343 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a36a6ef45aa..fc6072cdd96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -48,25 +48,6 @@ | |||
48 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
50 | 50 | ||
51 | /* configuration for the iwl4965 */ | ||
52 | extern struct iwl_cfg iwl4965_agn_cfg; | ||
53 | extern struct iwl_cfg iwl5300_agn_cfg; | ||
54 | extern struct iwl_cfg iwl5100_agn_cfg; | ||
55 | extern struct iwl_cfg iwl5350_agn_cfg; | ||
56 | extern struct iwl_cfg iwl5100_bgn_cfg; | ||
57 | extern struct iwl_cfg iwl5100_abg_cfg; | ||
58 | extern struct iwl_cfg iwl5150_agn_cfg; | ||
59 | extern struct iwl_cfg iwl5150_abg_cfg; | ||
60 | extern struct iwl_cfg iwl6000g2a_2agn_cfg; | ||
61 | extern struct iwl_cfg iwl6000i_2agn_cfg; | ||
62 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
63 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
64 | extern struct iwl_cfg iwl6000_3agn_cfg; | ||
65 | extern struct iwl_cfg iwl6050_2agn_cfg; | ||
66 | extern struct iwl_cfg iwl6050_2abg_cfg; | ||
67 | extern struct iwl_cfg iwl1000_bgn_cfg; | ||
68 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
69 | |||
70 | struct iwl_tx_queue; | 51 | struct iwl_tx_queue; |
71 | 52 | ||
72 | /* CT-KILL constants */ | 53 | /* CT-KILL constants */ |
@@ -133,8 +114,8 @@ struct iwl_cmd_meta { | |||
133 | * structure is stored at the end of the shared queue memory. */ | 114 | * structure is stored at the end of the shared queue memory. */ |
134 | u32 flags; | 115 | u32 flags; |
135 | 116 | ||
136 | DECLARE_PCI_UNMAP_ADDR(mapping) | 117 | DEFINE_DMA_UNMAP_ADDR(mapping); |
137 | DECLARE_PCI_UNMAP_LEN(len) | 118 | DEFINE_DMA_UNMAP_LEN(len); |
138 | }; | 119 | }; |
139 | 120 | ||
140 | /* | 121 | /* |
@@ -161,7 +142,7 @@ struct iwl_queue { | |||
161 | 142 | ||
162 | /* One for each TFD */ | 143 | /* One for each TFD */ |
163 | struct iwl_tx_info { | 144 | struct iwl_tx_info { |
164 | struct sk_buff *skb[IWL_NUM_OF_TBS - 1]; | 145 | struct sk_buff *skb; |
165 | }; | 146 | }; |
166 | 147 | ||
167 | /** | 148 | /** |
@@ -433,7 +414,7 @@ struct iwl_ht_agg { | |||
433 | 414 | ||
434 | 415 | ||
435 | struct iwl_tid_data { | 416 | struct iwl_tid_data { |
436 | u16 seq_number; | 417 | u16 seq_number; /* agn only */ |
437 | u16 tfds_in_queue; | 418 | u16 tfds_in_queue; |
438 | struct iwl_ht_agg agg; | 419 | struct iwl_ht_agg agg; |
439 | }; | 420 | }; |
@@ -583,6 +564,12 @@ enum iwl_ucode_tlv_type { | |||
583 | IWL_UCODE_TLV_INIT_DATA = 4, | 564 | IWL_UCODE_TLV_INIT_DATA = 4, |
584 | IWL_UCODE_TLV_BOOT = 5, | 565 | IWL_UCODE_TLV_BOOT = 5, |
585 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | 566 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ |
567 | IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, | ||
568 | IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, | ||
569 | IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, | ||
570 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | ||
571 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | ||
572 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | ||
586 | }; | 573 | }; |
587 | 574 | ||
588 | struct iwl_ucode_tlv { | 575 | struct iwl_ucode_tlv { |
@@ -675,6 +662,7 @@ struct iwl_sensitivity_ranges { | |||
675 | * @sw_crypto: 0 for hw, 1 for sw | 662 | * @sw_crypto: 0 for hw, 1 for sw |
676 | * @max_xxx_size: for ucode uses | 663 | * @max_xxx_size: for ucode uses |
677 | * @ct_kill_threshold: temperature threshold | 664 | * @ct_kill_threshold: temperature threshold |
665 | * @beacon_time_tsf_bits: number of valid tsf bits for beacon time | ||
678 | * @calib_init_cfg: setup initial calibrations for the hw | 666 | * @calib_init_cfg: setup initial calibrations for the hw |
679 | * @struct iwl_sensitivity_ranges: range of sensitivity values | 667 | * @struct iwl_sensitivity_ranges: range of sensitivity values |
680 | */ | 668 | */ |
@@ -701,6 +689,7 @@ struct iwl_hw_params { | |||
701 | u32 ct_kill_threshold; /* value in hw-dependent units */ | 689 | u32 ct_kill_threshold; /* value in hw-dependent units */ |
702 | u32 ct_kill_exit_threshold; /* value in hw-dependent units */ | 690 | u32 ct_kill_exit_threshold; /* value in hw-dependent units */ |
703 | /* for 1000, 6000 series and up */ | 691 | /* for 1000, 6000 series and up */ |
692 | u16 beacon_time_tsf_bits; | ||
704 | u32 calib_init_cfg; | 693 | u32 calib_init_cfg; |
705 | const struct iwl_sensitivity_ranges *sens; | 694 | const struct iwl_sensitivity_ranges *sens; |
706 | }; | 695 | }; |
@@ -1075,6 +1064,20 @@ struct iwl_force_reset { | |||
1075 | unsigned long last_force_reset_jiffies; | 1064 | unsigned long last_force_reset_jiffies; |
1076 | }; | 1065 | }; |
1077 | 1066 | ||
1067 | /* extend beacon time format bit shifting */ | ||
1068 | /* | ||
1069 | * for _3945 devices | ||
1070 | * bits 31:24 - extended | ||
1071 | * bits 23:0 - interval | ||
1072 | */ | ||
1073 | #define IWL3945_EXT_BEACON_TIME_POS 24 | ||
1074 | /* | ||
1075 | * for _agn devices | ||
1076 | * bits 31:22 - extended | ||
1077 | * bits 21:0 - interval | ||
1078 | */ | ||
1079 | #define IWLAGN_EXT_BEACON_TIME_POS 22 | ||
1080 | |||
1078 | struct iwl_priv { | 1081 | struct iwl_priv { |
1079 | 1082 | ||
1080 | /* ieee device used by generic ieee processing code */ | 1083 | /* ieee device used by generic ieee processing code */ |
@@ -1109,7 +1112,7 @@ struct iwl_priv { | |||
1109 | /* force reset */ | 1112 | /* force reset */ |
1110 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | 1113 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; |
1111 | 1114 | ||
1112 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. | 1115 | /* we allocate array of iwl_channel_info for NIC's valid channels. |
1113 | * Access via channel # using indirect index array */ | 1116 | * Access via channel # using indirect index array */ |
1114 | struct iwl_channel_info *channel_info; /* channel info array */ | 1117 | struct iwl_channel_info *channel_info; /* channel info array */ |
1115 | u8 channel_count; /* # of channels */ | 1118 | u8 channel_count; /* # of channels */ |
@@ -1127,6 +1130,7 @@ struct iwl_priv { | |||
1127 | void *scan_cmd; | 1130 | void *scan_cmd; |
1128 | enum ieee80211_band scan_band; | 1131 | enum ieee80211_band scan_band; |
1129 | struct cfg80211_scan_request *scan_request; | 1132 | struct cfg80211_scan_request *scan_request; |
1133 | struct ieee80211_vif *scan_vif; | ||
1130 | bool is_internal_short_scan; | 1134 | bool is_internal_short_scan; |
1131 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; | 1135 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; |
1132 | u8 mgmt_tx_ant; | 1136 | u8 mgmt_tx_ant; |
@@ -1174,7 +1178,7 @@ struct iwl_priv { | |||
1174 | struct iwl_switch_rxon switch_rxon; | 1178 | struct iwl_switch_rxon switch_rxon; |
1175 | 1179 | ||
1176 | /* 1st responses from initialize and runtime uCode images. | 1180 | /* 1st responses from initialize and runtime uCode images. |
1177 | * 4965's initialize alive response contains some calibration data. */ | 1181 | * _agn's initialize alive response contains some calibration data. */ |
1178 | struct iwl_init_alive_resp card_alive_init; | 1182 | struct iwl_init_alive_resp card_alive_init; |
1179 | struct iwl_alive_resp card_alive; | 1183 | struct iwl_alive_resp card_alive; |
1180 | 1184 | ||
@@ -1221,7 +1225,7 @@ struct iwl_priv { | |||
1221 | struct iwl_tt_mgmt thermal_throttle; | 1225 | struct iwl_tt_mgmt thermal_throttle; |
1222 | 1226 | ||
1223 | struct iwl_notif_statistics statistics; | 1227 | struct iwl_notif_statistics statistics; |
1224 | #ifdef CONFIG_IWLWIFI_DEBUG | 1228 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1225 | struct iwl_notif_statistics accum_statistics; | 1229 | struct iwl_notif_statistics accum_statistics; |
1226 | struct iwl_notif_statistics delta_statistics; | 1230 | struct iwl_notif_statistics delta_statistics; |
1227 | struct iwl_notif_statistics max_delta; | 1231 | struct iwl_notif_statistics max_delta; |
@@ -1229,9 +1233,10 @@ struct iwl_priv { | |||
1229 | 1233 | ||
1230 | /* context information */ | 1234 | /* context information */ |
1231 | u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ | 1235 | u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ |
1232 | u8 mac_addr[ETH_ALEN]; | ||
1233 | 1236 | ||
1234 | /*station table variables */ | 1237 | /* station table variables */ |
1238 | |||
1239 | /* Note: if lock and sta_lock are needed, lock must be acquired first */ | ||
1235 | spinlock_t sta_lock; | 1240 | spinlock_t sta_lock; |
1236 | int num_stations; | 1241 | int num_stations; |
1237 | struct iwl_station_entry stations[IWL_STATION_COUNT]; | 1242 | struct iwl_station_entry stations[IWL_STATION_COUNT]; |
@@ -1273,7 +1278,7 @@ struct iwl_priv { | |||
1273 | struct delayed_work rfkill_poll; | 1278 | struct delayed_work rfkill_poll; |
1274 | 1279 | ||
1275 | struct iwl3945_notif_statistics statistics; | 1280 | struct iwl3945_notif_statistics statistics; |
1276 | #ifdef CONFIG_IWLWIFI_DEBUG | 1281 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1277 | struct iwl3945_notif_statistics accum_statistics; | 1282 | struct iwl3945_notif_statistics accum_statistics; |
1278 | struct iwl3945_notif_statistics delta_statistics; | 1283 | struct iwl3945_notif_statistics delta_statistics; |
1279 | struct iwl3945_notif_statistics max_delta; | 1284 | struct iwl3945_notif_statistics max_delta; |
@@ -1315,6 +1320,9 @@ struct iwl_priv { | |||
1315 | bool last_phy_res_valid; | 1320 | bool last_phy_res_valid; |
1316 | 1321 | ||
1317 | struct completion firmware_loading_complete; | 1322 | struct completion firmware_loading_complete; |
1323 | |||
1324 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1325 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1318 | } _agn; | 1326 | } _agn; |
1319 | #endif | 1327 | #endif |
1320 | }; | 1328 | }; |
@@ -1353,9 +1361,7 @@ struct iwl_priv { | |||
1353 | /* debugging info */ | 1361 | /* debugging info */ |
1354 | u32 debug_level; /* per device debugging will override global | 1362 | u32 debug_level; /* per device debugging will override global |
1355 | iwl_debug_level if set */ | 1363 | iwl_debug_level if set */ |
1356 | u32 framecnt_to_us; | 1364 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
1357 | atomic_t restrict_refcnt; | ||
1358 | bool disable_ht40; | ||
1359 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1365 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1360 | /* debugfs */ | 1366 | /* debugfs */ |
1361 | u16 tx_traffic_idx; | 1367 | u16 tx_traffic_idx; |
@@ -1364,8 +1370,8 @@ struct iwl_priv { | |||
1364 | u8 *rx_traffic; | 1370 | u8 *rx_traffic; |
1365 | struct dentry *debugfs_dir; | 1371 | struct dentry *debugfs_dir; |
1366 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 1372 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
1373 | bool disable_ht40; | ||
1367 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 1374 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
1368 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
1369 | 1375 | ||
1370 | struct work_struct txpower_work; | 1376 | struct work_struct txpower_work; |
1371 | u32 disable_sens_cal; | 1377 | u32 disable_sens_cal; |
@@ -1419,9 +1425,9 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv) | |||
1419 | static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, | 1425 | static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, |
1420 | int txq_id, int idx) | 1426 | int txq_id, int idx) |
1421 | { | 1427 | { |
1422 | if (priv->txq[txq_id].txb[idx].skb[0]) | 1428 | if (priv->txq[txq_id].txb[idx].skb) |
1423 | return (struct ieee80211_hdr *)priv->txq[txq_id]. | 1429 | return (struct ieee80211_hdr *)priv->txq[txq_id]. |
1424 | txb[idx].skb[0]->data; | 1430 | txb[idx].skb->data; |
1425 | return NULL; | 1431 | return NULL; |
1426 | } | 1432 | } |
1427 | 1433 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 3ff6b9d25a1..621abe3c5af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -92,6 +92,11 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
92 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | 92 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, |
93 | struct fw_desc *desc) | 93 | struct fw_desc *desc) |
94 | { | 94 | { |
95 | if (!desc->len) { | ||
96 | desc->v_addr = NULL; | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
95 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, | 100 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, |
96 | &desc->p_addr, GFP_KERNEL); | 101 | &desc->p_addr, GFP_KERNEL); |
97 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | 102 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; |
@@ -170,4 +175,26 @@ static inline void iwl_enable_interrupts(struct iwl_priv *priv) | |||
170 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); | 175 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); |
171 | } | 176 | } |
172 | 177 | ||
178 | /** | ||
179 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | ||
180 | * @priv -- pointer to iwl_priv data structure | ||
181 | * @tsf_bits -- number of bits need to shift for masking) | ||
182 | */ | ||
183 | static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, | ||
184 | u16 tsf_bits) | ||
185 | { | ||
186 | return (1 << tsf_bits) - 1; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time | ||
191 | * @priv -- pointer to iwl_priv data structure | ||
192 | * @tsf_bits -- number of bits need to shift for masking) | ||
193 | */ | ||
194 | static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, | ||
195 | u16 tsf_bits) | ||
196 | { | ||
197 | return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; | ||
198 | } | ||
199 | |||
173 | #endif /* __iwl_helpers_h__ */ | 200 | #endif /* __iwl_helpers_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0a5d7cf2519..5e32057d693 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -286,7 +286,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
286 | last_rx_noise); | 286 | last_rx_noise); |
287 | } | 287 | } |
288 | 288 | ||
289 | #ifdef CONFIG_IWLWIFI_DEBUG | 289 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
290 | /* | 290 | /* |
291 | * based on the assumption of all statistics counter are in DWORD | 291 | * based on the assumption of all statistics counter are in DWORD |
292 | * FIXME: This function is for debugging, do not deal with | 292 | * FIXME: This function is for debugging, do not deal with |
@@ -448,7 +448,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
448 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 448 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
449 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 449 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
450 | 450 | ||
451 | #ifdef CONFIG_IWLWIFI_DEBUG | 451 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
452 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | 452 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); |
453 | #endif | 453 | #endif |
454 | iwl_recover_from_statistics(priv, pkt); | 454 | iwl_recover_from_statistics(priv, pkt); |
@@ -480,7 +480,7 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
480 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 480 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
481 | 481 | ||
482 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | 482 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { |
483 | #ifdef CONFIG_IWLWIFI_DEBUG | 483 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
484 | memset(&priv->accum_statistics, 0, | 484 | memset(&priv->accum_statistics, 0, |
485 | sizeof(struct iwl_notif_statistics)); | 485 | sizeof(struct iwl_notif_statistics)); |
486 | memset(&priv->delta_statistics, 0, | 486 | memset(&priv->delta_statistics, 0, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5d3f51ff2f0..b8bcd48eb8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -333,7 +333,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
333 | goto out_unlock; | 333 | goto out_unlock; |
334 | } | 334 | } |
335 | 335 | ||
336 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 336 | if (test_bit(STATUS_SCANNING, &priv->status) && |
337 | !priv->is_internal_short_scan) { | ||
337 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 338 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
338 | ret = -EAGAIN; | 339 | ret = -EAGAIN; |
339 | goto out_unlock; | 340 | goto out_unlock; |
@@ -348,8 +349,16 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
348 | /* mac80211 will only ask for one band at a time */ | 349 | /* mac80211 will only ask for one band at a time */ |
349 | priv->scan_band = req->channels[0]->band; | 350 | priv->scan_band = req->channels[0]->band; |
350 | priv->scan_request = req; | 351 | priv->scan_request = req; |
352 | priv->scan_vif = vif; | ||
351 | 353 | ||
352 | ret = iwl_scan_initiate(priv, vif); | 354 | /* |
355 | * If an internal scan is in progress, just set | ||
356 | * up the scan_request as per above. | ||
357 | */ | ||
358 | if (priv->is_internal_short_scan) | ||
359 | ret = 0; | ||
360 | else | ||
361 | ret = iwl_scan_initiate(priv, vif); | ||
353 | 362 | ||
354 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 363 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
355 | 364 | ||
@@ -438,7 +447,7 @@ EXPORT_SYMBOL(iwl_bg_scan_check); | |||
438 | */ | 447 | */ |
439 | 448 | ||
440 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 449 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
441 | const u8 *ies, int ie_len, int left) | 450 | const u8 *ta, const u8 *ies, int ie_len, int left) |
442 | { | 451 | { |
443 | int len = 0; | 452 | int len = 0; |
444 | u8 *pos = NULL; | 453 | u8 *pos = NULL; |
@@ -451,7 +460,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
451 | 460 | ||
452 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 461 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); |
453 | memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); | 462 | memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); |
454 | memcpy(frame->sa, priv->mac_addr, ETH_ALEN); | 463 | memcpy(frame->sa, ta, ETH_ALEN); |
455 | memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); | 464 | memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); |
456 | frame->seq_ctrl = 0; | 465 | frame->seq_ctrl = 0; |
457 | 466 | ||
@@ -513,7 +522,21 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
513 | priv->is_internal_short_scan = false; | 522 | priv->is_internal_short_scan = false; |
514 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 523 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
515 | internal = true; | 524 | internal = true; |
525 | } else { | ||
526 | priv->scan_request = NULL; | ||
527 | priv->scan_vif = NULL; | ||
516 | } | 528 | } |
529 | |||
530 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
531 | goto out; | ||
532 | |||
533 | if (internal && priv->scan_request) | ||
534 | iwl_scan_initiate(priv, priv->scan_vif); | ||
535 | |||
536 | /* Since setting the TXPOWER may have been deferred while | ||
537 | * performing the scan, fire one off */ | ||
538 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
539 | out: | ||
517 | mutex_unlock(&priv->mutex); | 540 | mutex_unlock(&priv->mutex); |
518 | 541 | ||
519 | /* | 542 | /* |
@@ -523,15 +546,6 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
523 | */ | 546 | */ |
524 | if (!internal) | 547 | if (!internal) |
525 | ieee80211_scan_completed(priv->hw, false); | 548 | ieee80211_scan_completed(priv->hw, false); |
526 | |||
527 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
528 | return; | ||
529 | |||
530 | /* Since setting the TXPOWER may have been deferred while | ||
531 | * performing the scan, fire one off */ | ||
532 | mutex_lock(&priv->mutex); | ||
533 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
534 | mutex_unlock(&priv->mutex); | ||
535 | } | 549 | } |
536 | EXPORT_SYMBOL(iwl_bg_scan_completed); | 550 | EXPORT_SYMBOL(iwl_bg_scan_completed); |
537 | 551 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 83a26361a9b..c7127132c29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -311,10 +311,10 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
311 | struct ieee80211_sta_ht_cap *ht_info, | 311 | struct ieee80211_sta_ht_cap *ht_info, |
312 | u8 *sta_id_r) | 312 | u8 *sta_id_r) |
313 | { | 313 | { |
314 | struct iwl_station_entry *station; | ||
315 | unsigned long flags_spin; | 314 | unsigned long flags_spin; |
316 | int ret = 0; | 315 | int ret = 0; |
317 | u8 sta_id; | 316 | u8 sta_id; |
317 | struct iwl_addsta_cmd sta_cmd; | ||
318 | 318 | ||
319 | *sta_id_r = 0; | 319 | *sta_id_r = 0; |
320 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 320 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
@@ -347,14 +347,15 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
347 | } | 347 | } |
348 | 348 | ||
349 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; | 349 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; |
350 | station = &priv->stations[sta_id]; | 350 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
351 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 351 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
352 | 352 | ||
353 | /* Add station to device's station table */ | 353 | /* Add station to device's station table */ |
354 | ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); | 354 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
355 | if (ret) { | 355 | if (ret) { |
356 | IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); | ||
357 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 356 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
357 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
358 | priv->stations[sta_id].sta.sta.addr); | ||
358 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | 359 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; |
359 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | 360 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; |
360 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 361 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -488,7 +489,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | |||
488 | } | 489 | } |
489 | 490 | ||
490 | static int iwl_send_remove_station(struct iwl_priv *priv, | 491 | static int iwl_send_remove_station(struct iwl_priv *priv, |
491 | struct iwl_station_entry *station) | 492 | const u8 *addr, int sta_id) |
492 | { | 493 | { |
493 | struct iwl_rx_packet *pkt; | 494 | struct iwl_rx_packet *pkt; |
494 | int ret; | 495 | int ret; |
@@ -505,7 +506,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
505 | 506 | ||
506 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); | 507 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); |
507 | rm_sta_cmd.num_sta = 1; | 508 | rm_sta_cmd.num_sta = 1; |
508 | memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); | 509 | memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN); |
509 | 510 | ||
510 | cmd.flags |= CMD_WANT_SKB; | 511 | cmd.flags |= CMD_WANT_SKB; |
511 | 512 | ||
@@ -525,7 +526,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
525 | switch (pkt->u.rem_sta.status) { | 526 | switch (pkt->u.rem_sta.status) { |
526 | case REM_STA_SUCCESS_MSK: | 527 | case REM_STA_SUCCESS_MSK: |
527 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 528 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
528 | iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); | 529 | iwl_sta_ucode_deactivate(priv, sta_id); |
529 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 530 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
530 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 531 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
531 | break; | 532 | break; |
@@ -546,7 +547,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
546 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | 547 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, |
547 | const u8 *addr) | 548 | const u8 *addr) |
548 | { | 549 | { |
549 | struct iwl_station_entry *station; | ||
550 | unsigned long flags; | 550 | unsigned long flags; |
551 | 551 | ||
552 | if (!iwl_is_ready(priv)) { | 552 | if (!iwl_is_ready(priv)) { |
@@ -592,10 +592,9 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | |||
592 | 592 | ||
593 | BUG_ON(priv->num_stations < 0); | 593 | BUG_ON(priv->num_stations < 0); |
594 | 594 | ||
595 | station = &priv->stations[sta_id]; | ||
596 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 595 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
597 | 596 | ||
598 | return iwl_send_remove_station(priv, station); | 597 | return iwl_send_remove_station(priv, addr, sta_id); |
599 | out_err: | 598 | out_err: |
600 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 599 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
601 | return -EINVAL; | 600 | return -EINVAL; |
@@ -643,11 +642,13 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); | |||
643 | */ | 642 | */ |
644 | void iwl_restore_stations(struct iwl_priv *priv) | 643 | void iwl_restore_stations(struct iwl_priv *priv) |
645 | { | 644 | { |
646 | struct iwl_station_entry *station; | 645 | struct iwl_addsta_cmd sta_cmd; |
646 | struct iwl_link_quality_cmd lq; | ||
647 | unsigned long flags_spin; | 647 | unsigned long flags_spin; |
648 | int i; | 648 | int i; |
649 | bool found = false; | 649 | bool found = false; |
650 | int ret; | 650 | int ret; |
651 | bool send_lq; | ||
651 | 652 | ||
652 | if (!iwl_is_ready(priv)) { | 653 | if (!iwl_is_ready(priv)) { |
653 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); | 654 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); |
@@ -669,13 +670,20 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
669 | 670 | ||
670 | for (i = 0; i < priv->hw_params.max_stations; i++) { | 671 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
671 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { | 672 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { |
673 | memcpy(&sta_cmd, &priv->stations[i].sta, | ||
674 | sizeof(struct iwl_addsta_cmd)); | ||
675 | send_lq = false; | ||
676 | if (priv->stations[i].lq) { | ||
677 | memcpy(&lq, priv->stations[i].lq, | ||
678 | sizeof(struct iwl_link_quality_cmd)); | ||
679 | send_lq = true; | ||
680 | } | ||
672 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 681 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
673 | station = &priv->stations[i]; | 682 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
674 | ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); | ||
675 | if (ret) { | 683 | if (ret) { |
676 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
677 | station->sta.sta.addr); | ||
678 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 684 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
685 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
686 | priv->stations[i].sta.sta.addr); | ||
679 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; | 687 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; |
680 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 688 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
681 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 689 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -684,8 +692,8 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
684 | * Rate scaling has already been initialized, send | 692 | * Rate scaling has already been initialized, send |
685 | * current LQ command | 693 | * current LQ command |
686 | */ | 694 | */ |
687 | if (station->lq) | 695 | if (send_lq) |
688 | iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); | 696 | iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true); |
689 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 697 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
690 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 698 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
691 | } | 699 | } |
@@ -972,24 +980,16 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
972 | unsigned long flags; | 980 | unsigned long flags; |
973 | int i; | 981 | int i; |
974 | 982 | ||
975 | if (sta) { | ||
976 | sta_id = iwl_sta_id(sta); | ||
977 | |||
978 | if (sta_id == IWL_INVALID_STATION) { | ||
979 | IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", | ||
980 | sta->addr); | ||
981 | return; | ||
982 | } | ||
983 | } else | ||
984 | sta_id = priv->hw_params.bcast_sta_id; | ||
985 | |||
986 | |||
987 | if (iwl_scan_cancel(priv)) { | 983 | if (iwl_scan_cancel(priv)) { |
988 | /* cancel scan failed, just live w/ bad key and rely | 984 | /* cancel scan failed, just live w/ bad key and rely |
989 | briefly on SW decryption */ | 985 | briefly on SW decryption */ |
990 | return; | 986 | return; |
991 | } | 987 | } |
992 | 988 | ||
989 | sta_id = iwl_sta_id_or_broadcast(priv, sta); | ||
990 | if (sta_id == IWL_INVALID_STATION) | ||
991 | return; | ||
992 | |||
993 | spin_lock_irqsave(&priv->sta_lock, flags); | 993 | spin_lock_irqsave(&priv->sta_lock, flags); |
994 | 994 | ||
995 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; | 995 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; |
@@ -1277,9 +1277,8 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) | |||
1277 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; | 1277 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; |
1278 | priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); | 1278 | priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); |
1279 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1279 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1280 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1281 | |||
1282 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1280 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1281 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1283 | } | 1282 | } |
1284 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); | 1283 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); |
1285 | 1284 | ||
@@ -1310,7 +1309,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1310 | int tid) | 1309 | int tid) |
1311 | { | 1310 | { |
1312 | unsigned long flags; | 1311 | unsigned long flags; |
1313 | int sta_id; | 1312 | int sta_id, ret; |
1314 | 1313 | ||
1315 | sta_id = iwl_sta_id(sta); | 1314 | sta_id = iwl_sta_id(sta); |
1316 | if (sta_id == IWL_INVALID_STATION) { | 1315 | if (sta_id == IWL_INVALID_STATION) { |
@@ -1323,10 +1322,11 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1323 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | 1322 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; |
1324 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | 1323 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; |
1325 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1324 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1325 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1326 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1326 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1327 | 1327 | ||
1328 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | 1328 | return ret; |
1329 | CMD_ASYNC); | 1329 | |
1330 | } | 1330 | } |
1331 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1331 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); |
1332 | 1332 | ||
@@ -1340,9 +1340,9 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1340 | priv->stations[sta_id].sta.sta.modify_mask = 0; | 1340 | priv->stations[sta_id].sta.sta.modify_mask = 0; |
1341 | priv->stations[sta_id].sta.sleep_tx_count = 0; | 1341 | priv->stations[sta_id].sta.sleep_tx_count = 0; |
1342 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1342 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1343 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1343 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1344 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1344 | 1345 | ||
1345 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1346 | } | 1346 | } |
1347 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | 1347 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); |
1348 | 1348 | ||
@@ -1357,9 +1357,9 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1357 | STA_MODIFY_SLEEP_TX_COUNT_MSK; | 1357 | STA_MODIFY_SLEEP_TX_COUNT_MSK; |
1358 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); | 1358 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); |
1359 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1359 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1360 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1360 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1361 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1361 | 1362 | ||
1362 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1363 | } | 1363 | } |
1364 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | 1364 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); |
1365 | 1365 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index c2a453a1a99..5b1b1e461eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -107,4 +107,33 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) | |||
107 | 107 | ||
108 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; | 108 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; |
109 | } | 109 | } |
110 | |||
111 | /** | ||
112 | * iwl_sta_id_or_broadcast - return sta_id or broadcast sta | ||
113 | * @priv: iwl priv | ||
114 | * @sta: mac80211 station | ||
115 | * | ||
116 | * In certain circumstances mac80211 passes a station pointer | ||
117 | * that may be %NULL, for example during TX or key setup. In | ||
118 | * that case, we need to use the broadcast station, so this | ||
119 | * inline wraps that pattern. | ||
120 | */ | ||
121 | static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, | ||
122 | struct ieee80211_sta *sta) | ||
123 | { | ||
124 | int sta_id; | ||
125 | |||
126 | if (!sta) | ||
127 | return priv->hw_params.bcast_sta_id; | ||
128 | |||
129 | sta_id = iwl_sta_id(sta); | ||
130 | |||
131 | /* | ||
132 | * mac80211 should not be passing a partially | ||
133 | * initialised station! | ||
134 | */ | ||
135 | WARN_ON(sta_id == IWL_INVALID_STATION); | ||
136 | |||
137 | return sta_id; | ||
138 | } | ||
110 | #endif /* __iwl_sta_h__ */ | 139 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ece2ea0977..a81989c0698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -77,21 +77,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
77 | } | 77 | } |
78 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 78 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |
79 | 79 | ||
80 | |||
81 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
82 | int sta_id, int tid, int freed) | ||
83 | { | ||
84 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | ||
85 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
86 | else { | ||
87 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", | ||
88 | priv->stations[sta_id].tid[tid].tfds_in_queue, | ||
89 | freed); | ||
90 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | ||
91 | } | ||
92 | } | ||
93 | EXPORT_SYMBOL(iwl_free_tfds_in_queue); | ||
94 | |||
95 | /** | 80 | /** |
96 | * iwl_tx_queue_free - Deallocate DMA queue. | 81 | * iwl_tx_queue_free - Deallocate DMA queue. |
97 | * @txq: Transmit queue to deallocate. | 82 | * @txq: Transmit queue to deallocate. |
@@ -169,15 +154,15 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
169 | } | 154 | } |
170 | 155 | ||
171 | pci_unmap_single(priv->pci_dev, | 156 | pci_unmap_single(priv->pci_dev, |
172 | pci_unmap_addr(&txq->meta[i], mapping), | 157 | dma_unmap_addr(&txq->meta[i], mapping), |
173 | pci_unmap_len(&txq->meta[i], len), | 158 | dma_unmap_len(&txq->meta[i], len), |
174 | PCI_DMA_BIDIRECTIONAL); | 159 | PCI_DMA_BIDIRECTIONAL); |
175 | } | 160 | } |
176 | if (huge) { | 161 | if (huge) { |
177 | i = q->n_window; | 162 | i = q->n_window; |
178 | pci_unmap_single(priv->pci_dev, | 163 | pci_unmap_single(priv->pci_dev, |
179 | pci_unmap_addr(&txq->meta[i], mapping), | 164 | dma_unmap_addr(&txq->meta[i], mapping), |
180 | pci_unmap_len(&txq->meta[i], len), | 165 | dma_unmap_len(&txq->meta[i], len), |
181 | PCI_DMA_BIDIRECTIONAL); | 166 | PCI_DMA_BIDIRECTIONAL); |
182 | } | 167 | } |
183 | 168 | ||
@@ -287,7 +272,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
287 | /* Driver private data, only for Tx (not command) queues, | 272 | /* Driver private data, only for Tx (not command) queues, |
288 | * not shared with device. */ | 273 | * not shared with device. */ |
289 | if (id != IWL_CMD_QUEUE_NUM) { | 274 | if (id != IWL_CMD_QUEUE_NUM) { |
290 | txq->txb = kmalloc(sizeof(txq->txb[0]) * | 275 | txq->txb = kzalloc(sizeof(txq->txb[0]) * |
291 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | 276 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); |
292 | if (!txq->txb) { | 277 | if (!txq->txb) { |
293 | IWL_ERR(priv, "kmalloc for auxiliary BD " | 278 | IWL_ERR(priv, "kmalloc for auxiliary BD " |
@@ -531,8 +516,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
531 | 516 | ||
532 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, | 517 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, |
533 | fix_size, PCI_DMA_BIDIRECTIONAL); | 518 | fix_size, PCI_DMA_BIDIRECTIONAL); |
534 | pci_unmap_addr_set(out_meta, mapping, phys_addr); | 519 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
535 | pci_unmap_len_set(out_meta, len, fix_size); | 520 | dma_unmap_len_set(out_meta, len, fix_size); |
536 | 521 | ||
537 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 522 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); |
538 | 523 | ||
@@ -626,8 +611,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
626 | meta = &txq->meta[cmd_index]; | 611 | meta = &txq->meta[cmd_index]; |
627 | 612 | ||
628 | pci_unmap_single(priv->pci_dev, | 613 | pci_unmap_single(priv->pci_dev, |
629 | pci_unmap_addr(meta, mapping), | 614 | dma_unmap_addr(meta, mapping), |
630 | pci_unmap_len(meta, len), | 615 | dma_unmap_len(meta, len), |
631 | PCI_DMA_BIDIRECTIONAL); | 616 | PCI_DMA_BIDIRECTIONAL); |
632 | 617 | ||
633 | /* Input error checking is done when commands are added to queue. */ | 618 | /* Input error checking is done when commands are added to queue. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3e5bffb6034..0f16c7d518f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -197,6 +197,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
197 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | 197 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) |
198 | { | 198 | { |
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | struct iwl_addsta_cmd sta_cmd; | ||
200 | 201 | ||
201 | spin_lock_irqsave(&priv->sta_lock, flags); | 202 | spin_lock_irqsave(&priv->sta_lock, flags); |
202 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); | 203 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); |
@@ -205,11 +206,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
205 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | 206 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; |
206 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 207 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
207 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 208 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
209 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
208 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 210 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
209 | 211 | ||
210 | IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); | 212 | IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); |
211 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); | 213 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
212 | return 0; | ||
213 | } | 214 | } |
214 | 215 | ||
215 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | 216 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, |
@@ -474,10 +475,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
474 | u8 unicast; | 475 | u8 unicast; |
475 | u8 sta_id; | 476 | u8 sta_id; |
476 | u8 tid = 0; | 477 | u8 tid = 0; |
477 | u16 seq_number = 0; | ||
478 | __le16 fc; | 478 | __le16 fc; |
479 | u8 wait_write_ptr = 0; | 479 | u8 wait_write_ptr = 0; |
480 | u8 *qc = NULL; | ||
481 | unsigned long flags; | 480 | unsigned long flags; |
482 | 481 | ||
483 | spin_lock_irqsave(&priv->lock, flags); | 482 | spin_lock_irqsave(&priv->lock, flags); |
@@ -510,10 +509,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
510 | hdr_len = ieee80211_hdrlen(fc); | 509 | hdr_len = ieee80211_hdrlen(fc); |
511 | 510 | ||
512 | /* Find index into station table for destination station */ | 511 | /* Find index into station table for destination station */ |
513 | if (!info->control.sta) | 512 | sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); |
514 | sta_id = priv->hw_params.bcast_sta_id; | ||
515 | else | ||
516 | sta_id = iwl_sta_id(info->control.sta); | ||
517 | if (sta_id == IWL_INVALID_STATION) { | 513 | if (sta_id == IWL_INVALID_STATION) { |
518 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 514 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
519 | hdr->addr1); | 515 | hdr->addr1); |
@@ -523,16 +519,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
523 | IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); | 519 | IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); |
524 | 520 | ||
525 | if (ieee80211_is_data_qos(fc)) { | 521 | if (ieee80211_is_data_qos(fc)) { |
526 | qc = ieee80211_get_qos_ctl(hdr); | 522 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
527 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 523 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
528 | if (unlikely(tid >= MAX_TID_COUNT)) | 524 | if (unlikely(tid >= MAX_TID_COUNT)) |
529 | goto drop; | 525 | goto drop; |
530 | seq_number = priv->stations[sta_id].tid[tid].seq_number & | ||
531 | IEEE80211_SCTL_SEQ; | ||
532 | hdr->seq_ctrl = cpu_to_le16(seq_number) | | ||
533 | (hdr->seq_ctrl & | ||
534 | cpu_to_le16(IEEE80211_SCTL_FRAG)); | ||
535 | seq_number += 0x10; | ||
536 | } | 526 | } |
537 | 527 | ||
538 | /* Descriptor for chosen Tx queue */ | 528 | /* Descriptor for chosen Tx queue */ |
@@ -548,7 +538,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
548 | 538 | ||
549 | /* Set up driver data for this TFD */ | 539 | /* Set up driver data for this TFD */ |
550 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 540 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
551 | txq->txb[q->write_ptr].skb[0] = skb; | 541 | txq->txb[q->write_ptr].skb = skb; |
552 | 542 | ||
553 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 543 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
554 | out_cmd = txq->cmd[idx]; | 544 | out_cmd = txq->cmd[idx]; |
@@ -591,8 +581,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
591 | 581 | ||
592 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 582 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
593 | txq->need_update = 1; | 583 | txq->need_update = 1; |
594 | if (qc) | ||
595 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
596 | } else { | 584 | } else { |
597 | wait_write_ptr = 1; | 585 | wait_write_ptr = 1; |
598 | txq->need_update = 0; | 586 | txq->need_update = 0; |
@@ -631,8 +619,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
631 | len, PCI_DMA_TODEVICE); | 619 | len, PCI_DMA_TODEVICE); |
632 | /* we do not map meta data ... so we can safely access address to | 620 | /* we do not map meta data ... so we can safely access address to |
633 | * provide to unmap command*/ | 621 | * provide to unmap command*/ |
634 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | 622 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
635 | pci_unmap_len_set(out_meta, len, len); | 623 | dma_unmap_len_set(out_meta, len, len); |
636 | 624 | ||
637 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 625 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
638 | * first entry */ | 626 | * first entry */ |
@@ -677,55 +665,6 @@ drop: | |||
677 | return -1; | 665 | return -1; |
678 | } | 666 | } |
679 | 667 | ||
680 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | ||
681 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | ||
682 | #define TIME_UNIT 1024 | ||
683 | |||
684 | /* | ||
685 | * extended beacon time format | ||
686 | * time in usec will be changed into a 32-bit value in 8:24 format | ||
687 | * the high 1 byte is the beacon counts | ||
688 | * the lower 3 bytes is the time in usec within one beacon interval | ||
689 | */ | ||
690 | |||
691 | static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval) | ||
692 | { | ||
693 | u32 quot; | ||
694 | u32 rem; | ||
695 | u32 interval = beacon_interval * 1024; | ||
696 | |||
697 | if (!interval || !usec) | ||
698 | return 0; | ||
699 | |||
700 | quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); | ||
701 | rem = (usec % interval) & BEACON_TIME_MASK_LOW; | ||
702 | |||
703 | return (quot << 24) + rem; | ||
704 | } | ||
705 | |||
706 | /* base is usually what we get from ucode with each received frame, | ||
707 | * the same as HW timer counter counting down | ||
708 | */ | ||
709 | |||
710 | static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) | ||
711 | { | ||
712 | u32 base_low = base & BEACON_TIME_MASK_LOW; | ||
713 | u32 addon_low = addon & BEACON_TIME_MASK_LOW; | ||
714 | u32 interval = beacon_interval * TIME_UNIT; | ||
715 | u32 res = (base & BEACON_TIME_MASK_HIGH) + | ||
716 | (addon & BEACON_TIME_MASK_HIGH); | ||
717 | |||
718 | if (base_low > addon_low) | ||
719 | res += base_low - addon_low; | ||
720 | else if (base_low < addon_low) { | ||
721 | res += interval + base_low - addon_low; | ||
722 | res += (1 << 24); | ||
723 | } else | ||
724 | res += (1 << 24); | ||
725 | |||
726 | return cpu_to_le32(res); | ||
727 | } | ||
728 | |||
729 | static int iwl3945_get_measurement(struct iwl_priv *priv, | 668 | static int iwl3945_get_measurement(struct iwl_priv *priv, |
730 | struct ieee80211_measurement_params *params, | 669 | struct ieee80211_measurement_params *params, |
731 | u8 type) | 670 | u8 type) |
@@ -743,8 +682,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
743 | int duration = le16_to_cpu(params->duration); | 682 | int duration = le16_to_cpu(params->duration); |
744 | 683 | ||
745 | if (iwl_is_associated(priv)) | 684 | if (iwl_is_associated(priv)) |
746 | add_time = | 685 | add_time = iwl_usecs_to_beacons(priv, |
747 | iwl3945_usecs_to_beacons( | ||
748 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, | 686 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, |
749 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 687 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
750 | 688 | ||
@@ -759,8 +697,8 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
759 | 697 | ||
760 | if (iwl_is_associated(priv)) | 698 | if (iwl_is_associated(priv)) |
761 | spectrum.start_time = | 699 | spectrum.start_time = |
762 | iwl3945_add_beacon_time(priv->_3945.last_beacon_time, | 700 | iwl_add_beacon_time(priv, |
763 | add_time, | 701 | priv->_3945.last_beacon_time, add_time, |
764 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 702 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
765 | else | 703 | else |
766 | spectrum.start_time = 0; | 704 | spectrum.start_time = 0; |
@@ -1844,6 +1782,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1844 | #endif | 1782 | #endif |
1845 | } | 1783 | } |
1846 | 1784 | ||
1785 | static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv, | ||
1786 | struct ieee80211_vif *vif, | ||
1787 | enum ieee80211_band band, | ||
1788 | struct iwl3945_scan_channel *scan_ch) | ||
1789 | { | ||
1790 | const struct ieee80211_supported_band *sband; | ||
1791 | u16 passive_dwell = 0; | ||
1792 | u16 active_dwell = 0; | ||
1793 | int added = 0; | ||
1794 | u8 channel = 0; | ||
1795 | |||
1796 | sband = iwl_get_hw_mode(priv, band); | ||
1797 | if (!sband) { | ||
1798 | IWL_ERR(priv, "invalid band\n"); | ||
1799 | return added; | ||
1800 | } | ||
1801 | |||
1802 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
1803 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
1804 | |||
1805 | if (passive_dwell <= active_dwell) | ||
1806 | passive_dwell = active_dwell + 1; | ||
1807 | |||
1808 | |||
1809 | channel = iwl_get_single_channel_number(priv, band); | ||
1810 | |||
1811 | if (channel) { | ||
1812 | scan_ch->channel = channel; | ||
1813 | scan_ch->type = 0; /* passive */ | ||
1814 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
1815 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
1816 | /* Set txpower levels to defaults */ | ||
1817 | scan_ch->tpc.dsp_atten = 110; | ||
1818 | if (band == IEEE80211_BAND_5GHZ) | ||
1819 | scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
1820 | else | ||
1821 | scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); | ||
1822 | added++; | ||
1823 | } else | ||
1824 | IWL_ERR(priv, "no valid channel found\n"); | ||
1825 | return added; | ||
1826 | } | ||
1827 | |||
1847 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | 1828 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, |
1848 | enum ieee80211_band band, | 1829 | enum ieee80211_band band, |
1849 | u8 is_active, u8 n_probes, | 1830 | u8 is_active, u8 n_probes, |
@@ -2979,22 +2960,31 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2979 | scan->tx_cmd.len = cpu_to_le16( | 2960 | scan->tx_cmd.len = cpu_to_le16( |
2980 | iwl_fill_probe_req(priv, | 2961 | iwl_fill_probe_req(priv, |
2981 | (struct ieee80211_mgmt *)scan->data, | 2962 | (struct ieee80211_mgmt *)scan->data, |
2963 | vif->addr, | ||
2982 | priv->scan_request->ie, | 2964 | priv->scan_request->ie, |
2983 | priv->scan_request->ie_len, | 2965 | priv->scan_request->ie_len, |
2984 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2966 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
2985 | } else { | 2967 | } else { |
2968 | /* use bcast addr, will not be transmitted but must be valid */ | ||
2986 | scan->tx_cmd.len = cpu_to_le16( | 2969 | scan->tx_cmd.len = cpu_to_le16( |
2987 | iwl_fill_probe_req(priv, | 2970 | iwl_fill_probe_req(priv, |
2988 | (struct ieee80211_mgmt *)scan->data, | 2971 | (struct ieee80211_mgmt *)scan->data, |
2989 | NULL, 0, | 2972 | iwl_bcast_addr, NULL, 0, |
2990 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2973 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
2991 | } | 2974 | } |
2992 | /* select Rx antennas */ | 2975 | /* select Rx antennas */ |
2993 | scan->flags |= iwl3945_get_antenna_flags(priv); | 2976 | scan->flags |= iwl3945_get_antenna_flags(priv); |
2994 | 2977 | ||
2995 | scan->channel_count = | 2978 | if (priv->is_internal_short_scan) { |
2996 | iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, | 2979 | scan->channel_count = |
2997 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); | 2980 | iwl3945_get_single_channel_for_scan(priv, vif, band, |
2981 | (void *)&scan->data[le16_to_cpu( | ||
2982 | scan->tx_cmd.len)]); | ||
2983 | } else { | ||
2984 | scan->channel_count = | ||
2985 | iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, | ||
2986 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); | ||
2987 | } | ||
2998 | 2988 | ||
2999 | if (scan->channel_count == 0) { | 2989 | if (scan->channel_count == 0) { |
3000 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 2990 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
@@ -3108,19 +3098,16 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3108 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3098 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
3109 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3099 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
3110 | 3100 | ||
3111 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3101 | if (vif->bss_conf.use_short_preamble) |
3112 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3102 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
3113 | else | 3103 | else |
3114 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3104 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3115 | 3105 | ||
3116 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3106 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3117 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3107 | if (vif->bss_conf.use_short_slot) |
3118 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3108 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3119 | else | 3109 | else |
3120 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3110 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3121 | |||
3122 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3123 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
3124 | } | 3111 | } |
3125 | 3112 | ||
3126 | iwlcore_commit_rxon(priv); | 3113 | iwlcore_commit_rxon(priv); |
@@ -3284,8 +3271,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3284 | 3271 | ||
3285 | priv->staging_rxon.assoc_id = 0; | 3272 | priv->staging_rxon.assoc_id = 0; |
3286 | 3273 | ||
3287 | if (vif->bss_conf.assoc_capability & | 3274 | if (vif->bss_conf.use_short_preamble) |
3288 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3289 | priv->staging_rxon.flags |= | 3275 | priv->staging_rxon.flags |= |
3290 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3276 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3291 | else | 3277 | else |
@@ -3293,17 +3279,12 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3293 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3279 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3294 | 3280 | ||
3295 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3281 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3296 | if (vif->bss_conf.assoc_capability & | 3282 | if (vif->bss_conf.use_short_slot) |
3297 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
3298 | priv->staging_rxon.flags |= | 3283 | priv->staging_rxon.flags |= |
3299 | RXON_FLG_SHORT_SLOT_MSK; | 3284 | RXON_FLG_SHORT_SLOT_MSK; |
3300 | else | 3285 | else |
3301 | priv->staging_rxon.flags &= | 3286 | priv->staging_rxon.flags &= |
3302 | ~RXON_FLG_SHORT_SLOT_MSK; | 3287 | ~RXON_FLG_SHORT_SLOT_MSK; |
3303 | |||
3304 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3305 | priv->staging_rxon.flags &= | ||
3306 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3307 | } | 3288 | } |
3308 | /* restore RXON assoc */ | 3289 | /* restore RXON assoc */ |
3309 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3290 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
@@ -3336,17 +3317,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3336 | static_key = !iwl_is_associated(priv); | 3317 | static_key = !iwl_is_associated(priv); |
3337 | 3318 | ||
3338 | if (!static_key) { | 3319 | if (!static_key) { |
3339 | if (!sta) { | 3320 | sta_id = iwl_sta_id_or_broadcast(priv, sta); |
3340 | sta_id = priv->hw_params.bcast_sta_id; | 3321 | if (sta_id == IWL_INVALID_STATION) |
3341 | } else { | 3322 | return -EINVAL; |
3342 | sta_id = iwl_sta_id(sta); | ||
3343 | if (sta_id == IWL_INVALID_STATION) { | ||
3344 | IWL_DEBUG_MAC80211(priv, | ||
3345 | "leave - %pM not in station map.\n", | ||
3346 | sta->addr); | ||
3347 | return -EINVAL; | ||
3348 | } | ||
3349 | } | ||
3350 | } | 3323 | } |
3351 | 3324 | ||
3352 | mutex_lock(&priv->mutex); | 3325 | mutex_lock(&priv->mutex); |
@@ -3973,9 +3946,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
3973 | priv->pci_dev = pdev; | 3946 | priv->pci_dev = pdev; |
3974 | priv->inta_mask = CSR_INI_SET_MASK; | 3947 | priv->inta_mask = CSR_INI_SET_MASK; |
3975 | 3948 | ||
3976 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3977 | atomic_set(&priv->restrict_refcnt, 0); | ||
3978 | #endif | ||
3979 | if (iwl_alloc_traffic_mem(priv)) | 3949 | if (iwl_alloc_traffic_mem(priv)) |
3980 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3950 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
3981 | 3951 | ||
@@ -4044,9 +4014,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4044 | } | 4014 | } |
4045 | /* MAC Address location in EEPROM same for 3945/4965 */ | 4015 | /* MAC Address location in EEPROM same for 3945/4965 */ |
4046 | eeprom = (struct iwl3945_eeprom *)priv->eeprom; | 4016 | eeprom = (struct iwl3945_eeprom *)priv->eeprom; |
4047 | memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); | 4017 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address); |
4048 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); | 4018 | SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address); |
4049 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | ||
4050 | 4019 | ||
4051 | /*********************** | 4020 | /*********************** |
4052 | * 5. Setup HW Constants | 4021 | * 5. Setup HW Constants |