iwlegacy: move under intel directory
Part of reorganising wireless drivers directory and Kconfig. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Esse commit está contido em:
@@ -12,5 +12,6 @@ config WLAN_VENDOR_INTEL
|
||||
if WLAN_VENDOR_INTEL
|
||||
|
||||
source "drivers/net/wireless/intel/ipw2x00/Kconfig"
|
||||
source "drivers/net/wireless/intel/iwlegacy/Kconfig"
|
||||
|
||||
endif # WLAN_VENDOR_INTEL
|
||||
|
@@ -1,2 +1,4 @@
|
||||
obj-$(CONFIG_IPW2100) += ipw2x00/
|
||||
obj-$(CONFIG_IPW2200) += ipw2x00/
|
||||
|
||||
obj-$(CONFIG_IWLEGACY) += iwlegacy/
|
||||
|
511
drivers/net/wireless/intel/iwlegacy/3945-debug.c
Arquivo normal
511
drivers/net/wireless/intel/iwlegacy/3945-debug.c
Arquivo normal
@@ -0,0 +1,511 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "3945.h"
|
||||
|
||||
static int
|
||||
il3945_stats_flag(struct il_priv *il, char *buf, int bufsz)
|
||||
{
|
||||
int p = 0;
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
|
||||
le32_to_cpu(il->_3945.stats.flag));
|
||||
if (le32_to_cpu(il->_3945.stats.flag) & UCODE_STATS_CLEAR_MSK)
|
||||
p += scnprintf(buf + p, bufsz - p,
|
||||
"\tStatistics have been cleared\n");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
|
||||
(le32_to_cpu(il->_3945.stats.flag) &
|
||||
UCODE_STATS_FREQUENCY_MSK) ? "2.4 GHz" : "5.2 GHz");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
|
||||
(le32_to_cpu(il->_3945.stats.flag) &
|
||||
UCODE_STATS_NARROW_BAND_MSK) ? "enabled" : "disabled");
|
||||
return p;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz =
|
||||
sizeof(struct iwl39_stats_rx_phy) * 40 +
|
||||
sizeof(struct iwl39_stats_rx_non_phy) * 40 + 400;
|
||||
ssize_t ret;
|
||||
struct iwl39_stats_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
|
||||
struct iwl39_stats_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
|
||||
struct iwl39_stats_rx_non_phy *general, *accum_general;
|
||||
struct iwl39_stats_rx_non_phy *delta_general, *max_general;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
ofdm = &il->_3945.stats.rx.ofdm;
|
||||
cck = &il->_3945.stats.rx.cck;
|
||||
general = &il->_3945.stats.rx.general;
|
||||
accum_ofdm = &il->_3945.accum_stats.rx.ofdm;
|
||||
accum_cck = &il->_3945.accum_stats.rx.cck;
|
||||
accum_general = &il->_3945.accum_stats.rx.general;
|
||||
delta_ofdm = &il->_3945.delta_stats.rx.ofdm;
|
||||
delta_cck = &il->_3945.delta_stats.rx.cck;
|
||||
delta_general = &il->_3945.delta_stats.rx.general;
|
||||
max_ofdm = &il->_3945.max_delta.rx.ofdm;
|
||||
max_cck = &il->_3945.max_delta.rx.cck;
|
||||
max_general = &il->_3945.max_delta.rx.general;
|
||||
|
||||
pos += il3945_stats_flag(il, buf, bufsz);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
"%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - OFDM:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "ina_cnt:",
|
||||
le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt,
|
||||
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_cnt:",
|
||||
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
|
||||
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "plcp_err:",
|
||||
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
|
||||
delta_ofdm->plcp_err, max_ofdm->plcp_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "crc32_err:",
|
||||
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
|
||||
delta_ofdm->crc32_err, max_ofdm->crc32_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "overrun_err:",
|
||||
le32_to_cpu(ofdm->overrun_err), accum_ofdm->overrun_err,
|
||||
delta_ofdm->overrun_err, max_ofdm->overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "early_overrun_err:",
|
||||
le32_to_cpu(ofdm->early_overrun_err),
|
||||
accum_ofdm->early_overrun_err,
|
||||
delta_ofdm->early_overrun_err,
|
||||
max_ofdm->early_overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "crc32_good:",
|
||||
le32_to_cpu(ofdm->crc32_good), accum_ofdm->crc32_good,
|
||||
delta_ofdm->crc32_good, max_ofdm->crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:",
|
||||
le32_to_cpu(ofdm->false_alarm_cnt),
|
||||
accum_ofdm->false_alarm_cnt, delta_ofdm->false_alarm_cnt,
|
||||
max_ofdm->false_alarm_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_sync_err_cnt:",
|
||||
le32_to_cpu(ofdm->fina_sync_err_cnt),
|
||||
accum_ofdm->fina_sync_err_cnt,
|
||||
delta_ofdm->fina_sync_err_cnt,
|
||||
max_ofdm->fina_sync_err_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sfd_timeout:",
|
||||
le32_to_cpu(ofdm->sfd_timeout), accum_ofdm->sfd_timeout,
|
||||
delta_ofdm->sfd_timeout, max_ofdm->sfd_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_timeout:",
|
||||
le32_to_cpu(ofdm->fina_timeout), accum_ofdm->fina_timeout,
|
||||
delta_ofdm->fina_timeout, max_ofdm->fina_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "unresponded_rts:",
|
||||
le32_to_cpu(ofdm->unresponded_rts),
|
||||
accum_ofdm->unresponded_rts, delta_ofdm->unresponded_rts,
|
||||
max_ofdm->unresponded_rts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
|
||||
accum_ofdm->rxe_frame_limit_overrun,
|
||||
delta_ofdm->rxe_frame_limit_overrun,
|
||||
max_ofdm->rxe_frame_limit_overrun);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
|
||||
le32_to_cpu(ofdm->sent_ack_cnt), accum_ofdm->sent_ack_cnt,
|
||||
delta_ofdm->sent_ack_cnt, max_ofdm->sent_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
|
||||
le32_to_cpu(ofdm->sent_cts_cnt), accum_ofdm->sent_cts_cnt,
|
||||
delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
|
||||
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
"%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - CCK:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "ina_cnt:",
|
||||
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
|
||||
delta_cck->ina_cnt, max_cck->ina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_cnt:",
|
||||
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
|
||||
delta_cck->fina_cnt, max_cck->fina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "plcp_err:",
|
||||
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
|
||||
delta_cck->plcp_err, max_cck->plcp_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "crc32_err:",
|
||||
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
|
||||
delta_cck->crc32_err, max_cck->crc32_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "overrun_err:",
|
||||
le32_to_cpu(cck->overrun_err), accum_cck->overrun_err,
|
||||
delta_cck->overrun_err, max_cck->overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "early_overrun_err:",
|
||||
le32_to_cpu(cck->early_overrun_err),
|
||||
accum_cck->early_overrun_err,
|
||||
delta_cck->early_overrun_err, max_cck->early_overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "crc32_good:",
|
||||
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
|
||||
delta_cck->crc32_good, max_cck->crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:",
|
||||
le32_to_cpu(cck->false_alarm_cnt),
|
||||
accum_cck->false_alarm_cnt, delta_cck->false_alarm_cnt,
|
||||
max_cck->false_alarm_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_sync_err_cnt:",
|
||||
le32_to_cpu(cck->fina_sync_err_cnt),
|
||||
accum_cck->fina_sync_err_cnt,
|
||||
delta_cck->fina_sync_err_cnt, max_cck->fina_sync_err_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sfd_timeout:",
|
||||
le32_to_cpu(cck->sfd_timeout), accum_cck->sfd_timeout,
|
||||
delta_cck->sfd_timeout, max_cck->sfd_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "fina_timeout:",
|
||||
le32_to_cpu(cck->fina_timeout), accum_cck->fina_timeout,
|
||||
delta_cck->fina_timeout, max_cck->fina_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "unresponded_rts:",
|
||||
le32_to_cpu(cck->unresponded_rts),
|
||||
accum_cck->unresponded_rts, delta_cck->unresponded_rts,
|
||||
max_cck->unresponded_rts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(cck->rxe_frame_limit_overrun),
|
||||
accum_cck->rxe_frame_limit_overrun,
|
||||
delta_cck->rxe_frame_limit_overrun,
|
||||
max_cck->rxe_frame_limit_overrun);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
|
||||
le32_to_cpu(cck->sent_ack_cnt), accum_cck->sent_ack_cnt,
|
||||
delta_cck->sent_ack_cnt, max_cck->sent_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
|
||||
le32_to_cpu(cck->sent_cts_cnt), accum_cck->sent_cts_cnt,
|
||||
delta_cck->sent_cts_cnt, max_cck->sent_cts_cnt);
|
||||
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
"%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - GENERAL:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "bogus_cts:",
|
||||
le32_to_cpu(general->bogus_cts), accum_general->bogus_cts,
|
||||
delta_general->bogus_cts, max_general->bogus_cts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "bogus_ack:",
|
||||
le32_to_cpu(general->bogus_ack), accum_general->bogus_ack,
|
||||
delta_general->bogus_ack, max_general->bogus_ack);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "non_bssid_frames:",
|
||||
le32_to_cpu(general->non_bssid_frames),
|
||||
accum_general->non_bssid_frames,
|
||||
delta_general->non_bssid_frames,
|
||||
max_general->non_bssid_frames);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "filtered_frames:",
|
||||
le32_to_cpu(general->filtered_frames),
|
||||
accum_general->filtered_frames,
|
||||
delta_general->filtered_frames,
|
||||
max_general->filtered_frames);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"non_channel_beacons:",
|
||||
le32_to_cpu(general->non_channel_beacons),
|
||||
accum_general->non_channel_beacons,
|
||||
delta_general->non_channel_beacons,
|
||||
max_general->non_channel_beacons);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = (sizeof(struct iwl39_stats_tx) * 48) + 250;
|
||||
ssize_t ret;
|
||||
struct iwl39_stats_tx *tx, *accum_tx, *delta_tx, *max_tx;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
tx = &il->_3945.stats.tx;
|
||||
accum_tx = &il->_3945.accum_stats.tx;
|
||||
delta_tx = &il->_3945.delta_stats.tx;
|
||||
max_tx = &il->_3945.max_delta.tx;
|
||||
pos += il3945_stats_flag(il, buf, bufsz);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
"%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Tx:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "preamble:",
|
||||
le32_to_cpu(tx->preamble_cnt), accum_tx->preamble_cnt,
|
||||
delta_tx->preamble_cnt, max_tx->preamble_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "rx_detected_cnt:",
|
||||
le32_to_cpu(tx->rx_detected_cnt),
|
||||
accum_tx->rx_detected_cnt, delta_tx->rx_detected_cnt,
|
||||
max_tx->rx_detected_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "bt_prio_defer_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_defer_cnt),
|
||||
accum_tx->bt_prio_defer_cnt, delta_tx->bt_prio_defer_cnt,
|
||||
max_tx->bt_prio_defer_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "bt_prio_kill_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_kill_cnt),
|
||||
accum_tx->bt_prio_kill_cnt, delta_tx->bt_prio_kill_cnt,
|
||||
max_tx->bt_prio_kill_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "few_bytes_cnt:",
|
||||
le32_to_cpu(tx->few_bytes_cnt), accum_tx->few_bytes_cnt,
|
||||
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "cts_timeout:",
|
||||
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
|
||||
delta_tx->cts_timeout, max_tx->cts_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "ack_timeout:",
|
||||
le32_to_cpu(tx->ack_timeout), accum_tx->ack_timeout,
|
||||
delta_tx->ack_timeout, max_tx->ack_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "expected_ack_cnt:",
|
||||
le32_to_cpu(tx->expected_ack_cnt),
|
||||
accum_tx->expected_ack_cnt, delta_tx->expected_ack_cnt,
|
||||
max_tx->expected_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "actual_ack_cnt:",
|
||||
le32_to_cpu(tx->actual_ack_cnt), accum_tx->actual_ack_cnt,
|
||||
delta_tx->actual_ack_cnt, max_tx->actual_ack_cnt);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il3945_ucode_general_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = sizeof(struct iwl39_stats_general) * 10 + 300;
|
||||
ssize_t ret;
|
||||
struct iwl39_stats_general *general, *accum_general;
|
||||
struct iwl39_stats_general *delta_general, *max_general;
|
||||
struct stats_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
|
||||
struct iwl39_stats_div *div, *accum_div, *delta_div, *max_div;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
general = &il->_3945.stats.general;
|
||||
dbg = &il->_3945.stats.general.dbg;
|
||||
div = &il->_3945.stats.general.div;
|
||||
accum_general = &il->_3945.accum_stats.general;
|
||||
delta_general = &il->_3945.delta_stats.general;
|
||||
max_general = &il->_3945.max_delta.general;
|
||||
accum_dbg = &il->_3945.accum_stats.general.dbg;
|
||||
delta_dbg = &il->_3945.delta_stats.general.dbg;
|
||||
max_dbg = &il->_3945.max_delta.general.dbg;
|
||||
accum_div = &il->_3945.accum_stats.general.div;
|
||||
delta_div = &il->_3945.delta_stats.general.div;
|
||||
max_div = &il->_3945.max_delta.general.div;
|
||||
pos += il3945_stats_flag(il, buf, bufsz);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
"%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_General:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "burst_check:",
|
||||
le32_to_cpu(dbg->burst_check), accum_dbg->burst_check,
|
||||
delta_dbg->burst_check, max_dbg->burst_check);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "burst_count:",
|
||||
le32_to_cpu(dbg->burst_count), accum_dbg->burst_count,
|
||||
delta_dbg->burst_count, max_dbg->burst_count);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "sleep_time:",
|
||||
le32_to_cpu(general->sleep_time),
|
||||
accum_general->sleep_time, delta_general->sleep_time,
|
||||
max_general->sleep_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "slots_out:",
|
||||
le32_to_cpu(general->slots_out), accum_general->slots_out,
|
||||
delta_general->slots_out, max_general->slots_out);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "slots_idle:",
|
||||
le32_to_cpu(general->slots_idle),
|
||||
accum_general->slots_idle, delta_general->slots_idle,
|
||||
max_general->slots_idle);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
|
||||
le32_to_cpu(general->ttl_timestamp));
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "tx_on_a:",
|
||||
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
|
||||
delta_div->tx_on_a, max_div->tx_on_a);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "tx_on_b:",
|
||||
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
|
||||
delta_div->tx_on_b, max_div->tx_on_b);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "exec_time:",
|
||||
le32_to_cpu(div->exec_time), accum_div->exec_time,
|
||||
delta_div->exec_time, max_div->exec_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "probe_time:",
|
||||
le32_to_cpu(div->probe_time), accum_div->probe_time,
|
||||
delta_div->probe_time, max_div->probe_time);
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct il_debugfs_ops il3945_debugfs_ops = {
|
||||
.rx_stats_read = il3945_ucode_rx_stats_read,
|
||||
.tx_stats_read = il3945_ucode_tx_stats_read,
|
||||
.general_stats_read = il3945_ucode_general_stats_read,
|
||||
};
|
3959
drivers/net/wireless/intel/iwlegacy/3945-mac.c
Arquivo normal
3959
drivers/net/wireless/intel/iwlegacy/3945-mac.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
979
drivers/net/wireless/intel/iwlegacy/3945-rs.c
Arquivo normal
979
drivers/net/wireless/intel/iwlegacy/3945-rs.c
Arquivo normal
@@ -0,0 +1,979 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "3945.h"
|
||||
|
||||
#define RS_NAME "iwl-3945-rs"
|
||||
|
||||
static s32 il3945_expected_tpt_g[RATE_COUNT_3945] = {
|
||||
7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
|
||||
};
|
||||
|
||||
static s32 il3945_expected_tpt_g_prot[RATE_COUNT_3945] = {
|
||||
7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
|
||||
};
|
||||
|
||||
static s32 il3945_expected_tpt_a[RATE_COUNT_3945] = {
|
||||
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
|
||||
};
|
||||
|
||||
static s32 il3945_expected_tpt_b[RATE_COUNT_3945] = {
|
||||
7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
struct il3945_tpt_entry {
|
||||
s8 min_rssi;
|
||||
u8 idx;
|
||||
};
|
||||
|
||||
static struct il3945_tpt_entry il3945_tpt_table_a[] = {
|
||||
{-60, RATE_54M_IDX},
|
||||
{-64, RATE_48M_IDX},
|
||||
{-72, RATE_36M_IDX},
|
||||
{-80, RATE_24M_IDX},
|
||||
{-84, RATE_18M_IDX},
|
||||
{-85, RATE_12M_IDX},
|
||||
{-87, RATE_9M_IDX},
|
||||
{-89, RATE_6M_IDX}
|
||||
};
|
||||
|
||||
static struct il3945_tpt_entry il3945_tpt_table_g[] = {
|
||||
{-60, RATE_54M_IDX},
|
||||
{-64, RATE_48M_IDX},
|
||||
{-68, RATE_36M_IDX},
|
||||
{-80, RATE_24M_IDX},
|
||||
{-84, RATE_18M_IDX},
|
||||
{-85, RATE_12M_IDX},
|
||||
{-86, RATE_11M_IDX},
|
||||
{-88, RATE_5M_IDX},
|
||||
{-90, RATE_2M_IDX},
|
||||
{-92, RATE_1M_IDX}
|
||||
};
|
||||
|
||||
#define RATE_MAX_WINDOW 62
|
||||
#define RATE_FLUSH (3*HZ)
|
||||
#define RATE_WIN_FLUSH (HZ/2)
|
||||
#define IL39_RATE_HIGH_TH 11520
|
||||
#define IL_SUCCESS_UP_TH 8960
|
||||
#define IL_SUCCESS_DOWN_TH 10880
|
||||
#define RATE_MIN_FAILURE_TH 6
|
||||
#define RATE_MIN_SUCCESS_TH 8
|
||||
#define RATE_DECREASE_TH 1920
|
||||
#define RATE_RETRY_TH 15
|
||||
|
||||
static u8
|
||||
il3945_get_rate_idx_by_rssi(s32 rssi, enum ieee80211_band band)
|
||||
{
|
||||
u32 idx = 0;
|
||||
u32 table_size = 0;
|
||||
struct il3945_tpt_entry *tpt_table = NULL;
|
||||
|
||||
if (rssi < IL_MIN_RSSI_VAL || rssi > IL_MAX_RSSI_VAL)
|
||||
rssi = IL_MIN_RSSI_VAL;
|
||||
|
||||
switch (band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
tpt_table = il3945_tpt_table_g;
|
||||
table_size = ARRAY_SIZE(il3945_tpt_table_g);
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
tpt_table = il3945_tpt_table_a;
|
||||
table_size = ARRAY_SIZE(il3945_tpt_table_a);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
while (idx < table_size && rssi < tpt_table[idx].min_rssi)
|
||||
idx++;
|
||||
|
||||
idx = min(idx, table_size - 1);
|
||||
|
||||
return tpt_table[idx].idx;
|
||||
}
|
||||
|
||||
static void
|
||||
il3945_clear_win(struct il3945_rate_scale_data *win)
|
||||
{
|
||||
win->data = 0;
|
||||
win->success_counter = 0;
|
||||
win->success_ratio = -1;
|
||||
win->counter = 0;
|
||||
win->average_tpt = IL_INVALID_VALUE;
|
||||
win->stamp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* il3945_rate_scale_flush_wins - flush out the rate scale wins
|
||||
*
|
||||
* Returns the number of wins that have gathered data but were
|
||||
* not flushed. If there were any that were not flushed, then
|
||||
* reschedule the rate flushing routine.
|
||||
*/
|
||||
static int
|
||||
il3945_rate_scale_flush_wins(struct il3945_rs_sta *rs_sta)
|
||||
{
|
||||
int unflushed = 0;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct il_priv *il __maybe_unused = rs_sta->il;
|
||||
|
||||
/*
|
||||
* For each rate, if we have collected data on that rate
|
||||
* and it has been more than RATE_WIN_FLUSH
|
||||
* since we flushed, clear out the gathered stats
|
||||
*/
|
||||
for (i = 0; i < RATE_COUNT_3945; i++) {
|
||||
if (!rs_sta->win[i].counter)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
if (time_after(jiffies, rs_sta->win[i].stamp + RATE_WIN_FLUSH)) {
|
||||
D_RATE("flushing %d samples of rate " "idx %d\n",
|
||||
rs_sta->win[i].counter, i);
|
||||
il3945_clear_win(&rs_sta->win[i]);
|
||||
} else
|
||||
unflushed++;
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
}
|
||||
|
||||
return unflushed;
|
||||
}
|
||||
|
||||
#define RATE_FLUSH_MAX 5000 /* msec */
|
||||
#define RATE_FLUSH_MIN 50 /* msec */
|
||||
#define IL_AVERAGE_PACKETS 1500
|
||||
|
||||
static void
|
||||
il3945_bg_rate_scale_flush(unsigned long data)
|
||||
{
|
||||
struct il3945_rs_sta *rs_sta = (void *)data;
|
||||
struct il_priv *il __maybe_unused = rs_sta->il;
|
||||
int unflushed = 0;
|
||||
unsigned long flags;
|
||||
u32 packet_count, duration, pps;
|
||||
|
||||
D_RATE("enter\n");
|
||||
|
||||
unflushed = il3945_rate_scale_flush_wins(rs_sta);
|
||||
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
|
||||
/* Number of packets Rx'd since last time this timer ran */
|
||||
packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
|
||||
|
||||
rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
|
||||
|
||||
if (unflushed) {
|
||||
duration =
|
||||
jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
|
||||
|
||||
D_RATE("Tx'd %d packets in %dms\n", packet_count, duration);
|
||||
|
||||
/* Determine packets per second */
|
||||
if (duration)
|
||||
pps = (packet_count * 1000) / duration;
|
||||
else
|
||||
pps = 0;
|
||||
|
||||
if (pps) {
|
||||
duration = (IL_AVERAGE_PACKETS * 1000) / pps;
|
||||
if (duration < RATE_FLUSH_MIN)
|
||||
duration = RATE_FLUSH_MIN;
|
||||
else if (duration > RATE_FLUSH_MAX)
|
||||
duration = RATE_FLUSH_MAX;
|
||||
} else
|
||||
duration = RATE_FLUSH_MAX;
|
||||
|
||||
rs_sta->flush_time = msecs_to_jiffies(duration);
|
||||
|
||||
D_RATE("new flush period: %d msec ave %d\n", duration,
|
||||
packet_count);
|
||||
|
||||
mod_timer(&rs_sta->rate_scale_flush,
|
||||
jiffies + rs_sta->flush_time);
|
||||
|
||||
rs_sta->last_partial_flush = jiffies;
|
||||
} else {
|
||||
rs_sta->flush_time = RATE_FLUSH;
|
||||
rs_sta->flush_pending = 0;
|
||||
}
|
||||
/* If there weren't any unflushed entries, we don't schedule the timer
|
||||
* to run again */
|
||||
|
||||
rs_sta->last_flush = jiffies;
|
||||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
D_RATE("leave\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* il3945_collect_tx_data - Update the success/failure sliding win
|
||||
*
|
||||
* We keep a sliding win of the last 64 packets transmitted
|
||||
* at this rate. win->data contains the bitmask of successful
|
||||
* packets.
|
||||
*/
|
||||
static void
|
||||
il3945_collect_tx_data(struct il3945_rs_sta *rs_sta,
|
||||
struct il3945_rate_scale_data *win, int success,
|
||||
int retries, int idx)
|
||||
{
|
||||
unsigned long flags;
|
||||
s32 fail_count;
|
||||
struct il_priv *il __maybe_unused = rs_sta->il;
|
||||
|
||||
if (!retries) {
|
||||
D_RATE("leave: retries == 0 -- should be at least 1\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
|
||||
/*
|
||||
* Keep track of only the latest 62 tx frame attempts in this rate's
|
||||
* history win; anything older isn't really relevant any more.
|
||||
* If we have filled up the sliding win, drop the oldest attempt;
|
||||
* if the oldest attempt (highest bit in bitmap) shows "success",
|
||||
* subtract "1" from the success counter (this is the main reason
|
||||
* we keep these bitmaps!).
|
||||
* */
|
||||
while (retries > 0) {
|
||||
if (win->counter >= RATE_MAX_WINDOW) {
|
||||
|
||||
/* remove earliest */
|
||||
win->counter = RATE_MAX_WINDOW - 1;
|
||||
|
||||
if (win->data & (1ULL << (RATE_MAX_WINDOW - 1))) {
|
||||
win->data &= ~(1ULL << (RATE_MAX_WINDOW - 1));
|
||||
win->success_counter--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment frames-attempted counter */
|
||||
win->counter++;
|
||||
|
||||
/* Shift bitmap by one frame (throw away oldest history),
|
||||
* OR in "1", and increment "success" if this
|
||||
* frame was successful. */
|
||||
win->data <<= 1;
|
||||
if (success > 0) {
|
||||
win->success_counter++;
|
||||
win->data |= 0x1;
|
||||
success--;
|
||||
}
|
||||
|
||||
retries--;
|
||||
}
|
||||
|
||||
/* Calculate current success ratio, avoid divide-by-0! */
|
||||
if (win->counter > 0)
|
||||
win->success_ratio =
|
||||
128 * (100 * win->success_counter) / win->counter;
|
||||
else
|
||||
win->success_ratio = IL_INVALID_VALUE;
|
||||
|
||||
fail_count = win->counter - win->success_counter;
|
||||
|
||||
/* Calculate average throughput, if we have enough history. */
|
||||
if (fail_count >= RATE_MIN_FAILURE_TH ||
|
||||
win->success_counter >= RATE_MIN_SUCCESS_TH)
|
||||
win->average_tpt =
|
||||
((win->success_ratio * rs_sta->expected_tpt[idx] +
|
||||
64) / 128);
|
||||
else
|
||||
win->average_tpt = IL_INVALID_VALUE;
|
||||
|
||||
/* Tag this win as having been updated */
|
||||
win->stamp = jiffies;
|
||||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after adding a new station to initialize rate scaling
|
||||
*/
|
||||
void
|
||||
il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
|
||||
{
|
||||
struct ieee80211_hw *hw = il->hw;
|
||||
struct ieee80211_conf *conf = &il->hw->conf;
|
||||
struct il3945_sta_priv *psta;
|
||||
struct il3945_rs_sta *rs_sta;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int i;
|
||||
|
||||
D_INFO("enter\n");
|
||||
if (sta_id == il->hw_params.bcast_id)
|
||||
goto out;
|
||||
|
||||
psta = (struct il3945_sta_priv *)sta->drv_priv;
|
||||
rs_sta = &psta->rs_sta;
|
||||
sband = hw->wiphy->bands[conf->chandef.chan->band];
|
||||
|
||||
rs_sta->il = il;
|
||||
|
||||
rs_sta->start_rate = RATE_INVALID;
|
||||
|
||||
/* default to just 802.11b */
|
||||
rs_sta->expected_tpt = il3945_expected_tpt_b;
|
||||
|
||||
rs_sta->last_partial_flush = jiffies;
|
||||
rs_sta->last_flush = jiffies;
|
||||
rs_sta->flush_time = RATE_FLUSH;
|
||||
rs_sta->last_tx_packets = 0;
|
||||
|
||||
rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
|
||||
rs_sta->rate_scale_flush.function = il3945_bg_rate_scale_flush;
|
||||
|
||||
for (i = 0; i < RATE_COUNT_3945; i++)
|
||||
il3945_clear_win(&rs_sta->win[i]);
|
||||
|
||||
/* TODO: what is a good starting rate for STA? About middle? Maybe not
|
||||
* the lowest or the highest rate.. Could consider using RSSI from
|
||||
* previous packets? Need to have IEEE 802.1X auth succeed immediately
|
||||
* after assoc.. */
|
||||
|
||||
for (i = sband->n_bitrates - 1; i >= 0; i--) {
|
||||
if (sta->supp_rates[sband->band] & (1 << i)) {
|
||||
rs_sta->last_txrate_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
il->_3945.sta_supp_rates = sta->supp_rates[sband->band];
|
||||
/* For 5 GHz band it start at IL_FIRST_OFDM_RATE */
|
||||
if (sband->band == IEEE80211_BAND_5GHZ) {
|
||||
rs_sta->last_txrate_idx += IL_FIRST_OFDM_RATE;
|
||||
il->_3945.sta_supp_rates <<= IL_FIRST_OFDM_RATE;
|
||||
}
|
||||
|
||||
out:
|
||||
il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
|
||||
|
||||
D_INFO("leave\n");
|
||||
}
|
||||
|
||||
static void *
|
||||
il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||
{
|
||||
return hw->priv;
|
||||
}
|
||||
|
||||
/* rate scale requires free function to be implemented */
|
||||
static void
|
||||
il3945_rs_free(void *il)
|
||||
{
|
||||
}
|
||||
|
||||
static void *
|
||||
il3945_rs_alloc_sta(void *il_priv, struct ieee80211_sta *sta, gfp_t gfp)
|
||||
{
|
||||
struct il3945_rs_sta *rs_sta;
|
||||
struct il3945_sta_priv *psta = (void *)sta->drv_priv;
|
||||
struct il_priv *il __maybe_unused = il_priv;
|
||||
|
||||
D_RATE("enter\n");
|
||||
|
||||
rs_sta = &psta->rs_sta;
|
||||
|
||||
spin_lock_init(&rs_sta->lock);
|
||||
init_timer(&rs_sta->rate_scale_flush);
|
||||
|
||||
D_RATE("leave\n");
|
||||
|
||||
return rs_sta;
|
||||
}
|
||||
|
||||
static void
|
||||
il3945_rs_free_sta(void *il_priv, struct ieee80211_sta *sta, void *il_sta)
|
||||
{
|
||||
struct il3945_rs_sta *rs_sta = il_sta;
|
||||
|
||||
/*
|
||||
* Be careful not to use any members of il3945_rs_sta (like trying
|
||||
* to use il_priv to print out debugging) since it may not be fully
|
||||
* initialized at this point.
|
||||
*/
|
||||
del_timer_sync(&rs_sta->rate_scale_flush);
|
||||
}
|
||||
|
||||
/**
|
||||
* il3945_rs_tx_status - Update rate control values based on Tx results
|
||||
*
|
||||
* NOTE: Uses il_priv->retry_rate for the # of retries attempted by
|
||||
* the hardware for each rate.
|
||||
*/
|
||||
static void
|
||||
il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_sta *sta, void *il_sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
s8 retries = 0, current_count;
|
||||
int scale_rate_idx, first_idx, last_idx;
|
||||
unsigned long flags;
|
||||
struct il_priv *il = (struct il_priv *)il_rate;
|
||||
struct il3945_rs_sta *rs_sta = il_sta;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
D_RATE("enter\n");
|
||||
|
||||
retries = info->status.rates[0].count;
|
||||
/* Sanity Check for retries */
|
||||
if (retries > RATE_RETRY_TH)
|
||||
retries = RATE_RETRY_TH;
|
||||
|
||||
first_idx = sband->bitrates[info->status.rates[0].idx].hw_value;
|
||||
if (first_idx < 0 || first_idx >= RATE_COUNT_3945) {
|
||||
D_RATE("leave: Rate out of bounds: %d\n", first_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!il_sta) {
|
||||
D_RATE("leave: No STA il data to update!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Treat uninitialized rate scaling data same as non-existing. */
|
||||
if (!rs_sta->il) {
|
||||
D_RATE("leave: STA il data uninitialized!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rs_sta->tx_packets++;
|
||||
|
||||
scale_rate_idx = first_idx;
|
||||
last_idx = first_idx;
|
||||
|
||||
/*
|
||||
* Update the win for each rate. We determine which rates
|
||||
* were Tx'd based on the total number of retries vs. the number
|
||||
* of retries configured for each rate -- currently set to the
|
||||
* il value 'retry_rate' vs. rate specific
|
||||
*
|
||||
* On exit from this while loop last_idx indicates the rate
|
||||
* at which the frame was finally transmitted (or failed if no
|
||||
* ACK)
|
||||
*/
|
||||
while (retries > 1) {
|
||||
if ((retries - 1) < il->retry_rate) {
|
||||
current_count = (retries - 1);
|
||||
last_idx = scale_rate_idx;
|
||||
} else {
|
||||
current_count = il->retry_rate;
|
||||
last_idx = il3945_rs_next_rate(il, scale_rate_idx);
|
||||
}
|
||||
|
||||
/* Update this rate accounting for as many retries
|
||||
* as was used for it (per current_count) */
|
||||
il3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_idx], 0,
|
||||
current_count, scale_rate_idx);
|
||||
D_RATE("Update rate %d for %d retries.\n", scale_rate_idx,
|
||||
current_count);
|
||||
|
||||
retries -= current_count;
|
||||
|
||||
scale_rate_idx = last_idx;
|
||||
}
|
||||
|
||||
/* Update the last idx win with success/failure based on ACK */
|
||||
D_RATE("Update rate %d with %s.\n", last_idx,
|
||||
(info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure");
|
||||
il3945_collect_tx_data(rs_sta, &rs_sta->win[last_idx],
|
||||
info->flags & IEEE80211_TX_STAT_ACK, 1,
|
||||
last_idx);
|
||||
|
||||
/* We updated the rate scale win -- if its been more than
|
||||
* flush_time since the last run, schedule the flush
|
||||
* again */
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
|
||||
if (!rs_sta->flush_pending &&
|
||||
time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) {
|
||||
|
||||
rs_sta->last_partial_flush = jiffies;
|
||||
rs_sta->flush_pending = 1;
|
||||
mod_timer(&rs_sta->rate_scale_flush,
|
||||
jiffies + rs_sta->flush_time);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
D_RATE("leave\n");
|
||||
}
|
||||
|
||||
static u16
|
||||
il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
u8 high = RATE_INVALID;
|
||||
u8 low = RATE_INVALID;
|
||||
struct il_priv *il __maybe_unused = rs_sta->il;
|
||||
|
||||
/* 802.11A walks to the next literal adjacent rate in
|
||||
* the rate table */
|
||||
if (unlikely(band == IEEE80211_BAND_5GHZ)) {
|
||||
int i;
|
||||
u32 mask;
|
||||
|
||||
/* Find the previous rate that is in the rate mask */
|
||||
i = idx - 1;
|
||||
for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
|
||||
if (rate_mask & mask) {
|
||||
low = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next rate that is in the rate mask */
|
||||
i = idx + 1;
|
||||
for (mask = (1 << i); i < RATE_COUNT_3945; i++, mask <<= 1) {
|
||||
if (rate_mask & mask) {
|
||||
high = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
low = idx;
|
||||
while (low != RATE_INVALID) {
|
||||
if (rs_sta->tgg)
|
||||
low = il3945_rates[low].prev_rs_tgg;
|
||||
else
|
||||
low = il3945_rates[low].prev_rs;
|
||||
if (low == RATE_INVALID)
|
||||
break;
|
||||
if (rate_mask & (1 << low))
|
||||
break;
|
||||
D_RATE("Skipping masked lower rate: %d\n", low);
|
||||
}
|
||||
|
||||
high = idx;
|
||||
while (high != RATE_INVALID) {
|
||||
if (rs_sta->tgg)
|
||||
high = il3945_rates[high].next_rs_tgg;
|
||||
else
|
||||
high = il3945_rates[high].next_rs;
|
||||
if (high == RATE_INVALID)
|
||||
break;
|
||||
if (rate_mask & (1 << high))
|
||||
break;
|
||||
D_RATE("Skipping masked higher rate: %d\n", high);
|
||||
}
|
||||
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
/**
|
||||
* il3945_rs_get_rate - find the rate for the requested packet
|
||||
*
|
||||
* Returns the ieee80211_rate structure allocated by the driver.
|
||||
*
|
||||
* The rate control algorithm has no internal mapping between hw_mode's
|
||||
* rate ordering and the rate ordering used by the rate control algorithm.
|
||||
*
|
||||
* The rate control algorithm uses a single table of rates that goes across
|
||||
* the entire A/B/G spectrum vs. being limited to just one particular
|
||||
* hw_mode.
|
||||
*
|
||||
* As such, we can't convert the idx obtained below into the hw_mode's
|
||||
* rate table and must reference the driver allocated rate table
|
||||
*
|
||||
*/
|
||||
static void
|
||||
il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
|
||||
struct ieee80211_tx_rate_control *txrc)
|
||||
{
|
||||
struct ieee80211_supported_band *sband = txrc->sband;
|
||||
struct sk_buff *skb = txrc->skb;
|
||||
u8 low = RATE_INVALID;
|
||||
u8 high = RATE_INVALID;
|
||||
u16 high_low;
|
||||
int idx;
|
||||
struct il3945_rs_sta *rs_sta = il_sta;
|
||||
struct il3945_rate_scale_data *win = NULL;
|
||||
int current_tpt = IL_INVALID_VALUE;
|
||||
int low_tpt = IL_INVALID_VALUE;
|
||||
int high_tpt = IL_INVALID_VALUE;
|
||||
u32 fail_count;
|
||||
s8 scale_action = 0;
|
||||
unsigned long flags;
|
||||
u16 rate_mask;
|
||||
s8 max_rate_idx = -1;
|
||||
struct il_priv *il __maybe_unused = (struct il_priv *)il_r;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
D_RATE("enter\n");
|
||||
|
||||
/* Treat uninitialized rate scaling data same as non-existing. */
|
||||
if (rs_sta && !rs_sta->il) {
|
||||
D_RATE("Rate scaling information not initialized yet.\n");
|
||||
il_sta = NULL;
|
||||
}
|
||||
|
||||
if (rate_control_send_low(sta, il_sta, txrc))
|
||||
return;
|
||||
|
||||
rate_mask = sta->supp_rates[sband->band];
|
||||
|
||||
/* get user max rate if set */
|
||||
max_rate_idx = txrc->max_rate_idx;
|
||||
if (sband->band == IEEE80211_BAND_5GHZ && max_rate_idx != -1)
|
||||
max_rate_idx += IL_FIRST_OFDM_RATE;
|
||||
if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT)
|
||||
max_rate_idx = -1;
|
||||
|
||||
idx = min(rs_sta->last_txrate_idx & 0xffff, RATE_COUNT_3945 - 1);
|
||||
|
||||
if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
rate_mask = rate_mask << IL_FIRST_OFDM_RATE;
|
||||
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
|
||||
/* for recent assoc, choose best rate regarding
|
||||
* to rssi value
|
||||
*/
|
||||
if (rs_sta->start_rate != RATE_INVALID) {
|
||||
if (rs_sta->start_rate < idx &&
|
||||
(rate_mask & (1 << rs_sta->start_rate)))
|
||||
idx = rs_sta->start_rate;
|
||||
rs_sta->start_rate = RATE_INVALID;
|
||||
}
|
||||
|
||||
/* force user max rate if set by user */
|
||||
if (max_rate_idx != -1 && max_rate_idx < idx) {
|
||||
if (rate_mask & (1 << max_rate_idx))
|
||||
idx = max_rate_idx;
|
||||
}
|
||||
|
||||
win = &(rs_sta->win[idx]);
|
||||
|
||||
fail_count = win->counter - win->success_counter;
|
||||
|
||||
if (fail_count < RATE_MIN_FAILURE_TH &&
|
||||
win->success_counter < RATE_MIN_SUCCESS_TH) {
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
D_RATE("Invalid average_tpt on rate %d: "
|
||||
"counter: %d, success_counter: %d, "
|
||||
"expected_tpt is %sNULL\n", idx, win->counter,
|
||||
win->success_counter,
|
||||
rs_sta->expected_tpt ? "not " : "");
|
||||
|
||||
/* Can't calculate this yet; not enough history */
|
||||
win->average_tpt = IL_INVALID_VALUE;
|
||||
goto out;
|
||||
|
||||
}
|
||||
|
||||
current_tpt = win->average_tpt;
|
||||
|
||||
high_low =
|
||||
il3945_get_adjacent_rate(rs_sta, idx, rate_mask, sband->band);
|
||||
low = high_low & 0xff;
|
||||
high = (high_low >> 8) & 0xff;
|
||||
|
||||
/* If user set max rate, dont allow higher than user constrain */
|
||||
if (max_rate_idx != -1 && max_rate_idx < high)
|
||||
high = RATE_INVALID;
|
||||
|
||||
/* Collect Measured throughputs of adjacent rates */
|
||||
if (low != RATE_INVALID)
|
||||
low_tpt = rs_sta->win[low].average_tpt;
|
||||
|
||||
if (high != RATE_INVALID)
|
||||
high_tpt = rs_sta->win[high].average_tpt;
|
||||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
scale_action = 0;
|
||||
|
||||
/* Low success ratio , need to drop the rate */
|
||||
if (win->success_ratio < RATE_DECREASE_TH || !current_tpt) {
|
||||
D_RATE("decrease rate because of low success_ratio\n");
|
||||
scale_action = -1;
|
||||
/* No throughput measured yet for adjacent rates,
|
||||
* try increase */
|
||||
} else if (low_tpt == IL_INVALID_VALUE && high_tpt == IL_INVALID_VALUE) {
|
||||
|
||||
if (high != RATE_INVALID &&
|
||||
win->success_ratio >= RATE_INCREASE_TH)
|
||||
scale_action = 1;
|
||||
else if (low != RATE_INVALID)
|
||||
scale_action = 0;
|
||||
|
||||
/* Both adjacent throughputs are measured, but neither one has
|
||||
* better throughput; we're using the best rate, don't change
|
||||
* it! */
|
||||
} else if (low_tpt != IL_INVALID_VALUE && high_tpt != IL_INVALID_VALUE
|
||||
&& low_tpt < current_tpt && high_tpt < current_tpt) {
|
||||
|
||||
D_RATE("No action -- low [%d] & high [%d] < "
|
||||
"current_tpt [%d]\n", low_tpt, high_tpt, current_tpt);
|
||||
scale_action = 0;
|
||||
|
||||
/* At least one of the rates has better throughput */
|
||||
} else {
|
||||
if (high_tpt != IL_INVALID_VALUE) {
|
||||
|
||||
/* High rate has better throughput, Increase
|
||||
* rate */
|
||||
if (high_tpt > current_tpt &&
|
||||
win->success_ratio >= RATE_INCREASE_TH)
|
||||
scale_action = 1;
|
||||
else {
|
||||
D_RATE("decrease rate because of high tpt\n");
|
||||
scale_action = 0;
|
||||
}
|
||||
} else if (low_tpt != IL_INVALID_VALUE) {
|
||||
if (low_tpt > current_tpt) {
|
||||
D_RATE("decrease rate because of low tpt\n");
|
||||
scale_action = -1;
|
||||
} else if (win->success_ratio >= RATE_INCREASE_TH) {
|
||||
/* Lower rate has better
|
||||
* throughput,decrease rate */
|
||||
scale_action = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check; asked for decrease, but success rate or throughput
|
||||
* has been good at old rate. Don't change it. */
|
||||
if (scale_action == -1 && low != RATE_INVALID &&
|
||||
(win->success_ratio > RATE_HIGH_TH ||
|
||||
current_tpt > 100 * rs_sta->expected_tpt[low]))
|
||||
scale_action = 0;
|
||||
|
||||
switch (scale_action) {
|
||||
case -1:
|
||||
/* Decrese rate */
|
||||
if (low != RATE_INVALID)
|
||||
idx = low;
|
||||
break;
|
||||
case 1:
|
||||
/* Increase rate */
|
||||
if (high != RATE_INVALID)
|
||||
idx = high;
|
||||
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
/* No change */
|
||||
break;
|
||||
}
|
||||
|
||||
D_RATE("Selected %d (action %d) - low %d high %d\n", idx, scale_action,
|
||||
low, high);
|
||||
|
||||
out:
|
||||
|
||||
if (sband->band == IEEE80211_BAND_5GHZ) {
|
||||
if (WARN_ON_ONCE(idx < IL_FIRST_OFDM_RATE))
|
||||
idx = IL_FIRST_OFDM_RATE;
|
||||
rs_sta->last_txrate_idx = idx;
|
||||
info->control.rates[0].idx = idx - IL_FIRST_OFDM_RATE;
|
||||
} else {
|
||||
rs_sta->last_txrate_idx = idx;
|
||||
info->control.rates[0].idx = rs_sta->last_txrate_idx;
|
||||
}
|
||||
info->control.rates[0].count = 1;
|
||||
|
||||
D_RATE("leave: %d\n", idx);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
|
||||
static ssize_t
|
||||
il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *buff;
|
||||
int desc = 0;
|
||||
int j;
|
||||
ssize_t ret;
|
||||
struct il3945_rs_sta *lq_sta = file->private_data;
|
||||
|
||||
buff = kmalloc(1024, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
desc +=
|
||||
sprintf(buff + desc,
|
||||
"tx packets=%d last rate idx=%d\n"
|
||||
"rate=0x%X flush time %d\n", lq_sta->tx_packets,
|
||||
lq_sta->last_txrate_idx, lq_sta->start_rate,
|
||||
jiffies_to_msecs(lq_sta->flush_time));
|
||||
for (j = 0; j < RATE_COUNT_3945; j++) {
|
||||
desc +=
|
||||
sprintf(buff + desc, "counter=%d success=%d %%=%d\n",
|
||||
lq_sta->win[j].counter,
|
||||
lq_sta->win[j].success_counter,
|
||||
lq_sta->win[j].success_ratio);
|
||||
}
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
|
||||
kfree(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
|
||||
.read = il3945_sta_dbgfs_stats_table_read,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void
|
||||
il3945_add_debugfs(void *il, void *il_sta, struct dentry *dir)
|
||||
{
|
||||
struct il3945_rs_sta *lq_sta = il_sta;
|
||||
|
||||
lq_sta->rs_sta_dbgfs_stats_table_file =
|
||||
debugfs_create_file("rate_stats_table", 0600, dir, lq_sta,
|
||||
&rs_sta_dbgfs_stats_table_ops);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
il3945_remove_debugfs(void *il, void *il_sta)
|
||||
{
|
||||
struct il3945_rs_sta *lq_sta = il_sta;
|
||||
debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialization of rate scaling information is done by driver after
|
||||
* the station is added. Since mac80211 calls this function before a
|
||||
* station is added we ignore it.
|
||||
*/
|
||||
static void
|
||||
il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
struct ieee80211_sta *sta, void *il_sta)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct rate_control_ops rs_ops = {
|
||||
.name = RS_NAME,
|
||||
.tx_status = il3945_rs_tx_status,
|
||||
.get_rate = il3945_rs_get_rate,
|
||||
.rate_init = il3945_rs_rate_init_stub,
|
||||
.alloc = il3945_rs_alloc,
|
||||
.free = il3945_rs_free,
|
||||
.alloc_sta = il3945_rs_alloc_sta,
|
||||
.free_sta = il3945_rs_free_sta,
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
.add_sta_debugfs = il3945_add_debugfs,
|
||||
.remove_sta_debugfs = il3945_remove_debugfs,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
void
|
||||
il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
|
||||
{
|
||||
struct il_priv *il = hw->priv;
|
||||
s32 rssi = 0;
|
||||
unsigned long flags;
|
||||
struct il3945_rs_sta *rs_sta;
|
||||
struct ieee80211_sta *sta;
|
||||
struct il3945_sta_priv *psta;
|
||||
|
||||
D_RATE("enter\n");
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = ieee80211_find_sta(il->vif, il->stations[sta_id].sta.sta.addr);
|
||||
if (!sta) {
|
||||
D_RATE("Unable to find station to initialize rate scaling.\n");
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
psta = (void *)sta->drv_priv;
|
||||
rs_sta = &psta->rs_sta;
|
||||
|
||||
spin_lock_irqsave(&rs_sta->lock, flags);
|
||||
|
||||
rs_sta->tgg = 0;
|
||||
switch (il->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
/* TODO: this always does G, not a regression */
|
||||
if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) {
|
||||
rs_sta->tgg = 1;
|
||||
rs_sta->expected_tpt = il3945_expected_tpt_g_prot;
|
||||
} else
|
||||
rs_sta->expected_tpt = il3945_expected_tpt_g;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
rs_sta->expected_tpt = il3945_expected_tpt_a;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
rssi = il->_3945.last_rx_rssi;
|
||||
if (rssi == 0)
|
||||
rssi = IL_MIN_RSSI_VAL;
|
||||
|
||||
D_RATE("Network RSSI: %d\n", rssi);
|
||||
|
||||
rs_sta->start_rate = il3945_get_rate_idx_by_rssi(rssi, il->band);
|
||||
|
||||
D_RATE("leave: rssi %d assign rate idx: " "%d (plcp 0x%x)\n", rssi,
|
||||
rs_sta->start_rate, il3945_rates[rs_sta->start_rate].plcp);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
int
|
||||
il3945_rate_control_register(void)
|
||||
{
|
||||
return ieee80211_rate_control_register(&rs_ops);
|
||||
}
|
||||
|
||||
void
|
||||
il3945_rate_control_unregister(void)
|
||||
{
|
||||
ieee80211_rate_control_unregister(&rs_ops);
|
||||
}
|
2741
drivers/net/wireless/intel/iwlegacy/3945.c
Arquivo normal
2741
drivers/net/wireless/intel/iwlegacy/3945.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
593
drivers/net/wireless/intel/iwlegacy/3945.h
Arquivo normal
593
drivers/net/wireless/intel/iwlegacy/3945.h
Arquivo normal
@@ -0,0 +1,593 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __il_3945_h__
|
||||
#define __il_3945_h__
|
||||
|
||||
#include <linux/pci.h> /* for struct pci_device_id */
|
||||
#include <linux/kernel.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
|
||||
/* Hardware specific file defines the PCI IDs table for that hardware module */
|
||||
extern const struct pci_device_id il3945_hw_card_ids[];
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern const struct il_ops il3945_ops;
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IL3945_UCODE_API_MAX 2
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IL3945_UCODE_API_MIN 1
|
||||
|
||||
#define IL3945_FW_PRE "iwlwifi-3945-"
|
||||
#define _IL3945_MODULE_FIRMWARE(api) IL3945_FW_PRE #api ".ucode"
|
||||
#define IL3945_MODULE_FIRMWARE(api) _IL3945_MODULE_FIRMWARE(api)
|
||||
|
||||
/* Default noise level to report when noise measurement is not available.
|
||||
* This may be because we're:
|
||||
* 1) Not associated (4965, no beacon stats being sent to driver)
|
||||
* 2) Scanning (noise measurement does not apply to associated channel)
|
||||
* 3) Receiving CCK (3945 delivers noise info only for OFDM frames)
|
||||
* Use default noise value of -127 ... this is below the range of measurable
|
||||
* Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
|
||||
* Also, -127 works better than 0 when averaging frames with/without
|
||||
* noise info (e.g. averaging might be done in app); measured dBm values are
|
||||
* always negative ... using a negative value as the default keeps all
|
||||
* averages within an s8's (used in some apps) range of negative values. */
|
||||
#define IL_NOISE_MEAS_NOT_AVAILABLE (-127)
|
||||
|
||||
/* Module parameters accessible from iwl-*.c */
|
||||
extern struct il_mod_params il3945_mod_params;
|
||||
|
||||
struct il3945_rate_scale_data {
|
||||
u64 data;
|
||||
s32 success_counter;
|
||||
s32 success_ratio;
|
||||
s32 counter;
|
||||
s32 average_tpt;
|
||||
unsigned long stamp;
|
||||
};
|
||||
|
||||
struct il3945_rs_sta {
|
||||
spinlock_t lock;
|
||||
struct il_priv *il;
|
||||
s32 *expected_tpt;
|
||||
unsigned long last_partial_flush;
|
||||
unsigned long last_flush;
|
||||
u32 flush_time;
|
||||
u32 last_tx_packets;
|
||||
u32 tx_packets;
|
||||
u8 tgg;
|
||||
u8 flush_pending;
|
||||
u8 start_rate;
|
||||
struct timer_list rate_scale_flush;
|
||||
struct il3945_rate_scale_data win[RATE_COUNT_3945];
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *rs_sta_dbgfs_stats_table_file;
|
||||
#endif
|
||||
|
||||
/* used to be in sta_info */
|
||||
int last_txrate_idx;
|
||||
};
|
||||
|
||||
/*
|
||||
* The common struct MUST be first because it is shared between
|
||||
* 3945 and 4965!
|
||||
*/
|
||||
struct il3945_sta_priv {
|
||||
struct il_station_priv_common common;
|
||||
struct il3945_rs_sta rs_sta;
|
||||
};
|
||||
|
||||
enum il3945_antenna {
|
||||
IL_ANTENNA_DIVERSITY,
|
||||
IL_ANTENNA_MAIN,
|
||||
IL_ANTENNA_AUX
|
||||
};
|
||||
|
||||
/*
|
||||
* RTS threshold here is total size [2347] minus 4 FCS bytes
|
||||
* Per spec:
|
||||
* a value of 0 means RTS on all data/management packets
|
||||
* a value > max MSDU size means no RTS
|
||||
* else RTS for data/management frames where MPDU is larger
|
||||
* than RTS value.
|
||||
*/
|
||||
#define DEFAULT_RTS_THRESHOLD 2347U
|
||||
#define MIN_RTS_THRESHOLD 0U
|
||||
#define MAX_RTS_THRESHOLD 2347U
|
||||
#define MAX_MSDU_SIZE 2304U
|
||||
#define MAX_MPDU_SIZE 2346U
|
||||
#define DEFAULT_BEACON_INTERVAL 100U
|
||||
#define DEFAULT_SHORT_RETRY_LIMIT 7U
|
||||
#define DEFAULT_LONG_RETRY_LIMIT 4U
|
||||
|
||||
#define IL_TX_FIFO_AC0 0
|
||||
#define IL_TX_FIFO_AC1 1
|
||||
#define IL_TX_FIFO_AC2 2
|
||||
#define IL_TX_FIFO_AC3 3
|
||||
#define IL_TX_FIFO_HCCA_1 5
|
||||
#define IL_TX_FIFO_HCCA_2 6
|
||||
#define IL_TX_FIFO_NONE 7
|
||||
|
||||
#define IEEE80211_DATA_LEN 2304
|
||||
#define IEEE80211_4ADDR_LEN 30
|
||||
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
|
||||
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
|
||||
|
||||
struct il3945_frame {
|
||||
union {
|
||||
struct ieee80211_hdr frame;
|
||||
struct il3945_tx_beacon_cmd beacon;
|
||||
u8 raw[IEEE80211_FRAME_LEN];
|
||||
u8 cmd[360];
|
||||
} u;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
|
||||
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
|
||||
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
|
||||
|
||||
#define IL_SUPPORTED_RATES_IE_LEN 8
|
||||
|
||||
#define SCAN_INTERVAL 100
|
||||
|
||||
#define MAX_TID_COUNT 9
|
||||
|
||||
#define IL_INVALID_RATE 0xFF
|
||||
#define IL_INVALID_VALUE -1
|
||||
|
||||
#define STA_PS_STATUS_WAKE 0
|
||||
#define STA_PS_STATUS_SLEEP 1
|
||||
|
||||
struct il3945_ibss_seq {
|
||||
u8 mac[ETH_ALEN];
|
||||
u16 seq_num;
|
||||
u16 frag_num;
|
||||
unsigned long packet_time;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define IL_RX_HDR(x) ((struct il3945_rx_frame_hdr *)(\
|
||||
x->u.rx_frame.stats.payload + \
|
||||
x->u.rx_frame.stats.phy_count))
|
||||
#define IL_RX_END(x) ((struct il3945_rx_frame_end *)(\
|
||||
IL_RX_HDR(x)->payload + \
|
||||
le16_to_cpu(IL_RX_HDR(x)->len)))
|
||||
#define IL_RX_STATS(x) (&x->u.rx_frame.stats)
|
||||
#define IL_RX_DATA(x) (IL_RX_HDR(x)->payload)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Functions implemented in iwl3945-base.c which are forward declared here
|
||||
* for use by iwl-*.c
|
||||
*
|
||||
*****************************************************************************/
|
||||
int il3945_calc_db_from_ratio(int sig_ratio);
|
||||
void il3945_rx_replenish(void *data);
|
||||
void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq);
|
||||
unsigned int il3945_fill_beacon_frame(struct il_priv *il,
|
||||
struct ieee80211_hdr *hdr, int left);
|
||||
int il3945_dump_nic_event_log(struct il_priv *il, bool full_log, char **buf,
|
||||
bool display);
|
||||
void il3945_dump_nic_error_log(struct il_priv *il);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Functions implemented in iwl-[34]*.c which are forward declared here
|
||||
* for use by iwl3945-base.c
|
||||
*
|
||||
* NOTE: The implementation of these functions are hardware specific
|
||||
* which is why they are in the hardware specific files (vs. iwl-base.c)
|
||||
*
|
||||
* Naming convention --
|
||||
* il3945_ <-- Its part of iwlwifi (should be changed to il3945_)
|
||||
* il3945_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
|
||||
* iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
|
||||
* il3945_bg_ <-- Called from work queue context
|
||||
* il3945_mac_ <-- mac80211 callback
|
||||
*
|
||||
****************************************************************************/
|
||||
void il3945_hw_handler_setup(struct il_priv *il);
|
||||
void il3945_hw_setup_deferred_work(struct il_priv *il);
|
||||
void il3945_hw_cancel_deferred_work(struct il_priv *il);
|
||||
int il3945_hw_rxq_stop(struct il_priv *il);
|
||||
int il3945_hw_set_hw_params(struct il_priv *il);
|
||||
int il3945_hw_nic_init(struct il_priv *il);
|
||||
int il3945_hw_nic_stop_master(struct il_priv *il);
|
||||
void il3945_hw_txq_ctx_free(struct il_priv *il);
|
||||
void il3945_hw_txq_ctx_stop(struct il_priv *il);
|
||||
int il3945_hw_nic_reset(struct il_priv *il);
|
||||
int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
|
||||
dma_addr_t addr, u16 len, u8 reset, u8 pad);
|
||||
void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq);
|
||||
int il3945_hw_get_temperature(struct il_priv *il);
|
||||
int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq);
|
||||
unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il,
|
||||
struct il3945_frame *frame, u8 rate);
|
||||
void il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr, int sta_id);
|
||||
int il3945_hw_reg_send_txpower(struct il_priv *il);
|
||||
int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power);
|
||||
void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb);
|
||||
void il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb);
|
||||
void il3945_disable_events(struct il_priv *il);
|
||||
int il4965_get_temperature(const struct il_priv *il);
|
||||
void il3945_post_associate(struct il_priv *il);
|
||||
void il3945_config_ap(struct il_priv *il);
|
||||
|
||||
int il3945_commit_rxon(struct il_priv *il);
|
||||
|
||||
/**
|
||||
* il3945_hw_find_station - Find station id for a given BSSID
|
||||
* @bssid: MAC address of station ID to find
|
||||
*
|
||||
* NOTE: This should not be hardware specific but the code has
|
||||
* not yet been merged into a single common layer for managing the
|
||||
* station tables.
|
||||
*/
|
||||
u8 il3945_hw_find_station(struct il_priv *il, const u8 *bssid);
|
||||
|
||||
__le32 il3945_get_antenna_flags(const struct il_priv *il);
|
||||
int il3945_init_hw_rate_table(struct il_priv *il);
|
||||
void il3945_reg_txpower_periodic(struct il_priv *il);
|
||||
int il3945_txpower_set_from_eeprom(struct il_priv *il);
|
||||
|
||||
int il3945_rs_next_rate(struct il_priv *il, int rate);
|
||||
|
||||
/* scanning */
|
||||
int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif);
|
||||
void il3945_post_scan(struct il_priv *il);
|
||||
|
||||
/* rates */
|
||||
extern const struct il3945_rate_info il3945_rates[RATE_COUNT_3945];
|
||||
|
||||
/* RSSI to dBm */
|
||||
#define IL39_RSSI_OFFSET 95
|
||||
|
||||
/*
|
||||
* EEPROM related constants, enums, and structures.
|
||||
*/
|
||||
#define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7)
|
||||
|
||||
/*
|
||||
* Mapping of a Tx power level, at factory calibration temperature,
|
||||
* to a radio/DSP gain table idx.
|
||||
* One for each of 5 "sample" power levels in each band.
|
||||
* v_det is measured at the factory, using the 3945's built-in power amplifier
|
||||
* (PA) output voltage detector. This same detector is used during Tx of
|
||||
* long packets in normal operation to provide feedback as to proper output
|
||||
* level.
|
||||
* Data copied from EEPROM.
|
||||
* DO NOT ALTER THIS STRUCTURE!!!
|
||||
*/
|
||||
struct il3945_eeprom_txpower_sample {
|
||||
u8 gain_idx; /* idx into power (gain) setup table ... */
|
||||
s8 power; /* ... for this pwr level for this chnl group */
|
||||
u16 v_det; /* PA output voltage */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Mappings of Tx power levels -> nominal radio/DSP gain table idxes.
|
||||
* One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
|
||||
* Tx power setup code interpolates between the 5 "sample" power levels
|
||||
* to determine the nominal setup for a requested power level.
|
||||
* Data copied from EEPROM.
|
||||
* DO NOT ALTER THIS STRUCTURE!!!
|
||||
*/
|
||||
struct il3945_eeprom_txpower_group {
|
||||
struct il3945_eeprom_txpower_sample samples[5]; /* 5 power levels */
|
||||
s32 a, b, c, d, e; /* coefficients for voltage->power
|
||||
* formula (signed) */
|
||||
s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on
|
||||
* frequency (signed) */
|
||||
s8 saturation_power; /* highest power possible by h/w in this
|
||||
* band */
|
||||
u8 group_channel; /* "representative" channel # in this band */
|
||||
s16 temperature; /* h/w temperature at factory calib this band
|
||||
* (signed) */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Temperature-based Tx-power compensation data, not band-specific.
|
||||
* These coefficients are use to modify a/b/c/d/e coeffs based on
|
||||
* difference between current temperature and factory calib temperature.
|
||||
* Data copied from EEPROM.
|
||||
*/
|
||||
struct il3945_eeprom_temperature_corr {
|
||||
u32 Ta;
|
||||
u32 Tb;
|
||||
u32 Tc;
|
||||
u32 Td;
|
||||
u32 Te;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* EEPROM map
|
||||
*/
|
||||
struct il3945_eeprom {
|
||||
u8 reserved0[16];
|
||||
u16 device_id; /* abs.ofs: 16 */
|
||||
u8 reserved1[2];
|
||||
u16 pmc; /* abs.ofs: 20 */
|
||||
u8 reserved2[20];
|
||||
u8 mac_address[6]; /* abs.ofs: 42 */
|
||||
u8 reserved3[58];
|
||||
u16 board_revision; /* abs.ofs: 106 */
|
||||
u8 reserved4[11];
|
||||
u8 board_pba_number[9]; /* abs.ofs: 119 */
|
||||
u8 reserved5[8];
|
||||
u16 version; /* abs.ofs: 136 */
|
||||
u8 sku_cap; /* abs.ofs: 138 */
|
||||
u8 leds_mode; /* abs.ofs: 139 */
|
||||
u16 oem_mode;
|
||||
u16 wowlan_mode; /* abs.ofs: 142 */
|
||||
u16 leds_time_interval; /* abs.ofs: 144 */
|
||||
u8 leds_off_time; /* abs.ofs: 146 */
|
||||
u8 leds_on_time; /* abs.ofs: 147 */
|
||||
u8 almgor_m_version; /* abs.ofs: 148 */
|
||||
u8 antenna_switch_type; /* abs.ofs: 149 */
|
||||
u8 reserved6[42];
|
||||
u8 sku_id[4]; /* abs.ofs: 192 */
|
||||
|
||||
/*
|
||||
* Per-channel regulatory data.
|
||||
*
|
||||
* Each channel that *might* be supported by 3945 has a fixed location
|
||||
* in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
|
||||
* txpower (MSB).
|
||||
*
|
||||
* Entries immediately below are for 20 MHz channel width.
|
||||
*
|
||||
* 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
|
||||
*/
|
||||
u16 band_1_count; /* abs.ofs: 196 */
|
||||
struct il_eeprom_channel band_1_channels[14]; /* abs.ofs: 198 */
|
||||
|
||||
/*
|
||||
* 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
|
||||
* 5.0 GHz channels 7, 8, 11, 12, 16
|
||||
* (4915-5080MHz) (none of these is ever supported)
|
||||
*/
|
||||
u16 band_2_count; /* abs.ofs: 226 */
|
||||
struct il_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
|
||||
|
||||
/*
|
||||
* 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
|
||||
* (5170-5320MHz)
|
||||
*/
|
||||
u16 band_3_count; /* abs.ofs: 254 */
|
||||
struct il_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
|
||||
|
||||
/*
|
||||
* 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
|
||||
* (5500-5700MHz)
|
||||
*/
|
||||
u16 band_4_count; /* abs.ofs: 280 */
|
||||
struct il_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
|
||||
|
||||
/*
|
||||
* 5.7 GHz channels 145, 149, 153, 157, 161, 165
|
||||
* (5725-5825MHz)
|
||||
*/
|
||||
u16 band_5_count; /* abs.ofs: 304 */
|
||||
struct il_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
|
||||
|
||||
u8 reserved9[194];
|
||||
|
||||
/*
|
||||
* 3945 Txpower calibration data.
|
||||
*/
|
||||
#define IL_NUM_TX_CALIB_GROUPS 5
|
||||
struct il3945_eeprom_txpower_group groups[IL_NUM_TX_CALIB_GROUPS];
|
||||
/* abs.ofs: 512 */
|
||||
struct il3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
|
||||
u8 reserved16[172]; /* fill out to full 1024 byte block */
|
||||
} __packed;
|
||||
|
||||
#define IL3945_EEPROM_IMG_SIZE 1024
|
||||
|
||||
/* End of EEPROM */
|
||||
|
||||
#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */
|
||||
#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */
|
||||
|
||||
/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
|
||||
#define IL39_NUM_QUEUES 5
|
||||
#define IL39_CMD_QUEUE_NUM 4
|
||||
|
||||
#define IL_DEFAULT_TX_RETRY 15
|
||||
|
||||
/*********************************************/
|
||||
|
||||
#define RFD_SIZE 4
|
||||
#define NUM_TFD_CHUNKS 4
|
||||
|
||||
#define TFD_CTL_COUNT_SET(n) (n << 24)
|
||||
#define TFD_CTL_COUNT_GET(ctl) ((ctl >> 24) & 7)
|
||||
#define TFD_CTL_PAD_SET(n) (n << 28)
|
||||
#define TFD_CTL_PAD_GET(ctl) (ctl >> 28)
|
||||
|
||||
/* Sizes and addresses for instruction and data memory (SRAM) in
|
||||
* 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
|
||||
#define IL39_RTC_INST_LOWER_BOUND (0x000000)
|
||||
#define IL39_RTC_INST_UPPER_BOUND (0x014000)
|
||||
|
||||
#define IL39_RTC_DATA_LOWER_BOUND (0x800000)
|
||||
#define IL39_RTC_DATA_UPPER_BOUND (0x808000)
|
||||
|
||||
#define IL39_RTC_INST_SIZE (IL39_RTC_INST_UPPER_BOUND - \
|
||||
IL39_RTC_INST_LOWER_BOUND)
|
||||
#define IL39_RTC_DATA_SIZE (IL39_RTC_DATA_UPPER_BOUND - \
|
||||
IL39_RTC_DATA_LOWER_BOUND)
|
||||
|
||||
#define IL39_MAX_INST_SIZE IL39_RTC_INST_SIZE
|
||||
#define IL39_MAX_DATA_SIZE IL39_RTC_DATA_SIZE
|
||||
|
||||
/* Size of uCode instruction memory in bootstrap state machine */
|
||||
#define IL39_MAX_BSM_SIZE IL39_RTC_INST_SIZE
|
||||
|
||||
static inline int
|
||||
il3945_hw_valid_rtc_data_addr(u32 addr)
|
||||
{
|
||||
return (addr >= IL39_RTC_DATA_LOWER_BOUND &&
|
||||
addr < IL39_RTC_DATA_UPPER_BOUND);
|
||||
}
|
||||
|
||||
/* Base physical address of il3945_shared is provided to FH39_TSSR_CBB_BASE
|
||||
* and &il3945_shared.rx_read_ptr[0] is provided to FH39_RCSR_RPTR_ADDR(0) */
|
||||
struct il3945_shared {
|
||||
__le32 tx_base_ptr[8];
|
||||
} __packed;
|
||||
|
||||
/************************************/
|
||||
/* iwl3945 Flow Handler Definitions */
|
||||
/************************************/
|
||||
|
||||
/**
|
||||
* This I/O area is directly read/writable by driver (e.g. Linux uses writel())
|
||||
* Addresses are offsets from device's PCI hardware base address.
|
||||
*/
|
||||
#define FH39_MEM_LOWER_BOUND (0x0800)
|
||||
#define FH39_MEM_UPPER_BOUND (0x1000)
|
||||
|
||||
#define FH39_CBCC_TBL (FH39_MEM_LOWER_BOUND + 0x140)
|
||||
#define FH39_TFDB_TBL (FH39_MEM_LOWER_BOUND + 0x180)
|
||||
#define FH39_RCSR_TBL (FH39_MEM_LOWER_BOUND + 0x400)
|
||||
#define FH39_RSSR_TBL (FH39_MEM_LOWER_BOUND + 0x4c0)
|
||||
#define FH39_TCSR_TBL (FH39_MEM_LOWER_BOUND + 0x500)
|
||||
#define FH39_TSSR_TBL (FH39_MEM_LOWER_BOUND + 0x680)
|
||||
|
||||
/* TFDB (Transmit Frame Buffer Descriptor) */
|
||||
#define FH39_TFDB(_ch, buf) (FH39_TFDB_TBL + \
|
||||
((_ch) * 2 + (buf)) * 0x28)
|
||||
#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch) (FH39_TFDB_TBL + 0x50 * (_ch))
|
||||
|
||||
/* CBCC channel is [0,2] */
|
||||
#define FH39_CBCC(_ch) (FH39_CBCC_TBL + (_ch) * 0x8)
|
||||
#define FH39_CBCC_CTRL(_ch) (FH39_CBCC(_ch) + 0x00)
|
||||
#define FH39_CBCC_BASE(_ch) (FH39_CBCC(_ch) + 0x04)
|
||||
|
||||
/* RCSR channel is [0,2] */
|
||||
#define FH39_RCSR(_ch) (FH39_RCSR_TBL + (_ch) * 0x40)
|
||||
#define FH39_RCSR_CONFIG(_ch) (FH39_RCSR(_ch) + 0x00)
|
||||
#define FH39_RCSR_RBD_BASE(_ch) (FH39_RCSR(_ch) + 0x04)
|
||||
#define FH39_RCSR_WPTR(_ch) (FH39_RCSR(_ch) + 0x20)
|
||||
#define FH39_RCSR_RPTR_ADDR(_ch) (FH39_RCSR(_ch) + 0x24)
|
||||
|
||||
#define FH39_RSCSR_CHNL0_WPTR (FH39_RCSR_WPTR(0))
|
||||
|
||||
/* RSSR */
|
||||
#define FH39_RSSR_CTRL (FH39_RSSR_TBL + 0x000)
|
||||
#define FH39_RSSR_STATUS (FH39_RSSR_TBL + 0x004)
|
||||
|
||||
/* TCSR */
|
||||
#define FH39_TCSR(_ch) (FH39_TCSR_TBL + (_ch) * 0x20)
|
||||
#define FH39_TCSR_CONFIG(_ch) (FH39_TCSR(_ch) + 0x00)
|
||||
#define FH39_TCSR_CREDIT(_ch) (FH39_TCSR(_ch) + 0x04)
|
||||
#define FH39_TCSR_BUFF_STTS(_ch) (FH39_TCSR(_ch) + 0x08)
|
||||
|
||||
/* TSSR */
|
||||
#define FH39_TSSR_CBB_BASE (FH39_TSSR_TBL + 0x000)
|
||||
#define FH39_TSSR_MSG_CONFIG (FH39_TSSR_TBL + 0x008)
|
||||
#define FH39_TSSR_TX_STATUS (FH39_TSSR_TBL + 0x010)
|
||||
|
||||
/* DBM */
|
||||
|
||||
#define FH39_SRVC_CHNL (6)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20)
|
||||
#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000)
|
||||
|
||||
#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000)
|
||||
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001)
|
||||
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
|
||||
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
|
||||
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
|
||||
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
|
||||
#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
|
||||
|
||||
#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000)
|
||||
|
||||
#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001)
|
||||
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000)
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000)
|
||||
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400)
|
||||
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100)
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080)
|
||||
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020)
|
||||
#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005)
|
||||
|
||||
#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) (BIT(_ch) << 24)
|
||||
#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch) (BIT(_ch) << 16)
|
||||
|
||||
#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
|
||||
(FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
|
||||
FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
|
||||
|
||||
#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
|
||||
|
||||
struct il3945_tfd_tb {
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
} __packed;
|
||||
|
||||
struct il3945_tfd {
|
||||
__le32 control_flags;
|
||||
struct il3945_tfd_tb tbs[4];
|
||||
u8 __pad[28];
|
||||
} __packed;
|
||||
|
||||
#ifdef CONFIG_IWLEGACY_DEBUGFS
|
||||
extern const struct il_debugfs_ops il3945_debugfs_ops;
|
||||
#endif
|
||||
|
||||
#endif
|
934
drivers/net/wireless/intel/iwlegacy/4965-calib.c
Arquivo normal
934
drivers/net/wireless/intel/iwlegacy/4965-calib.c
Arquivo normal
@@ -0,0 +1,934 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "4965.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* INIT calibrations framework
|
||||
*****************************************************************************/
|
||||
|
||||
struct stats_general_data {
|
||||
u32 beacon_silence_rssi_a;
|
||||
u32 beacon_silence_rssi_b;
|
||||
u32 beacon_silence_rssi_c;
|
||||
u32 beacon_energy_a;
|
||||
u32 beacon_energy_b;
|
||||
u32 beacon_energy_c;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* RUNTIME calibrations framework
|
||||
*****************************************************************************/
|
||||
|
||||
/* "false alarms" are signals that our DSP tries to lock onto,
|
||||
* but then determines that they are either noise, or transmissions
|
||||
* from a distant wireless network (also "noise", really) that get
|
||||
* "stepped on" by stronger transmissions within our own network.
|
||||
* This algorithm attempts to set a sensitivity level that is high
|
||||
* enough to receive all of our own network traffic, but not so
|
||||
* high that our DSP gets too busy trying to lock onto non-network
|
||||
* activity/noise. */
|
||||
static int
|
||||
il4965_sens_energy_cck(struct il_priv *il, u32 norm_fa, u32 rx_enable_time,
|
||||
struct stats_general_data *rx_info)
|
||||
{
|
||||
u32 max_nrg_cck = 0;
|
||||
int i = 0;
|
||||
u8 max_silence_rssi = 0;
|
||||
u32 silence_ref = 0;
|
||||
u8 silence_rssi_a = 0;
|
||||
u8 silence_rssi_b = 0;
|
||||
u8 silence_rssi_c = 0;
|
||||
u32 val;
|
||||
|
||||
/* "false_alarms" values below are cross-multiplications to assess the
|
||||
* numbers of false alarms within the measured period of actual Rx
|
||||
* (Rx is off when we're txing), vs the min/max expected false alarms
|
||||
* (some should be expected if rx is sensitive enough) in a
|
||||
* hypothetical listening period of 200 time units (TU), 204.8 msec:
|
||||
*
|
||||
* MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
|
||||
*
|
||||
* */
|
||||
u32 false_alarms = norm_fa * 200 * 1024;
|
||||
u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
|
||||
u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
|
||||
struct il_sensitivity_data *data = NULL;
|
||||
const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
|
||||
|
||||
data = &(il->sensitivity_data);
|
||||
|
||||
data->nrg_auto_corr_silence_diff = 0;
|
||||
|
||||
/* Find max silence rssi among all 3 receivers.
|
||||
* This is background noise, which may include transmissions from other
|
||||
* networks, measured during silence before our network's beacon */
|
||||
silence_rssi_a =
|
||||
(u8) ((rx_info->beacon_silence_rssi_a & ALL_BAND_FILTER) >> 8);
|
||||
silence_rssi_b =
|
||||
(u8) ((rx_info->beacon_silence_rssi_b & ALL_BAND_FILTER) >> 8);
|
||||
silence_rssi_c =
|
||||
(u8) ((rx_info->beacon_silence_rssi_c & ALL_BAND_FILTER) >> 8);
|
||||
|
||||
val = max(silence_rssi_b, silence_rssi_c);
|
||||
max_silence_rssi = max(silence_rssi_a, (u8) val);
|
||||
|
||||
/* Store silence rssi in 20-beacon history table */
|
||||
data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
|
||||
data->nrg_silence_idx++;
|
||||
if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
|
||||
data->nrg_silence_idx = 0;
|
||||
|
||||
/* Find max silence rssi across 20 beacon history */
|
||||
for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
|
||||
val = data->nrg_silence_rssi[i];
|
||||
silence_ref = max(silence_ref, val);
|
||||
}
|
||||
D_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n", silence_rssi_a,
|
||||
silence_rssi_b, silence_rssi_c, silence_ref);
|
||||
|
||||
/* Find max rx energy (min value!) among all 3 receivers,
|
||||
* measured during beacon frame.
|
||||
* Save it in 10-beacon history table. */
|
||||
i = data->nrg_energy_idx;
|
||||
val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
|
||||
data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
|
||||
|
||||
data->nrg_energy_idx++;
|
||||
if (data->nrg_energy_idx >= 10)
|
||||
data->nrg_energy_idx = 0;
|
||||
|
||||
/* Find min rx energy (max value) across 10 beacon history.
|
||||
* This is the minimum signal level that we want to receive well.
|
||||
* Add backoff (margin so we don't miss slightly lower energy frames).
|
||||
* This establishes an upper bound (min value) for energy threshold. */
|
||||
max_nrg_cck = data->nrg_value[0];
|
||||
for (i = 1; i < 10; i++)
|
||||
max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
|
||||
max_nrg_cck += 6;
|
||||
|
||||
D_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
|
||||
rx_info->beacon_energy_a, rx_info->beacon_energy_b,
|
||||
rx_info->beacon_energy_c, max_nrg_cck - 6);
|
||||
|
||||
/* Count number of consecutive beacons with fewer-than-desired
|
||||
* false alarms. */
|
||||
if (false_alarms < min_false_alarms)
|
||||
data->num_in_cck_no_fa++;
|
||||
else
|
||||
data->num_in_cck_no_fa = 0;
|
||||
D_CALIB("consecutive bcns with few false alarms = %u\n",
|
||||
data->num_in_cck_no_fa);
|
||||
|
||||
/* If we got too many false alarms this time, reduce sensitivity */
|
||||
if (false_alarms > max_false_alarms &&
|
||||
data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK) {
|
||||
D_CALIB("norm FA %u > max FA %u\n", false_alarms,
|
||||
max_false_alarms);
|
||||
D_CALIB("... reducing sensitivity\n");
|
||||
data->nrg_curr_state = IL_FA_TOO_MANY;
|
||||
/* Store for "fewer than desired" on later beacon */
|
||||
data->nrg_silence_ref = silence_ref;
|
||||
|
||||
/* increase energy threshold (reduce nrg value)
|
||||
* to decrease sensitivity */
|
||||
data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
|
||||
/* Else if we got fewer than desired, increase sensitivity */
|
||||
} else if (false_alarms < min_false_alarms) {
|
||||
data->nrg_curr_state = IL_FA_TOO_FEW;
|
||||
|
||||
/* Compare silence level with silence level for most recent
|
||||
* healthy number or too many false alarms */
|
||||
data->nrg_auto_corr_silence_diff =
|
||||
(s32) data->nrg_silence_ref - (s32) silence_ref;
|
||||
|
||||
D_CALIB("norm FA %u < min FA %u, silence diff %d\n",
|
||||
false_alarms, min_false_alarms,
|
||||
data->nrg_auto_corr_silence_diff);
|
||||
|
||||
/* Increase value to increase sensitivity, but only if:
|
||||
* 1a) previous beacon did *not* have *too many* false alarms
|
||||
* 1b) AND there's a significant difference in Rx levels
|
||||
* from a previous beacon with too many, or healthy # FAs
|
||||
* OR 2) We've seen a lot of beacons (100) with too few
|
||||
* false alarms */
|
||||
if (data->nrg_prev_state != IL_FA_TOO_MANY &&
|
||||
(data->nrg_auto_corr_silence_diff > NRG_DIFF ||
|
||||
data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA)) {
|
||||
|
||||
D_CALIB("... increasing sensitivity\n");
|
||||
/* Increase nrg value to increase sensitivity */
|
||||
val = data->nrg_th_cck + NRG_STEP_CCK;
|
||||
data->nrg_th_cck = min((u32) ranges->min_nrg_cck, val);
|
||||
} else {
|
||||
D_CALIB("... but not changing sensitivity\n");
|
||||
}
|
||||
|
||||
/* Else we got a healthy number of false alarms, keep status quo */
|
||||
} else {
|
||||
D_CALIB(" FA in safe zone\n");
|
||||
data->nrg_curr_state = IL_FA_GOOD_RANGE;
|
||||
|
||||
/* Store for use in "fewer than desired" with later beacon */
|
||||
data->nrg_silence_ref = silence_ref;
|
||||
|
||||
/* If previous beacon had too many false alarms,
|
||||
* give it some extra margin by reducing sensitivity again
|
||||
* (but don't go below measured energy of desired Rx) */
|
||||
if (IL_FA_TOO_MANY == data->nrg_prev_state) {
|
||||
D_CALIB("... increasing margin\n");
|
||||
if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
|
||||
data->nrg_th_cck -= NRG_MARGIN;
|
||||
else
|
||||
data->nrg_th_cck = max_nrg_cck;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the energy threshold does not go above the measured
|
||||
* energy of the desired Rx signals (reduced by backoff margin),
|
||||
* or else we might start missing Rx frames.
|
||||
* Lower value is higher energy, so we use max()!
|
||||
*/
|
||||
data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
|
||||
D_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck);
|
||||
|
||||
data->nrg_prev_state = data->nrg_curr_state;
|
||||
|
||||
/* Auto-correlation CCK algorithm */
|
||||
if (false_alarms > min_false_alarms) {
|
||||
|
||||
/* increase auto_corr values to decrease sensitivity
|
||||
* so the DSP won't be disturbed by the noise
|
||||
*/
|
||||
if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
|
||||
data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
|
||||
else {
|
||||
val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
|
||||
data->auto_corr_cck =
|
||||
min((u32) ranges->auto_corr_max_cck, val);
|
||||
}
|
||||
val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
|
||||
data->auto_corr_cck_mrc =
|
||||
min((u32) ranges->auto_corr_max_cck_mrc, val);
|
||||
} else if (false_alarms < min_false_alarms &&
|
||||
(data->nrg_auto_corr_silence_diff > NRG_DIFF ||
|
||||
data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA)) {
|
||||
|
||||
/* Decrease auto_corr values to increase sensitivity */
|
||||
val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
|
||||
data->auto_corr_cck = max((u32) ranges->auto_corr_min_cck, val);
|
||||
val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
|
||||
data->auto_corr_cck_mrc =
|
||||
max((u32) ranges->auto_corr_min_cck_mrc, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
il4965_sens_auto_corr_ofdm(struct il_priv *il, u32 norm_fa, u32 rx_enable_time)
|
||||
{
|
||||
u32 val;
|
||||
u32 false_alarms = norm_fa * 200 * 1024;
|
||||
u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
|
||||
u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
|
||||
struct il_sensitivity_data *data = NULL;
|
||||
const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
|
||||
|
||||
data = &(il->sensitivity_data);
|
||||
|
||||
/* If we got too many false alarms this time, reduce sensitivity */
|
||||
if (false_alarms > max_false_alarms) {
|
||||
|
||||
D_CALIB("norm FA %u > max FA %u)\n", false_alarms,
|
||||
max_false_alarms);
|
||||
|
||||
val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm =
|
||||
min((u32) ranges->auto_corr_max_ofdm, val);
|
||||
|
||||
val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_mrc =
|
||||
min((u32) ranges->auto_corr_max_ofdm_mrc, val);
|
||||
|
||||
val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_x1 =
|
||||
min((u32) ranges->auto_corr_max_ofdm_x1, val);
|
||||
|
||||
val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_mrc_x1 =
|
||||
min((u32) ranges->auto_corr_max_ofdm_mrc_x1, val);
|
||||
}
|
||||
|
||||
/* Else if we got fewer than desired, increase sensitivity */
|
||||
else if (false_alarms < min_false_alarms) {
|
||||
|
||||
D_CALIB("norm FA %u < min FA %u\n", false_alarms,
|
||||
min_false_alarms);
|
||||
|
||||
val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm =
|
||||
max((u32) ranges->auto_corr_min_ofdm, val);
|
||||
|
||||
val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_mrc =
|
||||
max((u32) ranges->auto_corr_min_ofdm_mrc, val);
|
||||
|
||||
val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_x1 =
|
||||
max((u32) ranges->auto_corr_min_ofdm_x1, val);
|
||||
|
||||
val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
|
||||
data->auto_corr_ofdm_mrc_x1 =
|
||||
max((u32) ranges->auto_corr_min_ofdm_mrc_x1, val);
|
||||
} else {
|
||||
D_CALIB("min FA %u < norm FA %u < max FA %u OK\n",
|
||||
min_false_alarms, false_alarms, max_false_alarms);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
il4965_prepare_legacy_sensitivity_tbl(struct il_priv *il,
|
||||
struct il_sensitivity_data *data,
|
||||
__le16 *tbl)
|
||||
{
|
||||
tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_ofdm);
|
||||
tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_ofdm_mrc);
|
||||
tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_ofdm_x1);
|
||||
tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_ofdm_mrc_x1);
|
||||
|
||||
tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_cck);
|
||||
tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
|
||||
cpu_to_le16((u16) data->auto_corr_cck_mrc);
|
||||
|
||||
tbl[HD_MIN_ENERGY_CCK_DET_IDX] = cpu_to_le16((u16) data->nrg_th_cck);
|
||||
tbl[HD_MIN_ENERGY_OFDM_DET_IDX] = cpu_to_le16((u16) data->nrg_th_ofdm);
|
||||
|
||||
tbl[HD_BARKER_CORR_TH_ADD_MIN_IDX] =
|
||||
cpu_to_le16(data->barker_corr_th_min);
|
||||
tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_IDX] =
|
||||
cpu_to_le16(data->barker_corr_th_min_mrc);
|
||||
tbl[HD_OFDM_ENERGY_TH_IN_IDX] = cpu_to_le16(data->nrg_th_cca);
|
||||
|
||||
D_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
|
||||
data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
|
||||
data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
|
||||
data->nrg_th_ofdm);
|
||||
|
||||
D_CALIB("cck: ac %u mrc %u thresh %u\n", data->auto_corr_cck,
|
||||
data->auto_corr_cck_mrc, data->nrg_th_cck);
|
||||
}
|
||||
|
||||
/* Prepare a C_SENSITIVITY, send to uCode if values have changed */
|
||||
static int
|
||||
il4965_sensitivity_write(struct il_priv *il)
|
||||
{
|
||||
struct il_sensitivity_cmd cmd;
|
||||
struct il_sensitivity_data *data = NULL;
|
||||
struct il_host_cmd cmd_out = {
|
||||
.id = C_SENSITIVITY,
|
||||
.len = sizeof(struct il_sensitivity_cmd),
|
||||
.flags = CMD_ASYNC,
|
||||
.data = &cmd,
|
||||
};
|
||||
|
||||
data = &(il->sensitivity_data);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
il4965_prepare_legacy_sensitivity_tbl(il, data, &cmd.table[0]);
|
||||
|
||||
/* Update uCode's "work" table, and copy it to DSP */
|
||||
cmd.control = C_SENSITIVITY_CONTROL_WORK_TBL;
|
||||
|
||||
/* Don't send command to uCode if nothing has changed */
|
||||
if (!memcmp
|
||||
(&cmd.table[0], &(il->sensitivity_tbl[0]),
|
||||
sizeof(u16) * HD_TBL_SIZE)) {
|
||||
D_CALIB("No change in C_SENSITIVITY\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy table for comparison next time */
|
||||
memcpy(&(il->sensitivity_tbl[0]), &(cmd.table[0]),
|
||||
sizeof(u16) * HD_TBL_SIZE);
|
||||
|
||||
return il_send_cmd(il, &cmd_out);
|
||||
}
|
||||
|
||||
void
|
||||
il4965_init_sensitivity(struct il_priv *il)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct il_sensitivity_data *data = NULL;
|
||||
const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
|
||||
|
||||
if (il->disable_sens_cal)
|
||||
return;
|
||||
|
||||
D_CALIB("Start il4965_init_sensitivity\n");
|
||||
|
||||
/* Clear driver's sensitivity algo data */
|
||||
data = &(il->sensitivity_data);
|
||||
|
||||
if (ranges == NULL)
|
||||
return;
|
||||
|
||||
memset(data, 0, sizeof(struct il_sensitivity_data));
|
||||
|
||||
data->num_in_cck_no_fa = 0;
|
||||
data->nrg_curr_state = IL_FA_TOO_MANY;
|
||||
data->nrg_prev_state = IL_FA_TOO_MANY;
|
||||
data->nrg_silence_ref = 0;
|
||||
data->nrg_silence_idx = 0;
|
||||
data->nrg_energy_idx = 0;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
data->nrg_value[i] = 0;
|
||||
|
||||
for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
|
||||
data->nrg_silence_rssi[i] = 0;
|
||||
|
||||
data->auto_corr_ofdm = ranges->auto_corr_min_ofdm;
|
||||
data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
|
||||
data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1;
|
||||
data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
|
||||
data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
|
||||
data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
|
||||
data->nrg_th_cck = ranges->nrg_th_cck;
|
||||
data->nrg_th_ofdm = ranges->nrg_th_ofdm;
|
||||
data->barker_corr_th_min = ranges->barker_corr_th_min;
|
||||
data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
|
||||
data->nrg_th_cca = ranges->nrg_th_cca;
|
||||
|
||||
data->last_bad_plcp_cnt_ofdm = 0;
|
||||
data->last_fa_cnt_ofdm = 0;
|
||||
data->last_bad_plcp_cnt_cck = 0;
|
||||
data->last_fa_cnt_cck = 0;
|
||||
|
||||
ret |= il4965_sensitivity_write(il);
|
||||
D_CALIB("<<return 0x%X\n", ret);
|
||||
}
|
||||
|
||||
void
|
||||
il4965_sensitivity_calibration(struct il_priv *il, void *resp)
|
||||
{
|
||||
u32 rx_enable_time;
|
||||
u32 fa_cck;
|
||||
u32 fa_ofdm;
|
||||
u32 bad_plcp_cck;
|
||||
u32 bad_plcp_ofdm;
|
||||
u32 norm_fa_ofdm;
|
||||
u32 norm_fa_cck;
|
||||
struct il_sensitivity_data *data = NULL;
|
||||
struct stats_rx_non_phy *rx_info;
|
||||
struct stats_rx_phy *ofdm, *cck;
|
||||
unsigned long flags;
|
||||
struct stats_general_data statis;
|
||||
|
||||
if (il->disable_sens_cal)
|
||||
return;
|
||||
|
||||
data = &(il->sensitivity_data);
|
||||
|
||||
if (!il_is_any_associated(il)) {
|
||||
D_CALIB("<< - not associated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&il->lock, flags);
|
||||
|
||||
rx_info = &(((struct il_notif_stats *)resp)->rx.general);
|
||||
ofdm = &(((struct il_notif_stats *)resp)->rx.ofdm);
|
||||
cck = &(((struct il_notif_stats *)resp)->rx.cck);
|
||||
|
||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||
D_CALIB("<< invalid data.\n");
|
||||
spin_unlock_irqrestore(&il->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extract Statistics: */
|
||||
rx_enable_time = le32_to_cpu(rx_info->channel_load);
|
||||
fa_cck = le32_to_cpu(cck->false_alarm_cnt);
|
||||
fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt);
|
||||
bad_plcp_cck = le32_to_cpu(cck->plcp_err);
|
||||
bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err);
|
||||
|
||||
statis.beacon_silence_rssi_a =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_a);
|
||||
statis.beacon_silence_rssi_b =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_b);
|
||||
statis.beacon_silence_rssi_c =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_c);
|
||||
statis.beacon_energy_a = le32_to_cpu(rx_info->beacon_energy_a);
|
||||
statis.beacon_energy_b = le32_to_cpu(rx_info->beacon_energy_b);
|
||||
statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c);
|
||||
|
||||
spin_unlock_irqrestore(&il->lock, flags);
|
||||
|
||||
D_CALIB("rx_enable_time = %u usecs\n", rx_enable_time);
|
||||
|
||||
if (!rx_enable_time) {
|
||||
D_CALIB("<< RX Enable Time == 0!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* These stats increase monotonically, and do not reset
|
||||
* at each beacon. Calculate difference from last value, or just
|
||||
* use the new stats value if it has reset or wrapped around. */
|
||||
if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
|
||||
data->last_bad_plcp_cnt_cck = bad_plcp_cck;
|
||||
else {
|
||||
bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
|
||||
data->last_bad_plcp_cnt_cck += bad_plcp_cck;
|
||||
}
|
||||
|
||||
if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
|
||||
data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
|
||||
else {
|
||||
bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
|
||||
data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
|
||||
}
|
||||
|
||||
if (data->last_fa_cnt_ofdm > fa_ofdm)
|
||||
data->last_fa_cnt_ofdm = fa_ofdm;
|
||||
else {
|
||||
fa_ofdm -= data->last_fa_cnt_ofdm;
|
||||
data->last_fa_cnt_ofdm += fa_ofdm;
|
||||
}
|
||||
|
||||
if (data->last_fa_cnt_cck > fa_cck)
|
||||
data->last_fa_cnt_cck = fa_cck;
|
||||
else {
|
||||
fa_cck -= data->last_fa_cnt_cck;
|
||||
data->last_fa_cnt_cck += fa_cck;
|
||||
}
|
||||
|
||||
/* Total aborted signal locks */
|
||||
norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
|
||||
norm_fa_cck = fa_cck + bad_plcp_cck;
|
||||
|
||||
D_CALIB("cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck,
|
||||
bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
|
||||
|
||||
il4965_sens_auto_corr_ofdm(il, norm_fa_ofdm, rx_enable_time);
|
||||
il4965_sens_energy_cck(il, norm_fa_cck, rx_enable_time, &statis);
|
||||
|
||||
il4965_sensitivity_write(il);
|
||||
}
|
||||
|
||||
static inline u8
|
||||
il4965_find_first_chain(u8 mask)
|
||||
{
|
||||
if (mask & ANT_A)
|
||||
return CHAIN_A;
|
||||
if (mask & ANT_B)
|
||||
return CHAIN_B;
|
||||
return CHAIN_C;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run disconnected antenna algorithm to find out which antennas are
|
||||
* disconnected.
|
||||
*/
|
||||
static void
|
||||
il4965_find_disconn_antenna(struct il_priv *il, u32 * average_sig,
|
||||
struct il_chain_noise_data *data)
|
||||
{
|
||||
u32 active_chains = 0;
|
||||
u32 max_average_sig;
|
||||
u16 max_average_sig_antenna_i;
|
||||
u8 num_tx_chains;
|
||||
u8 first_chain;
|
||||
u16 i = 0;
|
||||
|
||||
average_sig[0] =
|
||||
data->chain_signal_a /
|
||||
il->cfg->chain_noise_num_beacons;
|
||||
average_sig[1] =
|
||||
data->chain_signal_b /
|
||||
il->cfg->chain_noise_num_beacons;
|
||||
average_sig[2] =
|
||||
data->chain_signal_c /
|
||||
il->cfg->chain_noise_num_beacons;
|
||||
|
||||
if (average_sig[0] >= average_sig[1]) {
|
||||
max_average_sig = average_sig[0];
|
||||
max_average_sig_antenna_i = 0;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
} else {
|
||||
max_average_sig = average_sig[1];
|
||||
max_average_sig_antenna_i = 1;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
if (average_sig[2] >= max_average_sig) {
|
||||
max_average_sig = average_sig[2];
|
||||
max_average_sig_antenna_i = 2;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
D_CALIB("average_sig: a %d b %d c %d\n", average_sig[0], average_sig[1],
|
||||
average_sig[2]);
|
||||
D_CALIB("max_average_sig = %d, antenna %d\n", max_average_sig,
|
||||
max_average_sig_antenna_i);
|
||||
|
||||
/* Compare signal strengths for all 3 receivers. */
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (i != max_average_sig_antenna_i) {
|
||||
s32 rssi_delta = (max_average_sig - average_sig[i]);
|
||||
|
||||
/* If signal is very weak, compared with
|
||||
* strongest, mark it as disconnected. */
|
||||
if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
|
||||
data->disconn_array[i] = 1;
|
||||
else
|
||||
active_chains |= (1 << i);
|
||||
D_CALIB("i = %d rssiDelta = %d "
|
||||
"disconn_array[i] = %d\n", i, rssi_delta,
|
||||
data->disconn_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The above algorithm sometimes fails when the ucode
|
||||
* reports 0 for all chains. It's not clear why that
|
||||
* happens to start with, but it is then causing trouble
|
||||
* because this can make us enable more chains than the
|
||||
* hardware really has.
|
||||
*
|
||||
* To be safe, simply mask out any chains that we know
|
||||
* are not on the device.
|
||||
*/
|
||||
active_chains &= il->hw_params.valid_rx_ant;
|
||||
|
||||
num_tx_chains = 0;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
/* loops on all the bits of
|
||||
* il->hw_setting.valid_tx_ant */
|
||||
u8 ant_msk = (1 << i);
|
||||
if (!(il->hw_params.valid_tx_ant & ant_msk))
|
||||
continue;
|
||||
|
||||
num_tx_chains++;
|
||||
if (data->disconn_array[i] == 0)
|
||||
/* there is a Tx antenna connected */
|
||||
break;
|
||||
if (num_tx_chains == il->hw_params.tx_chains_num &&
|
||||
data->disconn_array[i]) {
|
||||
/*
|
||||
* If all chains are disconnected
|
||||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
il4965_find_first_chain(il->cfg->valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
D_CALIB("All Tx chains are disconnected"
|
||||
"- declare %d as connected\n", first_chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_chains != il->hw_params.valid_rx_ant &&
|
||||
active_chains != il->chain_noise_data.active_chains)
|
||||
D_CALIB("Detected that not all antennas are connected! "
|
||||
"Connected: %#x, valid: %#x.\n", active_chains,
|
||||
il->hw_params.valid_rx_ant);
|
||||
|
||||
/* Save for use within RXON, TX, SCAN commands, etc. */
|
||||
data->active_chains = active_chains;
|
||||
D_CALIB("active_chains (bitwise) = 0x%x\n", active_chains);
|
||||
}
|
||||
|
||||
static void
|
||||
il4965_gain_computation(struct il_priv *il, u32 * average_noise,
|
||||
u16 min_average_noise_antenna_i, u32 min_average_noise,
|
||||
u8 default_chain)
|
||||
{
|
||||
int i, ret;
|
||||
struct il_chain_noise_data *data = &il->chain_noise_data;
|
||||
|
||||
data->delta_gain_code[min_average_noise_antenna_i] = 0;
|
||||
|
||||
for (i = default_chain; i < NUM_RX_CHAINS; i++) {
|
||||
s32 delta_g = 0;
|
||||
|
||||
if (!data->disconn_array[i] &&
|
||||
data->delta_gain_code[i] ==
|
||||
CHAIN_NOISE_DELTA_GAIN_INIT_VAL) {
|
||||
delta_g = average_noise[i] - min_average_noise;
|
||||
data->delta_gain_code[i] = (u8) ((delta_g * 10) / 15);
|
||||
data->delta_gain_code[i] =
|
||||
min(data->delta_gain_code[i],
|
||||
(u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
|
||||
|
||||
data->delta_gain_code[i] =
|
||||
(data->delta_gain_code[i] | (1 << 2));
|
||||
} else {
|
||||
data->delta_gain_code[i] = 0;
|
||||
}
|
||||
}
|
||||
D_CALIB("delta_gain_codes: a %d b %d c %d\n", data->delta_gain_code[0],
|
||||
data->delta_gain_code[1], data->delta_gain_code[2]);
|
||||
|
||||
/* Differential gain gets sent to uCode only once */
|
||||
if (!data->radio_write) {
|
||||
struct il_calib_diff_gain_cmd cmd;
|
||||
data->radio_write = 1;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.op_code = IL_PHY_CALIBRATE_DIFF_GAIN_CMD;
|
||||
cmd.diff_gain_a = data->delta_gain_code[0];
|
||||
cmd.diff_gain_b = data->delta_gain_code[1];
|
||||
cmd.diff_gain_c = data->delta_gain_code[2];
|
||||
ret = il_send_cmd_pdu(il, C_PHY_CALIBRATION, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
D_CALIB("fail sending cmd " "C_PHY_CALIBRATION\n");
|
||||
|
||||
/* TODO we might want recalculate
|
||||
* rx_chain in rxon cmd */
|
||||
|
||||
/* Mark so we run this algo only once! */
|
||||
data->state = IL_CHAIN_NOISE_CALIBRATED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate 16 beacons of signal and noise stats for each of
|
||||
* 3 receivers/antennas/rx-chains, then figure out:
|
||||
* 1) Which antennas are connected.
|
||||
* 2) Differential rx gain settings to balance the 3 receivers.
|
||||
*/
|
||||
void
|
||||
il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp)
|
||||
{
|
||||
struct il_chain_noise_data *data = NULL;
|
||||
|
||||
u32 chain_noise_a;
|
||||
u32 chain_noise_b;
|
||||
u32 chain_noise_c;
|
||||
u32 chain_sig_a;
|
||||
u32 chain_sig_b;
|
||||
u32 chain_sig_c;
|
||||
u32 average_sig[NUM_RX_CHAINS] = { INITIALIZATION_VALUE };
|
||||
u32 average_noise[NUM_RX_CHAINS] = { INITIALIZATION_VALUE };
|
||||
u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
|
||||
u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
|
||||
u16 i = 0;
|
||||
u16 rxon_chnum = INITIALIZATION_VALUE;
|
||||
u16 stat_chnum = INITIALIZATION_VALUE;
|
||||
u8 rxon_band24;
|
||||
u8 stat_band24;
|
||||
unsigned long flags;
|
||||
struct stats_rx_non_phy *rx_info;
|
||||
|
||||
if (il->disable_chain_noise_cal)
|
||||
return;
|
||||
|
||||
data = &(il->chain_noise_data);
|
||||
|
||||
/*
|
||||
* Accumulate just the first "chain_noise_num_beacons" after
|
||||
* the first association, then we're done forever.
|
||||
*/
|
||||
if (data->state != IL_CHAIN_NOISE_ACCUMULATE) {
|
||||
if (data->state == IL_CHAIN_NOISE_ALIVE)
|
||||
D_CALIB("Wait for noise calib reset\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&il->lock, flags);
|
||||
|
||||
rx_info = &(((struct il_notif_stats *)stat_resp)->rx.general);
|
||||
|
||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||
D_CALIB(" << Interference data unavailable\n");
|
||||
spin_unlock_irqrestore(&il->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
rxon_band24 = !!(il->staging.flags & RXON_FLG_BAND_24G_MSK);
|
||||
rxon_chnum = le16_to_cpu(il->staging.channel);
|
||||
|
||||
stat_band24 =
|
||||
!!(((struct il_notif_stats *)stat_resp)->
|
||||
flag & STATS_REPLY_FLG_BAND_24G_MSK);
|
||||
stat_chnum =
|
||||
le32_to_cpu(((struct il_notif_stats *)stat_resp)->flag) >> 16;
|
||||
|
||||
/* Make sure we accumulate data for just the associated channel
|
||||
* (even if scanning). */
|
||||
if (rxon_chnum != stat_chnum || rxon_band24 != stat_band24) {
|
||||
D_CALIB("Stats not from chan=%d, band24=%d\n", rxon_chnum,
|
||||
rxon_band24);
|
||||
spin_unlock_irqrestore(&il->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate beacon stats values across
|
||||
* "chain_noise_num_beacons"
|
||||
*/
|
||||
chain_noise_a =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
|
||||
chain_noise_b =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
|
||||
chain_noise_c =
|
||||
le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
|
||||
|
||||
chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
|
||||
chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
|
||||
chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
|
||||
|
||||
spin_unlock_irqrestore(&il->lock, flags);
|
||||
|
||||
data->beacon_count++;
|
||||
|
||||
data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
|
||||
data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
|
||||
data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
|
||||
|
||||
data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
|
||||
data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
|
||||
data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
|
||||
|
||||
D_CALIB("chan=%d, band24=%d, beacon=%d\n", rxon_chnum, rxon_band24,
|
||||
data->beacon_count);
|
||||
D_CALIB("chain_sig: a %d b %d c %d\n", chain_sig_a, chain_sig_b,
|
||||
chain_sig_c);
|
||||
D_CALIB("chain_noise: a %d b %d c %d\n", chain_noise_a, chain_noise_b,
|
||||
chain_noise_c);
|
||||
|
||||
/* If this is the "chain_noise_num_beacons", determine:
|
||||
* 1) Disconnected antennas (using signal strengths)
|
||||
* 2) Differential gain (using silence noise) to balance receivers */
|
||||
if (data->beacon_count != il->cfg->chain_noise_num_beacons)
|
||||
return;
|
||||
|
||||
/* Analyze signal for disconnected antenna */
|
||||
il4965_find_disconn_antenna(il, average_sig, data);
|
||||
|
||||
/* Analyze noise for rx balance */
|
||||
average_noise[0] =
|
||||
data->chain_noise_a / il->cfg->chain_noise_num_beacons;
|
||||
average_noise[1] =
|
||||
data->chain_noise_b / il->cfg->chain_noise_num_beacons;
|
||||
average_noise[2] =
|
||||
data->chain_noise_c / il->cfg->chain_noise_num_beacons;
|
||||
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (!data->disconn_array[i] &&
|
||||
average_noise[i] <= min_average_noise) {
|
||||
/* This means that chain i is active and has
|
||||
* lower noise values so far: */
|
||||
min_average_noise = average_noise[i];
|
||||
min_average_noise_antenna_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
D_CALIB("average_noise: a %d b %d c %d\n", average_noise[0],
|
||||
average_noise[1], average_noise[2]);
|
||||
|
||||
D_CALIB("min_average_noise = %d, antenna %d\n", min_average_noise,
|
||||
min_average_noise_antenna_i);
|
||||
|
||||
il4965_gain_computation(il, average_noise, min_average_noise_antenna_i,
|
||||
min_average_noise,
|
||||
il4965_find_first_chain(il->cfg->valid_rx_ant));
|
||||
|
||||
/* Some power changes may have been made during the calibration.
|
||||
* Update and commit the RXON
|
||||
*/
|
||||
if (il->ops->update_chain_flags)
|
||||
il->ops->update_chain_flags(il);
|
||||
|
||||
data->state = IL_CHAIN_NOISE_DONE;
|
||||
il_power_update_mode(il, false);
|
||||
}
|
||||
|
||||
void
|
||||
il4965_reset_run_time_calib(struct il_priv *il)
|
||||
{
|
||||
int i;
|
||||
memset(&(il->sensitivity_data), 0, sizeof(struct il_sensitivity_data));
|
||||
memset(&(il->chain_noise_data), 0, sizeof(struct il_chain_noise_data));
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++)
|
||||
il->chain_noise_data.delta_gain_code[i] =
|
||||
CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
|
||||
|
||||
/* Ask for stats now, the uCode will send notification
|
||||
* periodically after association */
|
||||
il_send_stats_request(il, CMD_ASYNC, true);
|
||||
}
|
752
drivers/net/wireless/intel/iwlegacy/4965-debug.c
Arquivo normal
752
drivers/net/wireless/intel/iwlegacy/4965-debug.c
Arquivo normal
@@ -0,0 +1,752 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
#include "common.h"
|
||||
#include "4965.h"
|
||||
|
||||
static const char *fmt_value = " %-30s %10u\n";
|
||||
static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
|
||||
static const char *fmt_header =
|
||||
"%-32s current cumulative delta max\n";
|
||||
|
||||
static int
|
||||
il4965_stats_flag(struct il_priv *il, char *buf, int bufsz)
|
||||
{
|
||||
int p = 0;
|
||||
u32 flag;
|
||||
|
||||
flag = le32_to_cpu(il->_4965.stats.flag);
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
|
||||
if (flag & UCODE_STATS_CLEAR_MSK)
|
||||
p += scnprintf(buf + p, bufsz - p,
|
||||
"\tStatistics have been cleared\n");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
|
||||
(flag & UCODE_STATS_FREQUENCY_MSK) ? "2.4 GHz" :
|
||||
"5.2 GHz");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
|
||||
(flag & UCODE_STATS_NARROW_BAND_MSK) ? "enabled" :
|
||||
"disabled");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz =
|
||||
sizeof(struct stats_rx_phy) * 40 +
|
||||
sizeof(struct stats_rx_non_phy) * 40 +
|
||||
sizeof(struct stats_rx_ht_phy) * 40 + 400;
|
||||
ssize_t ret;
|
||||
struct stats_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
|
||||
struct stats_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
|
||||
struct stats_rx_non_phy *general, *accum_general;
|
||||
struct stats_rx_non_phy *delta_general, *max_general;
|
||||
struct stats_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* the statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
ofdm = &il->_4965.stats.rx.ofdm;
|
||||
cck = &il->_4965.stats.rx.cck;
|
||||
general = &il->_4965.stats.rx.general;
|
||||
ht = &il->_4965.stats.rx.ofdm_ht;
|
||||
accum_ofdm = &il->_4965.accum_stats.rx.ofdm;
|
||||
accum_cck = &il->_4965.accum_stats.rx.cck;
|
||||
accum_general = &il->_4965.accum_stats.rx.general;
|
||||
accum_ht = &il->_4965.accum_stats.rx.ofdm_ht;
|
||||
delta_ofdm = &il->_4965.delta_stats.rx.ofdm;
|
||||
delta_cck = &il->_4965.delta_stats.rx.cck;
|
||||
delta_general = &il->_4965.delta_stats.rx.general;
|
||||
delta_ht = &il->_4965.delta_stats.rx.ofdm_ht;
|
||||
max_ofdm = &il->_4965.max_delta.rx.ofdm;
|
||||
max_cck = &il->_4965.max_delta.rx.cck;
|
||||
max_general = &il->_4965.max_delta.rx.general;
|
||||
max_ht = &il->_4965.max_delta.rx.ofdm_ht;
|
||||
|
||||
pos += il4965_stats_flag(il, buf, bufsz);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_header,
|
||||
"Statistics_Rx - OFDM:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "ina_cnt:",
|
||||
le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt,
|
||||
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_cnt:",
|
||||
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
|
||||
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
|
||||
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
|
||||
delta_ofdm->plcp_err, max_ofdm->plcp_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
|
||||
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
|
||||
delta_ofdm->crc32_err, max_ofdm->crc32_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
|
||||
le32_to_cpu(ofdm->overrun_err), accum_ofdm->overrun_err,
|
||||
delta_ofdm->overrun_err, max_ofdm->overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
|
||||
le32_to_cpu(ofdm->early_overrun_err),
|
||||
accum_ofdm->early_overrun_err,
|
||||
delta_ofdm->early_overrun_err,
|
||||
max_ofdm->early_overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
|
||||
le32_to_cpu(ofdm->crc32_good), accum_ofdm->crc32_good,
|
||||
delta_ofdm->crc32_good, max_ofdm->crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "false_alarm_cnt:",
|
||||
le32_to_cpu(ofdm->false_alarm_cnt),
|
||||
accum_ofdm->false_alarm_cnt, delta_ofdm->false_alarm_cnt,
|
||||
max_ofdm->false_alarm_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_sync_err_cnt:",
|
||||
le32_to_cpu(ofdm->fina_sync_err_cnt),
|
||||
accum_ofdm->fina_sync_err_cnt,
|
||||
delta_ofdm->fina_sync_err_cnt,
|
||||
max_ofdm->fina_sync_err_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sfd_timeout:",
|
||||
le32_to_cpu(ofdm->sfd_timeout), accum_ofdm->sfd_timeout,
|
||||
delta_ofdm->sfd_timeout, max_ofdm->sfd_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_timeout:",
|
||||
le32_to_cpu(ofdm->fina_timeout), accum_ofdm->fina_timeout,
|
||||
delta_ofdm->fina_timeout, max_ofdm->fina_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "unresponded_rts:",
|
||||
le32_to_cpu(ofdm->unresponded_rts),
|
||||
accum_ofdm->unresponded_rts, delta_ofdm->unresponded_rts,
|
||||
max_ofdm->unresponded_rts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
|
||||
accum_ofdm->rxe_frame_limit_overrun,
|
||||
delta_ofdm->rxe_frame_limit_overrun,
|
||||
max_ofdm->rxe_frame_limit_overrun);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ack_cnt:",
|
||||
le32_to_cpu(ofdm->sent_ack_cnt), accum_ofdm->sent_ack_cnt,
|
||||
delta_ofdm->sent_ack_cnt, max_ofdm->sent_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_cts_cnt:",
|
||||
le32_to_cpu(ofdm->sent_cts_cnt), accum_ofdm->sent_cts_cnt,
|
||||
delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ba_rsp_cnt:",
|
||||
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
|
||||
accum_ofdm->sent_ba_rsp_cnt, delta_ofdm->sent_ba_rsp_cnt,
|
||||
max_ofdm->sent_ba_rsp_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_self_kill:",
|
||||
le32_to_cpu(ofdm->dsp_self_kill),
|
||||
accum_ofdm->dsp_self_kill, delta_ofdm->dsp_self_kill,
|
||||
max_ofdm->dsp_self_kill);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
|
||||
le32_to_cpu(ofdm->mh_format_err),
|
||||
accum_ofdm->mh_format_err, delta_ofdm->mh_format_err,
|
||||
max_ofdm->mh_format_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"re_acq_main_rssi_sum:",
|
||||
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
|
||||
accum_ofdm->re_acq_main_rssi_sum,
|
||||
delta_ofdm->re_acq_main_rssi_sum,
|
||||
max_ofdm->re_acq_main_rssi_sum);
|
||||
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_header,
|
||||
"Statistics_Rx - CCK:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "ina_cnt:",
|
||||
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
|
||||
delta_cck->ina_cnt, max_cck->ina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_cnt:",
|
||||
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
|
||||
delta_cck->fina_cnt, max_cck->fina_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
|
||||
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
|
||||
delta_cck->plcp_err, max_cck->plcp_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
|
||||
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
|
||||
delta_cck->crc32_err, max_cck->crc32_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
|
||||
le32_to_cpu(cck->overrun_err), accum_cck->overrun_err,
|
||||
delta_cck->overrun_err, max_cck->overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
|
||||
le32_to_cpu(cck->early_overrun_err),
|
||||
accum_cck->early_overrun_err,
|
||||
delta_cck->early_overrun_err, max_cck->early_overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
|
||||
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
|
||||
delta_cck->crc32_good, max_cck->crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "false_alarm_cnt:",
|
||||
le32_to_cpu(cck->false_alarm_cnt),
|
||||
accum_cck->false_alarm_cnt, delta_cck->false_alarm_cnt,
|
||||
max_cck->false_alarm_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_sync_err_cnt:",
|
||||
le32_to_cpu(cck->fina_sync_err_cnt),
|
||||
accum_cck->fina_sync_err_cnt,
|
||||
delta_cck->fina_sync_err_cnt, max_cck->fina_sync_err_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sfd_timeout:",
|
||||
le32_to_cpu(cck->sfd_timeout), accum_cck->sfd_timeout,
|
||||
delta_cck->sfd_timeout, max_cck->sfd_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_timeout:",
|
||||
le32_to_cpu(cck->fina_timeout), accum_cck->fina_timeout,
|
||||
delta_cck->fina_timeout, max_cck->fina_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "unresponded_rts:",
|
||||
le32_to_cpu(cck->unresponded_rts),
|
||||
accum_cck->unresponded_rts, delta_cck->unresponded_rts,
|
||||
max_cck->unresponded_rts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(cck->rxe_frame_limit_overrun),
|
||||
accum_cck->rxe_frame_limit_overrun,
|
||||
delta_cck->rxe_frame_limit_overrun,
|
||||
max_cck->rxe_frame_limit_overrun);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ack_cnt:",
|
||||
le32_to_cpu(cck->sent_ack_cnt), accum_cck->sent_ack_cnt,
|
||||
delta_cck->sent_ack_cnt, max_cck->sent_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_cts_cnt:",
|
||||
le32_to_cpu(cck->sent_cts_cnt), accum_cck->sent_cts_cnt,
|
||||
delta_cck->sent_cts_cnt, max_cck->sent_cts_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ba_rsp_cnt:",
|
||||
le32_to_cpu(cck->sent_ba_rsp_cnt),
|
||||
accum_cck->sent_ba_rsp_cnt, delta_cck->sent_ba_rsp_cnt,
|
||||
max_cck->sent_ba_rsp_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_self_kill:",
|
||||
le32_to_cpu(cck->dsp_self_kill), accum_cck->dsp_self_kill,
|
||||
delta_cck->dsp_self_kill, max_cck->dsp_self_kill);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
|
||||
le32_to_cpu(cck->mh_format_err), accum_cck->mh_format_err,
|
||||
delta_cck->mh_format_err, max_cck->mh_format_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"re_acq_main_rssi_sum:",
|
||||
le32_to_cpu(cck->re_acq_main_rssi_sum),
|
||||
accum_cck->re_acq_main_rssi_sum,
|
||||
delta_cck->re_acq_main_rssi_sum,
|
||||
max_cck->re_acq_main_rssi_sum);
|
||||
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_header,
|
||||
"Statistics_Rx - GENERAL:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "bogus_cts:",
|
||||
le32_to_cpu(general->bogus_cts), accum_general->bogus_cts,
|
||||
delta_general->bogus_cts, max_general->bogus_cts);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "bogus_ack:",
|
||||
le32_to_cpu(general->bogus_ack), accum_general->bogus_ack,
|
||||
delta_general->bogus_ack, max_general->bogus_ack);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "non_bssid_frames:",
|
||||
le32_to_cpu(general->non_bssid_frames),
|
||||
accum_general->non_bssid_frames,
|
||||
delta_general->non_bssid_frames,
|
||||
max_general->non_bssid_frames);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "filtered_frames:",
|
||||
le32_to_cpu(general->filtered_frames),
|
||||
accum_general->filtered_frames,
|
||||
delta_general->filtered_frames,
|
||||
max_general->filtered_frames);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "non_channel_beacons:",
|
||||
le32_to_cpu(general->non_channel_beacons),
|
||||
accum_general->non_channel_beacons,
|
||||
delta_general->non_channel_beacons,
|
||||
max_general->non_channel_beacons);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "channel_beacons:",
|
||||
le32_to_cpu(general->channel_beacons),
|
||||
accum_general->channel_beacons,
|
||||
delta_general->channel_beacons,
|
||||
max_general->channel_beacons);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "num_missed_bcon:",
|
||||
le32_to_cpu(general->num_missed_bcon),
|
||||
accum_general->num_missed_bcon,
|
||||
delta_general->num_missed_bcon,
|
||||
max_general->num_missed_bcon);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"adc_rx_saturation_time:",
|
||||
le32_to_cpu(general->adc_rx_saturation_time),
|
||||
accum_general->adc_rx_saturation_time,
|
||||
delta_general->adc_rx_saturation_time,
|
||||
max_general->adc_rx_saturation_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"ina_detect_search_tm:",
|
||||
le32_to_cpu(general->ina_detection_search_time),
|
||||
accum_general->ina_detection_search_time,
|
||||
delta_general->ina_detection_search_time,
|
||||
max_general->ina_detection_search_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"beacon_silence_rssi_a:",
|
||||
le32_to_cpu(general->beacon_silence_rssi_a),
|
||||
accum_general->beacon_silence_rssi_a,
|
||||
delta_general->beacon_silence_rssi_a,
|
||||
max_general->beacon_silence_rssi_a);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"beacon_silence_rssi_b:",
|
||||
le32_to_cpu(general->beacon_silence_rssi_b),
|
||||
accum_general->beacon_silence_rssi_b,
|
||||
delta_general->beacon_silence_rssi_b,
|
||||
max_general->beacon_silence_rssi_b);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"beacon_silence_rssi_c:",
|
||||
le32_to_cpu(general->beacon_silence_rssi_c),
|
||||
accum_general->beacon_silence_rssi_c,
|
||||
delta_general->beacon_silence_rssi_c,
|
||||
max_general->beacon_silence_rssi_c);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"interference_data_flag:",
|
||||
le32_to_cpu(general->interference_data_flag),
|
||||
accum_general->interference_data_flag,
|
||||
delta_general->interference_data_flag,
|
||||
max_general->interference_data_flag);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "channel_load:",
|
||||
le32_to_cpu(general->channel_load),
|
||||
accum_general->channel_load, delta_general->channel_load,
|
||||
max_general->channel_load);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_false_alarms:",
|
||||
le32_to_cpu(general->dsp_false_alarms),
|
||||
accum_general->dsp_false_alarms,
|
||||
delta_general->dsp_false_alarms,
|
||||
max_general->dsp_false_alarms);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_a:",
|
||||
le32_to_cpu(general->beacon_rssi_a),
|
||||
accum_general->beacon_rssi_a,
|
||||
delta_general->beacon_rssi_a, max_general->beacon_rssi_a);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_b:",
|
||||
le32_to_cpu(general->beacon_rssi_b),
|
||||
accum_general->beacon_rssi_b,
|
||||
delta_general->beacon_rssi_b, max_general->beacon_rssi_b);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_c:",
|
||||
le32_to_cpu(general->beacon_rssi_c),
|
||||
accum_general->beacon_rssi_c,
|
||||
delta_general->beacon_rssi_c, max_general->beacon_rssi_c);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_a:",
|
||||
le32_to_cpu(general->beacon_energy_a),
|
||||
accum_general->beacon_energy_a,
|
||||
delta_general->beacon_energy_a,
|
||||
max_general->beacon_energy_a);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_b:",
|
||||
le32_to_cpu(general->beacon_energy_b),
|
||||
accum_general->beacon_energy_b,
|
||||
delta_general->beacon_energy_b,
|
||||
max_general->beacon_energy_b);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_c:",
|
||||
le32_to_cpu(general->beacon_energy_c),
|
||||
accum_general->beacon_energy_c,
|
||||
delta_general->beacon_energy_c,
|
||||
max_general->beacon_energy_c);
|
||||
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_header,
|
||||
"Statistics_Rx - OFDM_HT:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
|
||||
le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
|
||||
delta_ht->plcp_err, max_ht->plcp_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
|
||||
le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
|
||||
delta_ht->overrun_err, max_ht->overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
|
||||
le32_to_cpu(ht->early_overrun_err),
|
||||
accum_ht->early_overrun_err, delta_ht->early_overrun_err,
|
||||
max_ht->early_overrun_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
|
||||
le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
|
||||
delta_ht->crc32_good, max_ht->crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
|
||||
le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
|
||||
delta_ht->crc32_err, max_ht->crc32_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
|
||||
le32_to_cpu(ht->mh_format_err), accum_ht->mh_format_err,
|
||||
delta_ht->mh_format_err, max_ht->mh_format_err);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_crc32_good:",
|
||||
le32_to_cpu(ht->agg_crc32_good), accum_ht->agg_crc32_good,
|
||||
delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_mpdu_cnt:",
|
||||
le32_to_cpu(ht->agg_mpdu_cnt), accum_ht->agg_mpdu_cnt,
|
||||
delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_cnt:",
|
||||
le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
|
||||
delta_ht->agg_cnt, max_ht->agg_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "unsupport_mcs:",
|
||||
le32_to_cpu(ht->unsupport_mcs), accum_ht->unsupport_mcs,
|
||||
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = (sizeof(struct stats_tx) * 48) + 250;
|
||||
ssize_t ret;
|
||||
struct stats_tx *tx, *accum_tx, *delta_tx, *max_tx;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* the statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
tx = &il->_4965.stats.tx;
|
||||
accum_tx = &il->_4965.accum_stats.tx;
|
||||
delta_tx = &il->_4965.delta_stats.tx;
|
||||
max_tx = &il->_4965.max_delta.tx;
|
||||
|
||||
pos += il4965_stats_flag(il, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, fmt_header, "Statistics_Tx:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "preamble:",
|
||||
le32_to_cpu(tx->preamble_cnt), accum_tx->preamble_cnt,
|
||||
delta_tx->preamble_cnt, max_tx->preamble_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "rx_detected_cnt:",
|
||||
le32_to_cpu(tx->rx_detected_cnt),
|
||||
accum_tx->rx_detected_cnt, delta_tx->rx_detected_cnt,
|
||||
max_tx->rx_detected_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "bt_prio_defer_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_defer_cnt),
|
||||
accum_tx->bt_prio_defer_cnt, delta_tx->bt_prio_defer_cnt,
|
||||
max_tx->bt_prio_defer_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "bt_prio_kill_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_kill_cnt),
|
||||
accum_tx->bt_prio_kill_cnt, delta_tx->bt_prio_kill_cnt,
|
||||
max_tx->bt_prio_kill_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "few_bytes_cnt:",
|
||||
le32_to_cpu(tx->few_bytes_cnt), accum_tx->few_bytes_cnt,
|
||||
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "cts_timeout:",
|
||||
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
|
||||
delta_tx->cts_timeout, max_tx->cts_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "ack_timeout:",
|
||||
le32_to_cpu(tx->ack_timeout), accum_tx->ack_timeout,
|
||||
delta_tx->ack_timeout, max_tx->ack_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "expected_ack_cnt:",
|
||||
le32_to_cpu(tx->expected_ack_cnt),
|
||||
accum_tx->expected_ack_cnt, delta_tx->expected_ack_cnt,
|
||||
max_tx->expected_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "actual_ack_cnt:",
|
||||
le32_to_cpu(tx->actual_ack_cnt), accum_tx->actual_ack_cnt,
|
||||
delta_tx->actual_ack_cnt, max_tx->actual_ack_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "dump_msdu_cnt:",
|
||||
le32_to_cpu(tx->dump_msdu_cnt), accum_tx->dump_msdu_cnt,
|
||||
delta_tx->dump_msdu_cnt, max_tx->dump_msdu_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"abort_nxt_frame_mismatch:",
|
||||
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
|
||||
accum_tx->burst_abort_next_frame_mismatch_cnt,
|
||||
delta_tx->burst_abort_next_frame_mismatch_cnt,
|
||||
max_tx->burst_abort_next_frame_mismatch_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"abort_missing_nxt_frame:",
|
||||
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
|
||||
accum_tx->burst_abort_missing_next_frame_cnt,
|
||||
delta_tx->burst_abort_missing_next_frame_cnt,
|
||||
max_tx->burst_abort_missing_next_frame_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"cts_timeout_collision:",
|
||||
le32_to_cpu(tx->cts_timeout_collision),
|
||||
accum_tx->cts_timeout_collision,
|
||||
delta_tx->cts_timeout_collision,
|
||||
max_tx->cts_timeout_collision);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"ack_ba_timeout_collision:",
|
||||
le32_to_cpu(tx->ack_or_ba_timeout_collision),
|
||||
accum_tx->ack_or_ba_timeout_collision,
|
||||
delta_tx->ack_or_ba_timeout_collision,
|
||||
max_tx->ack_or_ba_timeout_collision);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg ba_timeout:",
|
||||
le32_to_cpu(tx->agg.ba_timeout), accum_tx->agg.ba_timeout,
|
||||
delta_tx->agg.ba_timeout, max_tx->agg.ba_timeout);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"agg ba_resched_frames:",
|
||||
le32_to_cpu(tx->agg.ba_reschedule_frames),
|
||||
accum_tx->agg.ba_reschedule_frames,
|
||||
delta_tx->agg.ba_reschedule_frames,
|
||||
max_tx->agg.ba_reschedule_frames);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"agg scd_query_agg_frame:",
|
||||
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
|
||||
accum_tx->agg.scd_query_agg_frame_cnt,
|
||||
delta_tx->agg.scd_query_agg_frame_cnt,
|
||||
max_tx->agg.scd_query_agg_frame_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"agg scd_query_no_agg:",
|
||||
le32_to_cpu(tx->agg.scd_query_no_agg),
|
||||
accum_tx->agg.scd_query_no_agg,
|
||||
delta_tx->agg.scd_query_no_agg,
|
||||
max_tx->agg.scd_query_no_agg);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg scd_query_agg:",
|
||||
le32_to_cpu(tx->agg.scd_query_agg),
|
||||
accum_tx->agg.scd_query_agg, delta_tx->agg.scd_query_agg,
|
||||
max_tx->agg.scd_query_agg);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"agg scd_query_mismatch:",
|
||||
le32_to_cpu(tx->agg.scd_query_mismatch),
|
||||
accum_tx->agg.scd_query_mismatch,
|
||||
delta_tx->agg.scd_query_mismatch,
|
||||
max_tx->agg.scd_query_mismatch);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg frame_not_ready:",
|
||||
le32_to_cpu(tx->agg.frame_not_ready),
|
||||
accum_tx->agg.frame_not_ready,
|
||||
delta_tx->agg.frame_not_ready,
|
||||
max_tx->agg.frame_not_ready);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg underrun:",
|
||||
le32_to_cpu(tx->agg.underrun), accum_tx->agg.underrun,
|
||||
delta_tx->agg.underrun, max_tx->agg.underrun);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg bt_prio_kill:",
|
||||
le32_to_cpu(tx->agg.bt_prio_kill),
|
||||
accum_tx->agg.bt_prio_kill, delta_tx->agg.bt_prio_kill,
|
||||
max_tx->agg.bt_prio_kill);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "agg rx_ba_rsp_cnt:",
|
||||
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
|
||||
accum_tx->agg.rx_ba_rsp_cnt, delta_tx->agg.rx_ba_rsp_cnt,
|
||||
max_tx->agg.rx_ba_rsp_cnt);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
il4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct il_priv *il = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = sizeof(struct stats_general) * 10 + 300;
|
||||
ssize_t ret;
|
||||
struct stats_general_common *general, *accum_general;
|
||||
struct stats_general_common *delta_general, *max_general;
|
||||
struct stats_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
|
||||
struct stats_div *div, *accum_div, *delta_div, *max_div;
|
||||
|
||||
if (!il_is_alive(il))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IL_ERR("Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* the statistic information display here is based on
|
||||
* the last stats notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
general = &il->_4965.stats.general.common;
|
||||
dbg = &il->_4965.stats.general.common.dbg;
|
||||
div = &il->_4965.stats.general.common.div;
|
||||
accum_general = &il->_4965.accum_stats.general.common;
|
||||
accum_dbg = &il->_4965.accum_stats.general.common.dbg;
|
||||
accum_div = &il->_4965.accum_stats.general.common.div;
|
||||
delta_general = &il->_4965.delta_stats.general.common;
|
||||
max_general = &il->_4965.max_delta.general.common;
|
||||
delta_dbg = &il->_4965.delta_stats.general.common.dbg;
|
||||
max_dbg = &il->_4965.max_delta.general.common.dbg;
|
||||
delta_div = &il->_4965.delta_stats.general.common.div;
|
||||
max_div = &il->_4965.max_delta.general.common.div;
|
||||
|
||||
pos += il4965_stats_flag(il, buf, bufsz);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_header,
|
||||
"Statistics_General:");
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_value, "temperature:",
|
||||
le32_to_cpu(general->temperature));
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_value, "ttl_timestamp:",
|
||||
le32_to_cpu(general->ttl_timestamp));
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "burst_check:",
|
||||
le32_to_cpu(dbg->burst_check), accum_dbg->burst_check,
|
||||
delta_dbg->burst_check, max_dbg->burst_check);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "burst_count:",
|
||||
le32_to_cpu(dbg->burst_count), accum_dbg->burst_count,
|
||||
delta_dbg->burst_count, max_dbg->burst_count);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table,
|
||||
"wait_for_silence_timeout_count:",
|
||||
le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
|
||||
accum_dbg->wait_for_silence_timeout_cnt,
|
||||
delta_dbg->wait_for_silence_timeout_cnt,
|
||||
max_dbg->wait_for_silence_timeout_cnt);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "sleep_time:",
|
||||
le32_to_cpu(general->sleep_time),
|
||||
accum_general->sleep_time, delta_general->sleep_time,
|
||||
max_general->sleep_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "slots_out:",
|
||||
le32_to_cpu(general->slots_out), accum_general->slots_out,
|
||||
delta_general->slots_out, max_general->slots_out);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "slots_idle:",
|
||||
le32_to_cpu(general->slots_idle),
|
||||
accum_general->slots_idle, delta_general->slots_idle,
|
||||
max_general->slots_idle);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "tx_on_a:",
|
||||
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
|
||||
delta_div->tx_on_a, max_div->tx_on_a);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "tx_on_b:",
|
||||
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
|
||||
delta_div->tx_on_b, max_div->tx_on_b);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "exec_time:",
|
||||
le32_to_cpu(div->exec_time), accum_div->exec_time,
|
||||
delta_div->exec_time, max_div->exec_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "probe_time:",
|
||||
le32_to_cpu(div->probe_time), accum_div->probe_time,
|
||||
delta_div->probe_time, max_div->probe_time);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "rx_enable_counter:",
|
||||
le32_to_cpu(general->rx_enable_counter),
|
||||
accum_general->rx_enable_counter,
|
||||
delta_general->rx_enable_counter,
|
||||
max_general->rx_enable_counter);
|
||||
pos +=
|
||||
scnprintf(buf + pos, bufsz - pos, fmt_table, "num_of_sos_states:",
|
||||
le32_to_cpu(general->num_of_sos_states),
|
||||
accum_general->num_of_sos_states,
|
||||
delta_general->num_of_sos_states,
|
||||
max_general->num_of_sos_states);
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct il_debugfs_ops il4965_debugfs_ops = {
|
||||
.rx_stats_read = il4965_ucode_rx_stats_read,
|
||||
.tx_stats_read = il4965_ucode_tx_stats_read,
|
||||
.general_stats_read = il4965_ucode_general_stats_read,
|
||||
};
|
6868
drivers/net/wireless/intel/iwlegacy/4965-mac.c
Arquivo normal
6868
drivers/net/wireless/intel/iwlegacy/4965-mac.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
2835
drivers/net/wireless/intel/iwlegacy/4965-rs.c
Arquivo normal
2835
drivers/net/wireless/intel/iwlegacy/4965-rs.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
1950
drivers/net/wireless/intel/iwlegacy/4965.c
Arquivo normal
1950
drivers/net/wireless/intel/iwlegacy/4965.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
1285
drivers/net/wireless/intel/iwlegacy/4965.h
Arquivo normal
1285
drivers/net/wireless/intel/iwlegacy/4965.h
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
100
drivers/net/wireless/intel/iwlegacy/Kconfig
Arquivo normal
100
drivers/net/wireless/intel/iwlegacy/Kconfig
Arquivo normal
@@ -0,0 +1,100 @@
|
||||
config IWLEGACY
|
||||
tristate
|
||||
select FW_LOADER
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
select LEDS_TRIGGERS
|
||||
select MAC80211_LEDS
|
||||
|
||||
config IWL4965
|
||||
tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
|
||||
depends on PCI && MAC80211
|
||||
select IWLEGACY
|
||||
---help---
|
||||
This option enables support for
|
||||
|
||||
Select to build the driver supporting the:
|
||||
|
||||
Intel Wireless WiFi Link 4965AGN
|
||||
|
||||
This driver uses the kernel's mac80211 subsystem.
|
||||
|
||||
In order to use this driver, you will need a microcode (uCode)
|
||||
image for it. You can obtain the microcode from:
|
||||
|
||||
<http://intellinuxwireless.org/>.
|
||||
|
||||
The microcode is typically installed in /lib/firmware. You can
|
||||
look in the hotplug script /etc/hotplug/firmware.agent to
|
||||
determine which directory FIRMWARE_DIR is set to when the script
|
||||
runs.
|
||||
|
||||
If you want to compile the driver as a module ( = code which can be
|
||||
inserted in and removed from the running kernel whenever you want),
|
||||
say M here and read <file:Documentation/kbuild/modules.txt>. The
|
||||
module will be called iwl4965.
|
||||
|
||||
config IWL3945
|
||||
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
|
||||
depends on PCI && MAC80211
|
||||
select IWLEGACY
|
||||
---help---
|
||||
Select to build the driver supporting the:
|
||||
|
||||
Intel PRO/Wireless 3945ABG/BG Network Connection
|
||||
|
||||
This driver uses the kernel's mac80211 subsystem.
|
||||
|
||||
In order to use this driver, you will need a microcode (uCode)
|
||||
image for it. You can obtain the microcode from:
|
||||
|
||||
<http://intellinuxwireless.org/>.
|
||||
|
||||
The microcode is typically installed in /lib/firmware. You can
|
||||
look in the hotplug script /etc/hotplug/firmware.agent to
|
||||
determine which directory FIRMWARE_DIR is set to when the script
|
||||
runs.
|
||||
|
||||
If you want to compile the driver as a module ( = code which can be
|
||||
inserted in and removed from the running kernel whenever you want),
|
||||
say M here and read <file:Documentation/kbuild/modules.txt>. The
|
||||
module will be called iwl3945.
|
||||
|
||||
menu "iwl3945 / iwl4965 Debugging Options"
|
||||
depends on IWLEGACY
|
||||
|
||||
config IWLEGACY_DEBUG
|
||||
bool "Enable full debugging output in iwlegacy (iwl 3945/4965) drivers"
|
||||
depends on IWLEGACY
|
||||
---help---
|
||||
This option will enable debug tracing output for the iwlegacy
|
||||
drivers.
|
||||
|
||||
This will result in the kernel module being ~100k larger. You can
|
||||
control which debug output is sent to the kernel log by setting the
|
||||
value in
|
||||
|
||||
/sys/class/net/wlan0/device/debug_level
|
||||
|
||||
This entry will only exist if this option is enabled.
|
||||
|
||||
To set a value, simply echo an 8-byte hex value to the same file:
|
||||
|
||||
% echo 0x43fff > /sys/class/net/wlan0/device/debug_level
|
||||
|
||||
You can find the list of debug mask values in:
|
||||
drivers/net/wireless/iwlegacy/common.h
|
||||
|
||||
If this is your first time using this driver, you should say Y here
|
||||
as the debug information can assist others in helping you resolve
|
||||
any problems you may encounter.
|
||||
|
||||
config IWLEGACY_DEBUGFS
|
||||
bool "iwlegacy (iwl 3945/4965) debugfs support"
|
||||
depends on IWLEGACY && MAC80211_DEBUGFS
|
||||
---help---
|
||||
Enable creation of debugfs files for the iwlegacy drivers. This
|
||||
is a low-impact option that allows getting insight into the
|
||||
driver's state at runtime.
|
||||
|
||||
endmenu
|
17
drivers/net/wireless/intel/iwlegacy/Makefile
Arquivo normal
17
drivers/net/wireless/intel/iwlegacy/Makefile
Arquivo normal
@@ -0,0 +1,17 @@
|
||||
obj-$(CONFIG_IWLEGACY) += iwlegacy.o
|
||||
iwlegacy-objs := common.o
|
||||
iwlegacy-$(CONFIG_IWLEGACY_DEBUGFS) += debug.o
|
||||
|
||||
iwlegacy-objs += $(iwlegacy-m)
|
||||
|
||||
# 4965
|
||||
obj-$(CONFIG_IWL4965) += iwl4965.o
|
||||
iwl4965-objs := 4965.o 4965-mac.o 4965-rs.o 4965-calib.o
|
||||
iwl4965-$(CONFIG_IWLEGACY_DEBUGFS) += 4965-debug.o
|
||||
|
||||
# 3945
|
||||
obj-$(CONFIG_IWL3945) += iwl3945.o
|
||||
iwl3945-objs := 3945-mac.o 3945.o 3945-rs.o
|
||||
iwl3945-$(CONFIG_IWLEGACY_DEBUGFS) += 3945-debug.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
3370
drivers/net/wireless/intel/iwlegacy/commands.h
Arquivo normal
3370
drivers/net/wireless/intel/iwlegacy/commands.h
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
5586
drivers/net/wireless/intel/iwlegacy/common.c
Arquivo normal
5586
drivers/net/wireless/intel/iwlegacy/common.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
3084
drivers/net/wireless/intel/iwlegacy/common.h
Arquivo normal
3084
drivers/net/wireless/intel/iwlegacy/common.h
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
419
drivers/net/wireless/intel/iwlegacy/csr.h
Arquivo normal
419
drivers/net/wireless/intel/iwlegacy/csr.h
Arquivo normal
@@ -0,0 +1,419 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __il_csr_h__
|
||||
#define __il_csr_h__
|
||||
/*
|
||||
* CSR (control and status registers)
|
||||
*
|
||||
* CSR registers are mapped directly into PCI bus space, and are accessible
|
||||
* whenever platform supplies power to device, even when device is in
|
||||
* low power states due to driver-invoked device resets
|
||||
* (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
|
||||
*
|
||||
* Use _il_wr() and _il_rd() family to access these registers;
|
||||
* these provide simple PCI bus access, without waking up the MAC.
|
||||
* Do not use il_wr() family for these registers;
|
||||
* no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
|
||||
* The MAC (uCode processor, etc.) does not need to be powered up for accessing
|
||||
* the CSR registers.
|
||||
*
|
||||
* NOTE: Device does need to be awake in order to read this memory
|
||||
* via CSR_EEPROM register
|
||||
*/
|
||||
#define CSR_BASE (0x000)
|
||||
|
||||
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
|
||||
#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
|
||||
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
|
||||
#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
|
||||
#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack */
|
||||
#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
|
||||
#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc */
|
||||
#define CSR_GP_CNTRL (CSR_BASE+0x024)
|
||||
|
||||
/* 2nd byte of CSR_INT_COALESCING, not accessible via _il_wr()! */
|
||||
#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
|
||||
|
||||
/*
|
||||
* Hardware revision info
|
||||
* Bit fields:
|
||||
* 31-8: Reserved
|
||||
* 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions
|
||||
* 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
|
||||
* 1-0: "Dash" (-) value, as in A-1, etc.
|
||||
*
|
||||
* NOTE: Revision step affects calculation of CCK txpower for 4965.
|
||||
* NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965).
|
||||
*/
|
||||
#define CSR_HW_REV (CSR_BASE+0x028)
|
||||
|
||||
/*
|
||||
* EEPROM memory reads
|
||||
*
|
||||
* NOTE: Device must be awake, initialized via apm_ops.init(),
|
||||
* in order to read.
|
||||
*/
|
||||
#define CSR_EEPROM_REG (CSR_BASE+0x02c)
|
||||
#define CSR_EEPROM_GP (CSR_BASE+0x030)
|
||||
|
||||
#define CSR_GIO_REG (CSR_BASE+0x03C)
|
||||
#define CSR_GP_UCODE_REG (CSR_BASE+0x048)
|
||||
#define CSR_GP_DRIVER_REG (CSR_BASE+0x050)
|
||||
|
||||
/*
|
||||
* UCODE-DRIVER GP (general purpose) mailbox registers.
|
||||
* SET/CLR registers set/clear bit(s) if "1" is written.
|
||||
*/
|
||||
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
|
||||
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
|
||||
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
|
||||
#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
|
||||
|
||||
#define CSR_LED_REG (CSR_BASE+0x094)
|
||||
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
|
||||
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
||||
/* Analog phase-lock-loop configuration */
|
||||
#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
|
||||
|
||||
/*
|
||||
* CSR Hardware Revision Workaround Register. Indicates hardware rev;
|
||||
* "step" determines CCK backoff for txpower calculation. Used for 4965 only.
|
||||
* See also CSR_HW_REV register.
|
||||
* Bit fields:
|
||||
* 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
|
||||
* 1-0: "Dash" (-) value, as in C-1, etc.
|
||||
*/
|
||||
#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
|
||||
|
||||
#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240)
|
||||
#define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250)
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
|
||||
|
||||
#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100)
|
||||
#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200)
|
||||
#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
|
||||
#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
|
||||
#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
|
||||
#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
|
||||
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
|
||||
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
|
||||
|
||||
#define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int */
|
||||
#define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec */
|
||||
|
||||
/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
|
||||
* acknowledged (reset) by host writing "1" to flagged bits. */
|
||||
#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
|
||||
#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
|
||||
#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */
|
||||
#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
|
||||
#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
|
||||
#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
|
||||
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
|
||||
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
|
||||
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
|
||||
#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
|
||||
#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
|
||||
|
||||
#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
|
||||
CSR_INT_BIT_HW_ERR | \
|
||||
CSR_INT_BIT_FH_TX | \
|
||||
CSR_INT_BIT_SW_ERR | \
|
||||
CSR_INT_BIT_RF_KILL | \
|
||||
CSR_INT_BIT_SW_RX | \
|
||||
CSR_INT_BIT_WAKEUP | \
|
||||
CSR_INT_BIT_ALIVE)
|
||||
|
||||
/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
|
||||
#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
|
||||
#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
|
||||
#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
|
||||
#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
|
||||
#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
|
||||
#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
|
||||
#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
|
||||
#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
|
||||
|
||||
#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
|
||||
CSR39_FH_INT_BIT_RX_CHNL2 | \
|
||||
CSR_FH_INT_BIT_RX_CHNL1 | \
|
||||
CSR_FH_INT_BIT_RX_CHNL0)
|
||||
|
||||
#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \
|
||||
CSR_FH_INT_BIT_TX_CHNL1 | \
|
||||
CSR_FH_INT_BIT_TX_CHNL0)
|
||||
|
||||
#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
|
||||
CSR_FH_INT_BIT_RX_CHNL1 | \
|
||||
CSR_FH_INT_BIT_RX_CHNL0)
|
||||
|
||||
#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
|
||||
CSR_FH_INT_BIT_TX_CHNL0)
|
||||
|
||||
/* GPIO */
|
||||
#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
|
||||
#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
|
||||
#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC (0x00000200)
|
||||
|
||||
/* RESET */
|
||||
#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
|
||||
#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
|
||||
#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
|
||||
#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
|
||||
#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
|
||||
#define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000)
|
||||
|
||||
/*
|
||||
* GP (general purpose) CONTROL REGISTER
|
||||
* Bit fields:
|
||||
* 27: HW_RF_KILL_SW
|
||||
* Indicates state of (platform's) hardware RF-Kill switch
|
||||
* 26-24: POWER_SAVE_TYPE
|
||||
* Indicates current power-saving mode:
|
||||
* 000 -- No power saving
|
||||
* 001 -- MAC power-down
|
||||
* 010 -- PHY (radio) power-down
|
||||
* 011 -- Error
|
||||
* 9-6: SYS_CONFIG
|
||||
* Indicates current system configuration, reflecting pins on chip
|
||||
* as forced high/low by device circuit board.
|
||||
* 4: GOING_TO_SLEEP
|
||||
* Indicates MAC is entering a power-saving sleep power-down.
|
||||
* Not a good time to access device-internal resources.
|
||||
* 3: MAC_ACCESS_REQ
|
||||
* Host sets this to request and maintain MAC wakeup, to allow host
|
||||
* access to device-internal resources. Host must wait for
|
||||
* MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
|
||||
* device registers.
|
||||
* 2: INIT_DONE
|
||||
* Host sets this to put device into fully operational D0 power mode.
|
||||
* Host resets this after SW_RESET to put device into low power mode.
|
||||
* 0: MAC_CLOCK_READY
|
||||
* Indicates MAC (ucode processor, etc.) is powered up and can run.
|
||||
* Internal resources are accessible.
|
||||
* NOTE: This does not indicate that the processor is actually running.
|
||||
* NOTE: This does not indicate that 4965 or 3945 has completed
|
||||
* init or post-power-down restore of internal SRAM memory.
|
||||
* Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
|
||||
* SRAM is restored and uCode is in normal operation mode.
|
||||
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
|
||||
* do not need to save/restore it.
|
||||
* NOTE: After device reset, this bit remains "0" until host sets
|
||||
* INIT_DONE
|
||||
*/
|
||||
#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
|
||||
#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
|
||||
#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
|
||||
#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
|
||||
|
||||
#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
|
||||
|
||||
#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
|
||||
#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
|
||||
#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
|
||||
|
||||
/* EEPROM REG */
|
||||
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
|
||||
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
|
||||
#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC)
|
||||
#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000)
|
||||
|
||||
/* EEPROM GP */
|
||||
#define CSR_EEPROM_GP_VALID_MSK (0x00000007) /* signature */
|
||||
#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
|
||||
#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002)
|
||||
#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004)
|
||||
|
||||
/* GP REG */
|
||||
#define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */
|
||||
#define CSR_GP_REG_NO_POWER_SAVE (0x00000000)
|
||||
#define CSR_GP_REG_MAC_POWER_SAVE (0x01000000)
|
||||
#define CSR_GP_REG_PHY_POWER_SAVE (0x02000000)
|
||||
#define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000)
|
||||
|
||||
/* CSR GIO */
|
||||
#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002)
|
||||
|
||||
/*
|
||||
* UCODE-DRIVER GP (general purpose) mailbox register 1
|
||||
* Host driver and uCode write and/or read this register to communicate with
|
||||
* each other.
|
||||
* Bit fields:
|
||||
* 4: UCODE_DISABLE
|
||||
* Host sets this to request permanent halt of uCode, same as
|
||||
* sending CARD_STATE command with "halt" bit set.
|
||||
* 3: CT_KILL_EXIT
|
||||
* Host sets this to request exit from CT_KILL state, i.e. host thinks
|
||||
* device temperature is low enough to continue normal operation.
|
||||
* 2: CMD_BLOCKED
|
||||
* Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)
|
||||
* to release uCode to clear all Tx and command queues, enter
|
||||
* unassociated mode, and power down.
|
||||
* NOTE: Some devices also use HBUS_TARG_MBX_C register for this bit.
|
||||
* 1: SW_BIT_RFKILL
|
||||
* Host sets this when issuing CARD_STATE command to request
|
||||
* device sleep.
|
||||
* 0: MAC_SLEEP
|
||||
* uCode sets this when preparing a power-saving power-down.
|
||||
* uCode resets this when power-up is complete and SRAM is sane.
|
||||
* NOTE: 3945/4965 saves internal SRAM data to host when powering down,
|
||||
* and must restore this data after powering back up.
|
||||
* MAC_SLEEP is the best indication that restore is complete.
|
||||
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
|
||||
* do not need to save/restore it.
|
||||
*/
|
||||
#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
|
||||
#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
|
||||
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
|
||||
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
|
||||
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
|
||||
#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
|
||||
|
||||
/* LED */
|
||||
#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
|
||||
#define CSR_LED_REG_TRUN_ON (0x78)
|
||||
#define CSR_LED_REG_TRUN_OFF (0x38)
|
||||
|
||||
/* ANA_PLL */
|
||||
#define CSR39_ANA_PLL_CFG_VAL (0x01000000)
|
||||
|
||||
/* HPET MEM debug */
|
||||
#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000)
|
||||
|
||||
/* DRAM INT TBL */
|
||||
#define CSR_DRAM_INT_TBL_ENABLE (1 << 31)
|
||||
#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)
|
||||
|
||||
/*
|
||||
* HBUS (Host-side Bus)
|
||||
*
|
||||
* HBUS registers are mapped directly into PCI bus space, but are used
|
||||
* to indirectly access device's internal memory or registers that
|
||||
* may be powered-down.
|
||||
*
|
||||
* Use il_wr()/il_rd() family
|
||||
* for these registers;
|
||||
* host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
|
||||
* to make sure the MAC (uCode processor, etc.) is powered up for accessing
|
||||
* internal resources.
|
||||
*
|
||||
* Do not use _il_wr()/_il_rd() family to access these registers;
|
||||
* these provide only simple PCI bus access, without waking up the MAC.
|
||||
*/
|
||||
#define HBUS_BASE (0x400)
|
||||
|
||||
/*
|
||||
* Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
|
||||
* structures, error log, event log, verifying uCode load).
|
||||
* First write to address register, then read from or write to data register
|
||||
* to complete the job. Once the address register is set up, accesses to
|
||||
* data registers auto-increment the address by one dword.
|
||||
* Bit usage for address registers (read or write):
|
||||
* 0-31: memory address within device
|
||||
*/
|
||||
#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
|
||||
#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
|
||||
#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
|
||||
#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
|
||||
|
||||
/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */
|
||||
#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
|
||||
#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
|
||||
|
||||
/*
|
||||
* Registers for accessing device's internal peripheral registers
|
||||
* (e.g. SCD, BSM, etc.). First write to address register,
|
||||
* then read from or write to data register to complete the job.
|
||||
* Bit usage for address registers (read or write):
|
||||
* 0-15: register address (offset) within device
|
||||
* 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
|
||||
*/
|
||||
#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
|
||||
#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
|
||||
#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
|
||||
#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
|
||||
|
||||
/*
|
||||
* Per-Tx-queue write pointer (idx, really!)
|
||||
* Indicates idx to next TFD that driver will fill (1 past latest filled).
|
||||
* Bit usage:
|
||||
* 0-7: queue write idx
|
||||
* 11-8: queue selector
|
||||
*/
|
||||
#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
|
||||
|
||||
#endif /* !__il_csr_h__ */
|
1426
drivers/net/wireless/intel/iwlegacy/debug.c
Arquivo normal
1426
drivers/net/wireless/intel/iwlegacy/debug.c
Arquivo normal
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
92
drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
Arquivo normal
92
drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
Arquivo normal
@@ -0,0 +1,92 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Portions of this file are derived from the ieee80211 subsystem header files.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __il_spectrum_h__
|
||||
#define __il_spectrum_h__
|
||||
enum { /* ieee80211_basic_report.map */
|
||||
IEEE80211_BASIC_MAP_BSS = (1 << 0),
|
||||
IEEE80211_BASIC_MAP_OFDM = (1 << 1),
|
||||
IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
|
||||
IEEE80211_BASIC_MAP_RADAR = (1 << 3),
|
||||
IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
|
||||
/* Bits 5-7 are reserved */
|
||||
|
||||
};
|
||||
struct ieee80211_basic_report {
|
||||
u8 channel;
|
||||
__le64 start_time;
|
||||
__le16 duration;
|
||||
u8 map;
|
||||
} __packed;
|
||||
|
||||
enum { /* ieee80211_measurement_request.mode */
|
||||
/* Bit 0 is reserved */
|
||||
IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
|
||||
IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
|
||||
IEEE80211_MEASUREMENT_REPORT = (1 << 3),
|
||||
/* Bits 4-7 are reserved */
|
||||
};
|
||||
|
||||
enum {
|
||||
IEEE80211_REPORT_BASIC = 0, /* required */
|
||||
IEEE80211_REPORT_CCA = 1, /* optional */
|
||||
IEEE80211_REPORT_RPI = 2, /* optional */
|
||||
/* 3-255 reserved */
|
||||
};
|
||||
|
||||
struct ieee80211_measurement_params {
|
||||
u8 channel;
|
||||
__le64 start_time;
|
||||
__le16 duration;
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_info_element {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_measurement_request {
|
||||
struct ieee80211_info_element ie;
|
||||
u8 token;
|
||||
u8 mode;
|
||||
u8 type;
|
||||
struct ieee80211_measurement_params params[0];
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_measurement_report {
|
||||
struct ieee80211_info_element ie;
|
||||
u8 token;
|
||||
u8 mode;
|
||||
u8 type;
|
||||
union {
|
||||
struct ieee80211_basic_report basic[0];
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
#endif
|
522
drivers/net/wireless/intel/iwlegacy/prph.h
Arquivo normal
522
drivers/net/wireless/intel/iwlegacy/prph.h
Arquivo normal
@@ -0,0 +1,522 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __il_prph_h__
|
||||
#define __il_prph_h__
|
||||
|
||||
/*
|
||||
* Registers in this file are internal, not PCI bus memory mapped.
|
||||
* Driver accesses these via HBUS_TARG_PRPH_* registers.
|
||||
*/
|
||||
#define PRPH_BASE (0x00000)
|
||||
#define PRPH_END (0xFFFFF)
|
||||
|
||||
/* APMG (power management) constants */
|
||||
#define APMG_BASE (PRPH_BASE + 0x3000)
|
||||
#define APMG_CLK_CTRL_REG (APMG_BASE + 0x0000)
|
||||
#define APMG_CLK_EN_REG (APMG_BASE + 0x0004)
|
||||
#define APMG_CLK_DIS_REG (APMG_BASE + 0x0008)
|
||||
#define APMG_PS_CTRL_REG (APMG_BASE + 0x000c)
|
||||
#define APMG_PCIDEV_STT_REG (APMG_BASE + 0x0010)
|
||||
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
|
||||
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
|
||||
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
|
||||
#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
|
||||
#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
|
||||
|
||||
#define APMS_CLK_VAL_MRB_FUNC_MODE (0x00000001)
|
||||
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
|
||||
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
|
||||
|
||||
#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000)
|
||||
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
|
||||
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)
|
||||
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
|
||||
#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */
|
||||
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
|
||||
#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
|
||||
#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
|
||||
|
||||
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
|
||||
|
||||
/**
|
||||
* BSM (Bootstrap State Machine)
|
||||
*
|
||||
* The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
|
||||
* in special SRAM that does not power down when the embedded control
|
||||
* processor is sleeping (e.g. for periodic power-saving shutdowns of radio).
|
||||
*
|
||||
* When powering back up after sleeps (or during initial uCode load), the BSM
|
||||
* internally loads the short bootstrap program from the special SRAM into the
|
||||
* embedded processor's instruction SRAM, and starts the processor so it runs
|
||||
* the bootstrap program.
|
||||
*
|
||||
* This bootstrap program loads (via PCI busmaster DMA) instructions and data
|
||||
* images for a uCode program from host DRAM locations. The host driver
|
||||
* indicates DRAM locations and sizes for instruction and data images via the
|
||||
* four BSM_DRAM_* registers. Once the bootstrap program loads the new program,
|
||||
* the new program starts automatically.
|
||||
*
|
||||
* The uCode used for open-source drivers includes two programs:
|
||||
*
|
||||
* 1) Initialization -- performs hardware calibration and sets up some
|
||||
* internal data, then notifies host via "initialize alive" notification
|
||||
* (struct il_init_alive_resp) that it has completed all of its work.
|
||||
* After signal from host, it then loads and starts the runtime program.
|
||||
* The initialization program must be used when initially setting up the
|
||||
* NIC after loading the driver.
|
||||
*
|
||||
* 2) Runtime/Protocol -- performs all normal runtime operations. This
|
||||
* notifies host via "alive" notification (struct il_alive_resp) that it
|
||||
* is ready to be used.
|
||||
*
|
||||
* When initializing the NIC, the host driver does the following procedure:
|
||||
*
|
||||
* 1) Load bootstrap program (instructions only, no data image for bootstrap)
|
||||
* into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND
|
||||
*
|
||||
* 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction
|
||||
* images in host DRAM.
|
||||
*
|
||||
* 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked:
|
||||
* BSM_WR_MEM_SRC_REG = 0
|
||||
* BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND
|
||||
* BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image
|
||||
*
|
||||
* 4) Load bootstrap into instruction SRAM:
|
||||
* BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START
|
||||
*
|
||||
* 5) Wait for load completion:
|
||||
* Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0
|
||||
*
|
||||
* 6) Enable future boot loads whenever NIC's power management triggers it:
|
||||
* BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN
|
||||
*
|
||||
* 7) Start the NIC by removing all reset bits:
|
||||
* CSR_RESET = 0
|
||||
*
|
||||
* The bootstrap uCode (already in instruction SRAM) loads initialization
|
||||
* uCode. Initialization uCode performs data initialization, sends
|
||||
* "initialize alive" notification to host, and waits for a signal from
|
||||
* host to load runtime code.
|
||||
*
|
||||
* 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
|
||||
* images in host DRAM. The last register loaded must be the instruction
|
||||
* byte count register ("1" in MSbit tells initialization uCode to load
|
||||
* the runtime uCode):
|
||||
* BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD
|
||||
*
|
||||
* 5) Wait for "alive" notification, then issue normal runtime commands.
|
||||
*
|
||||
* Data caching during power-downs:
|
||||
*
|
||||
* Just before the embedded controller powers down (e.g for automatic
|
||||
* power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA)
|
||||
* a current snapshot of the embedded processor's data SRAM into host DRAM.
|
||||
* This caches the data while the embedded processor's memory is powered down.
|
||||
* Location and size are controlled by BSM_DRAM_DATA_* registers.
|
||||
*
|
||||
* NOTE: Instruction SRAM does not need to be saved, since that doesn't
|
||||
* change during operation; the original image (from uCode distribution
|
||||
* file) can be used for reload.
|
||||
*
|
||||
* When powering back up, the BSM loads the bootstrap program. Bootstrap looks
|
||||
* at the BSM_DRAM_* registers, which now point to the runtime instruction
|
||||
* image and the cached (modified) runtime data (*not* the initialization
|
||||
* uCode). Bootstrap reloads these runtime images into SRAM, and restarts the
|
||||
* uCode from where it left off before the power-down.
|
||||
*
|
||||
* NOTE: Initialization uCode does *not* run as part of the save/restore
|
||||
* procedure.
|
||||
*
|
||||
* This save/restore method is mostly for autonomous power management during
|
||||
* normal operation (result of C_POWER_TBL). Platform suspend/resume and
|
||||
* RFKILL should use complete restarts (with total re-initialization) of uCode,
|
||||
* allowing total shutdown (including BSM memory).
|
||||
*
|
||||
* Note that, during normal operation, the host DRAM that held the initial
|
||||
* startup data for the runtime code is now being used as a backup data cache
|
||||
* for modified data! If you need to completely re-initialize the NIC, make
|
||||
* sure that you use the runtime data image from the uCode distribution file,
|
||||
* not the modified/saved runtime data. You may want to store a separate
|
||||
* "clean" runtime data image in DRAM to avoid disk reads of distribution file.
|
||||
*/
|
||||
|
||||
/* BSM bit fields */
|
||||
#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */
|
||||
#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup */
|
||||
#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */
|
||||
|
||||
/* BSM addresses */
|
||||
#define BSM_BASE (PRPH_BASE + 0x3400)
|
||||
#define BSM_END (PRPH_BASE + 0x3800)
|
||||
|
||||
#define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */
|
||||
#define BSM_WR_MEM_SRC_REG (BSM_BASE + 0x004) /* source in BSM mem */
|
||||
#define BSM_WR_MEM_DST_REG (BSM_BASE + 0x008) /* dest in SRAM mem */
|
||||
#define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */
|
||||
#define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */
|
||||
|
||||
/*
|
||||
* Pointers and size regs for bootstrap load and data SRAM save/restore.
|
||||
* NOTE: 3945 pointers use bits 31:0 of DRAM address.
|
||||
* 4965 pointers use bits 35:4 of DRAM address.
|
||||
*/
|
||||
#define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090)
|
||||
#define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094)
|
||||
#define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098)
|
||||
#define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C)
|
||||
|
||||
/*
|
||||
* BSM special memory, stays powered on during power-save sleeps.
|
||||
* Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1)
|
||||
*/
|
||||
#define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800)
|
||||
#define BSM_SRAM_SIZE (1024) /* bytes */
|
||||
|
||||
/* 3945 Tx scheduler registers */
|
||||
#define ALM_SCD_BASE (PRPH_BASE + 0x2E00)
|
||||
#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000)
|
||||
#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004)
|
||||
#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010)
|
||||
#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014)
|
||||
#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020)
|
||||
#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C)
|
||||
#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030)
|
||||
|
||||
/**
|
||||
* Tx Scheduler
|
||||
*
|
||||
* The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
|
||||
* (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
|
||||
* host DRAM. It steers each frame's Tx command (which contains the frame
|
||||
* data) into one of up to 7 prioritized Tx DMA FIFO channels within the
|
||||
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
|
||||
* but one DMA channel may take input from several queues.
|
||||
*
|
||||
* Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows
|
||||
* (cf. default_queue_to_tx_fifo in 4965.c):
|
||||
*
|
||||
* 0 -- EDCA BK (background) frames, lowest priority
|
||||
* 1 -- EDCA BE (best effort) frames, normal priority
|
||||
* 2 -- EDCA VI (video) frames, higher priority
|
||||
* 3 -- EDCA VO (voice) and management frames, highest priority
|
||||
* 4 -- Commands (e.g. RXON, etc.)
|
||||
* 5 -- unused (HCCA)
|
||||
* 6 -- unused (HCCA)
|
||||
* 7 -- not used by driver (device-internal only)
|
||||
*
|
||||
*
|
||||
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
|
||||
* In addition, driver can map the remaining queues to Tx DMA/FIFO
|
||||
* channels 0-3 to support 11n aggregation via EDCA DMA channels.
|
||||
*
|
||||
* The driver sets up each queue to work in one of two modes:
|
||||
*
|
||||
* 1) Scheduler-Ack, in which the scheduler automatically supports a
|
||||
* block-ack (BA) win of up to 64 TFDs. In this mode, each queue
|
||||
* contains TFDs for a unique combination of Recipient Address (RA)
|
||||
* and Traffic Identifier (TID), that is, traffic of a given
|
||||
* Quality-Of-Service (QOS) priority, destined for a single station.
|
||||
*
|
||||
* In scheduler-ack mode, the scheduler keeps track of the Tx status of
|
||||
* each frame within the BA win, including whether it's been transmitted,
|
||||
* and whether it's been acknowledged by the receiving station. The device
|
||||
* automatically processes block-acks received from the receiving STA,
|
||||
* and reschedules un-acked frames to be retransmitted (successful
|
||||
* Tx completion may end up being out-of-order).
|
||||
*
|
||||
* The driver must maintain the queue's Byte Count table in host DRAM
|
||||
* (struct il4965_sched_queue_byte_cnt_tbl) for this mode.
|
||||
* This mode does not support fragmentation.
|
||||
*
|
||||
* 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
|
||||
* The device may automatically retry Tx, but will retry only one frame
|
||||
* at a time, until receiving ACK from receiving station, or reaching
|
||||
* retry limit and giving up.
|
||||
*
|
||||
* The command queue (#4/#9) must use this mode!
|
||||
* This mode does not require use of the Byte Count table in host DRAM.
|
||||
*
|
||||
* Driver controls scheduler operation via 3 means:
|
||||
* 1) Scheduler registers
|
||||
* 2) Shared scheduler data base in internal 4956 SRAM
|
||||
* 3) Shared data in host DRAM
|
||||
*
|
||||
* Initialization:
|
||||
*
|
||||
* When loading, driver should allocate memory for:
|
||||
* 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs.
|
||||
* 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory
|
||||
* (1024 bytes for each queue).
|
||||
*
|
||||
* After receiving "Alive" response from uCode, driver must initialize
|
||||
* the scheduler (especially for queue #4/#9, the command queue, otherwise
|
||||
* the driver can't issue commands!):
|
||||
*/
|
||||
|
||||
/**
|
||||
* Max Tx win size is the max number of contiguous TFDs that the scheduler
|
||||
* can keep track of at one time when creating block-ack chains of frames.
|
||||
* Note that "64" matches the number of ack bits in a block-ack packet.
|
||||
* Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize
|
||||
* IL49_SCD_CONTEXT_QUEUE_OFFSET(x) values.
|
||||
*/
|
||||
#define SCD_WIN_SIZE 64
|
||||
#define SCD_FRAME_LIMIT 64
|
||||
|
||||
/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */
|
||||
#define IL49_SCD_START_OFFSET 0xa02c00
|
||||
|
||||
/*
|
||||
* 4965 tells driver SRAM address for internal scheduler structs via this reg.
|
||||
* Value is valid only after "Alive" response from uCode.
|
||||
*/
|
||||
#define IL49_SCD_SRAM_BASE_ADDR (IL49_SCD_START_OFFSET + 0x0)
|
||||
|
||||
/*
|
||||
* Driver may need to update queue-empty bits after changing queue's
|
||||
* write and read pointers (idxes) during (re-)initialization (i.e. when
|
||||
* scheduler is not tracking what's happening).
|
||||
* Bit fields:
|
||||
* 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit
|
||||
* 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty
|
||||
* NOTE: This register is not used by Linux driver.
|
||||
*/
|
||||
#define IL49_SCD_EMPTY_BITS (IL49_SCD_START_OFFSET + 0x4)
|
||||
|
||||
/*
|
||||
* Physical base address of array of byte count (BC) circular buffers (CBs).
|
||||
* Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode.
|
||||
* This register points to BC CB for queue 0, must be on 1024-byte boundary.
|
||||
* Others are spaced by 1024 bytes.
|
||||
* Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad.
|
||||
* (Index into a queue's BC CB) = (idx into queue's TFD CB) = (SSN & 0xff).
|
||||
* Bit fields:
|
||||
* 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned.
|
||||
*/
|
||||
#define IL49_SCD_DRAM_BASE_ADDR (IL49_SCD_START_OFFSET + 0x10)
|
||||
|
||||
/*
|
||||
* Enables any/all Tx DMA/FIFO channels.
|
||||
* Scheduler generates requests for only the active channels.
|
||||
* Set this to 0xff to enable all 8 channels (normal usage).
|
||||
* Bit fields:
|
||||
* 7- 0: Enable (1), disable (0), one bit for each channel 0-7
|
||||
*/
|
||||
#define IL49_SCD_TXFACT (IL49_SCD_START_OFFSET + 0x1c)
|
||||
/*
|
||||
* Queue (x) Write Pointers (idxes, really!), one for each Tx queue.
|
||||
* Initialized and updated by driver as new TFDs are added to queue.
|
||||
* NOTE: If using Block Ack, idx must correspond to frame's
|
||||
* Start Sequence Number; idx = (SSN & 0xff)
|
||||
* NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses?
|
||||
*/
|
||||
#define IL49_SCD_QUEUE_WRPTR(x) (IL49_SCD_START_OFFSET + 0x24 + (x) * 4)
|
||||
|
||||
/*
|
||||
* Queue (x) Read Pointers (idxes, really!), one for each Tx queue.
|
||||
* For FIFO mode, idx indicates next frame to transmit.
|
||||
* For Scheduler-ACK mode, idx indicates first frame in Tx win.
|
||||
* Initialized by driver, updated by scheduler.
|
||||
*/
|
||||
#define IL49_SCD_QUEUE_RDPTR(x) (IL49_SCD_START_OFFSET + 0x64 + (x) * 4)
|
||||
|
||||
/*
|
||||
* Select which queues work in chain mode (1) vs. not (0).
|
||||
* Use chain mode to build chains of aggregated frames.
|
||||
* Bit fields:
|
||||
* 31-16: Reserved
|
||||
* 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time
|
||||
* NOTE: If driver sets up queue for chain mode, it should be also set up
|
||||
* Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x).
|
||||
*/
|
||||
#define IL49_SCD_QUEUECHAIN_SEL (IL49_SCD_START_OFFSET + 0xd0)
|
||||
|
||||
/*
|
||||
* Select which queues interrupt driver when scheduler increments
|
||||
* a queue's read pointer (idx).
|
||||
* Bit fields:
|
||||
* 31-16: Reserved
|
||||
* 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled
|
||||
* NOTE: This functionality is apparently a no-op; driver relies on interrupts
|
||||
* from Rx queue to read Tx command responses and update Tx queues.
|
||||
*/
|
||||
#define IL49_SCD_INTERRUPT_MASK (IL49_SCD_START_OFFSET + 0xe4)
|
||||
|
||||
/*
|
||||
* Queue search status registers. One for each queue.
|
||||
* Sets up queue mode and assigns queue to Tx DMA channel.
|
||||
* Bit fields:
|
||||
* 19-10: Write mask/enable bits for bits 0-9
|
||||
* 9: Driver should init to "0"
|
||||
* 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0).
|
||||
* Driver should init to "1" for aggregation mode, or "0" otherwise.
|
||||
* 7-6: Driver should init to "0"
|
||||
* 5: Window Size Left; indicates whether scheduler can request
|
||||
* another TFD, based on win size, etc. Driver should init
|
||||
* this bit to "1" for aggregation mode, or "0" for non-agg.
|
||||
* 4-1: Tx FIFO to use (range 0-7).
|
||||
* 0: Queue is active (1), not active (0).
|
||||
* Other bits should be written as "0"
|
||||
*
|
||||
* NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled
|
||||
* via SCD_QUEUECHAIN_SEL.
|
||||
*/
|
||||
#define IL49_SCD_QUEUE_STATUS_BITS(x)\
|
||||
(IL49_SCD_START_OFFSET + 0x104 + (x) * 4)
|
||||
|
||||
/* Bit field positions */
|
||||
#define IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE (0)
|
||||
#define IL49_SCD_QUEUE_STTS_REG_POS_TXF (1)
|
||||
#define IL49_SCD_QUEUE_STTS_REG_POS_WSL (5)
|
||||
#define IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK (8)
|
||||
|
||||
/* Write masks */
|
||||
#define IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10)
|
||||
#define IL49_SCD_QUEUE_STTS_REG_MSK (0x0007FC00)
|
||||
|
||||
/**
|
||||
* 4965 internal SRAM structures for scheduler, shared with driver ...
|
||||
*
|
||||
* Driver should clear and initialize the following areas after receiving
|
||||
* "Alive" response from 4965 uCode, i.e. after initial
|
||||
* uCode load, or after a uCode load done for error recovery:
|
||||
*
|
||||
* SCD_CONTEXT_DATA_OFFSET (size 128 bytes)
|
||||
* SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes)
|
||||
* SCD_TRANSLATE_TBL_OFFSET (size 32 bytes)
|
||||
*
|
||||
* Driver accesses SRAM via HBUS_TARG_MEM_* registers.
|
||||
* Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR.
|
||||
* All OFFSET values must be added to this base address.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Queue context. One 8-byte entry for each of 16 queues.
|
||||
*
|
||||
* Driver should clear this entire area (size 0x80) to 0 after receiving
|
||||
* "Alive" notification from uCode. Additionally, driver should init
|
||||
* each queue's entry as follows:
|
||||
*
|
||||
* LS Dword bit fields:
|
||||
* 0-06: Max Tx win size for Scheduler-ACK. Driver should init to 64.
|
||||
*
|
||||
* MS Dword bit fields:
|
||||
* 16-22: Frame limit. Driver should init to 10 (0xa).
|
||||
*
|
||||
* Driver should init all other bits to 0.
|
||||
*
|
||||
* Init must be done after driver receives "Alive" response from 4965 uCode,
|
||||
* and when setting up queue for aggregation.
|
||||
*/
|
||||
#define IL49_SCD_CONTEXT_DATA_OFFSET 0x380
|
||||
#define IL49_SCD_CONTEXT_QUEUE_OFFSET(x) \
|
||||
(IL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
|
||||
|
||||
#define IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0)
|
||||
#define IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F)
|
||||
#define IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
|
||||
#define IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
|
||||
|
||||
/*
|
||||
* Tx Status Bitmap
|
||||
*
|
||||
* Driver should clear this entire area (size 0x100) to 0 after receiving
|
||||
* "Alive" notification from uCode. Area is used only by device itself;
|
||||
* no other support (besides clearing) is required from driver.
|
||||
*/
|
||||
#define IL49_SCD_TX_STTS_BITMAP_OFFSET 0x400
|
||||
|
||||
/*
|
||||
* RAxTID to queue translation mapping.
|
||||
*
|
||||
* When queue is in Scheduler-ACK mode, frames placed in a that queue must be
|
||||
* for only one combination of receiver address (RA) and traffic ID (TID), i.e.
|
||||
* one QOS priority level destined for one station (for this wireless link,
|
||||
* not final destination). The SCD_TRANSLATE_TBL area provides 16 16-bit
|
||||
* mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK
|
||||
* mode, the device ignores the mapping value.
|
||||
*
|
||||
* Bit fields, for each 16-bit map:
|
||||
* 15-9: Reserved, set to 0
|
||||
* 8-4: Index into device's station table for recipient station
|
||||
* 3-0: Traffic ID (tid), range 0-15
|
||||
*
|
||||
* Driver should clear this entire area (size 32 bytes) to 0 after receiving
|
||||
* "Alive" notification from uCode. To update a 16-bit map value, driver
|
||||
* must read a dword-aligned value from device SRAM, replace the 16-bit map
|
||||
* value of interest, and write the dword value back into device SRAM.
|
||||
*/
|
||||
#define IL49_SCD_TRANSLATE_TBL_OFFSET 0x500
|
||||
|
||||
/* Find translation table dword to read/write for given queue */
|
||||
#define IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
|
||||
((IL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
|
||||
|
||||
#define IL_SCD_TXFIFO_POS_TID (0)
|
||||
#define IL_SCD_TXFIFO_POS_RA (4)
|
||||
#define IL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
|
||||
|
||||
/*********************** END TX SCHEDULER *************************************/
|
||||
|
||||
#endif /* __il_prph_h__ */
|
Referência em uma nova issue
Block a user