aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c250
1 files changed, 217 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index a9c30bcb65b8..8b9c419e094e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -122,6 +122,35 @@ static u8 is_single_stream(struct iwl4965_priv *priv)
122 return 0; 122 return 0;
123} 123}
124 124
125int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
126{
127 int idx = 0;
128
129 /* 4965 HT rate format */
130 if (rate_n_flags & RATE_MCS_HT_MSK) {
131 idx = (rate_n_flags & 0xff);
132
133 if (idx >= IWL_RATE_MIMO_6M_PLCP)
134 idx = idx - IWL_RATE_MIMO_6M_PLCP;
135
136 idx += IWL_FIRST_OFDM_RATE;
137 /* skip 9M not supported in ht*/
138 if (idx >= IWL_RATE_9M_INDEX)
139 idx += 1;
140 if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
141 return idx;
142
143 /* 4965 legacy rate format, search for match in table */
144 } else {
145 for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++)
146 if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF))
147 return idx;
148 }
149
150 return -1;
151}
152
153
125/* 154/*
126 * Determine how many receiver/antenna chains to use. 155 * Determine how many receiver/antenna chains to use.
127 * More provides better reception via diversity. Fewer saves power. 156 * More provides better reception via diversity. Fewer saves power.
@@ -3523,6 +3552,160 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad
3523 } 3552 }
3524 } 3553 }
3525} 3554}
3555#ifdef CONFIG_IWL4965_DEBUG
3556
3557/**
3558 * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions
3559 *
3560 * You may hack this function to show different aspects of received frames,
3561 * including selective frame dumps.
3562 * group100 parameter selects whether to show 1 out of 100 good frames.
3563 *
3564 * TODO: This was originally written for 3945, need to audit for
3565 * proper operation with 4965.
3566 */
3567static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv,
3568 struct iwl4965_rx_packet *pkt,
3569 struct ieee80211_hdr *header, int group100)
3570{
3571 u32 to_us;
3572 u32 print_summary = 0;
3573 u32 print_dump = 0; /* set to 1 to dump all frames' contents */
3574 u32 hundred = 0;
3575 u32 dataframe = 0;
3576 u16 fc;
3577 u16 seq_ctl;
3578 u16 channel;
3579 u16 phy_flags;
3580 int rate_sym;
3581 u16 length;
3582 u16 status;
3583 u16 bcn_tmr;
3584 u32 tsf_low;
3585 u64 tsf;
3586 u8 rssi;
3587 u8 agc;
3588 u16 sig_avg;
3589 u16 noise_diff;
3590 struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
3591 struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
3592 struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
3593 u8 *data = IWL_RX_DATA(pkt);
3594
3595 if (likely(!(iwl4965_debug_level & IWL_DL_RX)))
3596 return;
3597
3598 /* MAC header */
3599 fc = le16_to_cpu(header->frame_control);
3600 seq_ctl = le16_to_cpu(header->seq_ctrl);
3601
3602 /* metadata */
3603 channel = le16_to_cpu(rx_hdr->channel);
3604 phy_flags = le16_to_cpu(rx_hdr->phy_flags);
3605 rate_sym = rx_hdr->rate;
3606 length = le16_to_cpu(rx_hdr->len);
3607
3608 /* end-of-frame status and timestamp */
3609 status = le32_to_cpu(rx_end->status);
3610 bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
3611 tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
3612 tsf = le64_to_cpu(rx_end->timestamp);
3613
3614 /* signal statistics */
3615 rssi = rx_stats->rssi;
3616 agc = rx_stats->agc;
3617 sig_avg = le16_to_cpu(rx_stats->sig_avg);
3618 noise_diff = le16_to_cpu(rx_stats->noise_diff);
3619
3620 to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
3621
3622 /* if data frame is to us and all is good,
3623 * (optionally) print summary for only 1 out of every 100 */
3624 if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
3625 (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
3626 dataframe = 1;
3627 if (!group100)
3628 print_summary = 1; /* print each frame */
3629 else if (priv->framecnt_to_us < 100) {
3630 priv->framecnt_to_us++;
3631 print_summary = 0;
3632 } else {
3633 priv->framecnt_to_us = 0;
3634 print_summary = 1;
3635 hundred = 1;
3636 }
3637 } else {
3638 /* print summary for all other frames */
3639 print_summary = 1;
3640 }
3641
3642 if (print_summary) {
3643 char *title;
3644 int rate_idx;
3645 u32 bitrate;
3646
3647 if (hundred)
3648 title = "100Frames";
3649 else if (fc & IEEE80211_FCTL_RETRY)
3650 title = "Retry";
3651 else if (ieee80211_is_assoc_response(fc))
3652 title = "AscRsp";
3653 else if (ieee80211_is_reassoc_response(fc))
3654 title = "RasRsp";
3655 else if (ieee80211_is_probe_response(fc)) {
3656 title = "PrbRsp";
3657 print_dump = 1; /* dump frame contents */
3658 } else if (ieee80211_is_beacon(fc)) {
3659 title = "Beacon";
3660 print_dump = 1; /* dump frame contents */
3661 } else if (ieee80211_is_atim(fc))
3662 title = "ATIM";
3663 else if (ieee80211_is_auth(fc))
3664 title = "Auth";
3665 else if (ieee80211_is_deauth(fc))
3666 title = "DeAuth";
3667 else if (ieee80211_is_disassoc(fc))
3668 title = "DisAssoc";
3669 else
3670 title = "Frame";
3671
3672 rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym);
3673 if (unlikely(rate_idx == -1))
3674 bitrate = 0;
3675 else
3676 bitrate = iwl4965_rates[rate_idx].ieee / 2;
3677
3678 /* print frame summary.
3679 * MAC addresses show just the last byte (for brevity),
3680 * but you can hack it to show more, if you'd like to. */
3681 if (dataframe)
3682 IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
3683 "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
3684 title, fc, header->addr1[5],
3685 length, rssi, channel, bitrate);
3686 else {
3687 /* src/dst addresses assume managed mode */
3688 IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
3689 "src=0x%02x, rssi=%u, tim=%lu usec, "
3690 "phy=0x%02x, chnl=%d\n",
3691 title, fc, header->addr1[5],
3692 header->addr3[5], rssi,
3693 tsf_low - priv->scan_start_tsf,
3694 phy_flags, channel);
3695 }
3696 }
3697 if (print_dump)
3698 iwl4965_print_hex_dump(IWL_DL_RX, data, length);
3699}
3700#else
3701static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv,
3702 struct iwl4965_rx_packet *pkt,
3703 struct ieee80211_hdr *header,
3704 int group100)
3705{
3706}
3707#endif
3708
3526 3709
3527#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) 3710#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
3528 3711
@@ -3531,6 +3714,8 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad
3531static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, 3714static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3532 struct iwl4965_rx_mem_buffer *rxb) 3715 struct iwl4965_rx_mem_buffer *rxb)
3533{ 3716{
3717 struct ieee80211_hdr *header;
3718 struct ieee80211_rx_status rx_status;
3534 struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; 3719 struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
3535 /* Use phy data (Rx signal strength, etc.) contained within 3720 /* Use phy data (Rx signal strength, etc.) contained within
3536 * this rx packet for legacy frames, 3721 * this rx packet for legacy frames,
@@ -3541,27 +3726,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3541 (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; 3726 (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
3542 __le32 *rx_end; 3727 __le32 *rx_end;
3543 unsigned int len = 0; 3728 unsigned int len = 0;
3544 struct ieee80211_hdr *header;
3545 u16 fc; 3729 u16 fc;
3546 struct ieee80211_rx_status stats = {
3547 .mactime = le64_to_cpu(rx_start->timestamp),
3548 .freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)),
3549 .band =
3550 (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
3551 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ,
3552 .antenna = 0,
3553 .rate_idx = iwl4965_rate_index_from_plcp(
3554 le32_to_cpu(rx_start->rate_n_flags)),
3555 .flag = 0,
3556 };
3557 u8 network_packet; 3730 u8 network_packet;
3558 3731
3732 rx_status.mactime = le64_to_cpu(rx_start->timestamp);
3733 rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel));
3734 rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
3735 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
3736 rx_status.rate_idx = iwl4965_hwrate_to_plcp_idx(
3737 le32_to_cpu(rx_start->rate_n_flags));
3738
3739 if (rx_status.band == IEEE80211_BAND_5GHZ)
3740 rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
3741
3742 rx_status.antenna = 0;
3743 rx_status.flag = 0;
3744
3559 if ((unlikely(rx_start->cfg_phy_cnt > 20))) { 3745 if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
3560 IWL_DEBUG_DROP 3746 IWL_DEBUG_DROP
3561 ("dsp size out of range [0,20]: " 3747 ("dsp size out of range [0,20]: "
3562 "%d/n", rx_start->cfg_phy_cnt); 3748 "%d/n", rx_start->cfg_phy_cnt);
3563 return; 3749 return;
3564 } 3750 }
3751
3565 if (!include_phy) { 3752 if (!include_phy) {
3566 if (priv->last_phy_res[0]) 3753 if (priv->last_phy_res[0])
3567 rx_start = (struct iwl4965_rx_phy_res *) 3754 rx_start = (struct iwl4965_rx_phy_res *)
@@ -3580,7 +3767,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3580 + rx_start->cfg_phy_cnt); 3767 + rx_start->cfg_phy_cnt);
3581 3768
3582 len = le16_to_cpu(rx_start->byte_count); 3769 len = le16_to_cpu(rx_start->byte_count);
3583 rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt + 3770 rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
3584 sizeof(struct iwl4965_rx_phy_res) + len); 3771 sizeof(struct iwl4965_rx_phy_res) + len);
3585 } else { 3772 } else {
3586 struct iwl4965_rx_mpdu_res_start *amsdu = 3773 struct iwl4965_rx_mpdu_res_start *amsdu =
@@ -3603,7 +3790,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3603 priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); 3790 priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
3604 3791
3605 /* Find max signal strength (dBm) among 3 antenna/receiver chains */ 3792 /* Find max signal strength (dBm) among 3 antenna/receiver chains */
3606 stats.ssi = iwl4965_calc_rssi(rx_start); 3793 rx_status.ssi = iwl4965_calc_rssi(rx_start);
3607 3794
3608 /* Meaningful noise values are available only from beacon statistics, 3795 /* Meaningful noise values are available only from beacon statistics,
3609 * which are gathered only when associated, and indicate noise 3796 * which are gathered only when associated, and indicate noise
@@ -3611,32 +3798,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3611 * Ignore these noise values while scanning (other channels) */ 3798 * Ignore these noise values while scanning (other channels) */
3612 if (iwl4965_is_associated(priv) && 3799 if (iwl4965_is_associated(priv) &&
3613 !test_bit(STATUS_SCANNING, &priv->status)) { 3800 !test_bit(STATUS_SCANNING, &priv->status)) {
3614 stats.noise = priv->last_rx_noise; 3801 rx_status.noise = priv->last_rx_noise;
3615 stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise); 3802 rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
3803 rx_status.noise);
3616 } else { 3804 } else {
3617 stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; 3805 rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
3618 stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0); 3806 rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
3619 } 3807 }
3620 3808
3621 /* Reset beacon noise level if not associated. */ 3809 /* Reset beacon noise level if not associated. */
3622 if (!iwl4965_is_associated(priv)) 3810 if (!iwl4965_is_associated(priv))
3623 priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; 3811 priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
3624 3812
3625#ifdef CONFIG_IWL4965_DEBUG 3813 /* Set "1" to report good data frames in groups of 100 */
3626 /* TODO: Parts of iwl4965_report_frame are broken for 4965 */ 3814 /* FIXME: need to optimze the call: */
3627 if (iwl4965_debug_level & (IWL_DL_RX)) 3815 iwl4965_dbg_report_frame(priv, pkt, header, 1);
3628 /* Set "1" to report good data frames in groups of 100 */ 3816
3629 iwl4965_report_frame(priv, pkt, header, 1); 3817 IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
3630 3818 rx_status.ssi, rx_status.noise, rx_status.signal,
3631 if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS)) 3819 rx_status.mactime);
3632 IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n",
3633 stats.ssi, stats.noise, stats.signal,
3634 (long unsigned int)le64_to_cpu(rx_start->timestamp));
3635#endif
3636 3820
3637 network_packet = iwl4965_is_network_packet(priv, header); 3821 network_packet = iwl4965_is_network_packet(priv, header);
3638 if (network_packet) { 3822 if (network_packet) {
3639 priv->last_rx_rssi = stats.ssi; 3823 priv->last_rx_rssi = rx_status.ssi;
3640 priv->last_beacon_time = priv->ucode_beacon_time; 3824 priv->last_beacon_time = priv->ucode_beacon_time;
3641 priv->last_tsf = le64_to_cpu(rx_start->timestamp); 3825 priv->last_tsf = le64_to_cpu(rx_start->timestamp);
3642 } 3826 }
@@ -3739,7 +3923,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3739 return; 3923 return;
3740 } 3924 }
3741 } 3925 }
3742 iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats); 3926 iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
3743 break; 3927 break;
3744 3928
3745 case IEEE80211_FTYPE_CTL: 3929 case IEEE80211_FTYPE_CTL:
@@ -3748,7 +3932,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3748 case IEEE80211_STYPE_BACK_REQ: 3932 case IEEE80211_STYPE_BACK_REQ:
3749 IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); 3933 IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
3750 iwl4965_handle_data_packet(priv, 0, include_phy, 3934 iwl4965_handle_data_packet(priv, 0, include_phy,
3751 rxb, &stats); 3935 rxb, &rx_status);
3752 break; 3936 break;
3753 default: 3937 default:
3754 break; 3938 break;
@@ -3778,7 +3962,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
3778 print_mac(mac3, header->addr3)); 3962 print_mac(mac3, header->addr3));
3779 else 3963 else
3780 iwl4965_handle_data_packet(priv, 1, include_phy, rxb, 3964 iwl4965_handle_data_packet(priv, 1, include_phy, rxb,
3781 &stats); 3965 &rx_status);
3782 break; 3966 break;
3783 } 3967 }
3784 default: 3968 default: