Revert "iwlwifi: split the drivers for agn and legacy devices 3945/4965"

This reverts commit aa833c4b1a.
This commit is contained in:
Wey-Yi Guy 2011-02-21 11:11:05 -08:00
parent aa833c4b1a
commit 4bc85c1324
30 changed files with 14046 additions and 61 deletions

View File

@ -274,7 +274,6 @@ source "drivers/net/wireless/b43legacy/Kconfig"
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/ipw2x00/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/iwlegacy/Kconfig"
source "drivers/net/wireless/iwmc3200wifi/Kconfig"
source "drivers/net/wireless/libertas/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig"

View File

@ -41,8 +41,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o
obj-$(CONFIG_MWL8K) += mwl8k.o
obj-$(CONFIG_IWLAGN) += iwlwifi/
obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/
obj-$(CONFIG_IWLWIFI) += iwlwifi/
obj-$(CONFIG_RT2X00) += rt2x00/
obj-$(CONFIG_P54_COMMON) += p54/

View File

@ -1,52 +1,18 @@
config IWLAGN
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) "
config IWLWIFI
tristate "Intel Wireless Wifi"
depends on PCI && MAC80211
select FW_LOADER
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGERS
select MAC80211_LEDS
---help---
Select to build the driver supporting the:
Intel Wireless WiFi Link Next-Gen AGN
This option enables support for use with the following hardware:
Intel Wireless WiFi Link 6250AGN Adapter
Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
Intel WiFi Link 1000BGN
Intel Wireless WiFi 5150AGN
Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
Intel 6005 Series Wi-Fi Adapters
Intel 6030 Series Wi-Fi Adapters
Intel Wireless WiFi Link 6150BGN 2 Adapter
Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
Intel 2000 Series Wi-Fi Adapters
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 iwlagn.
menu "Debugging Options"
depends on IWLAGN
depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlagn driver"
depends on IWLAGN
bool "Enable full debugging output in iwlagn and iwl3945 drivers"
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
@ -71,7 +37,7 @@ config IWLWIFI_DEBUG
config IWLWIFI_DEBUGFS
bool "iwlagn debugfs support"
depends on IWLAGN && MAC80211_DEBUGFS
depends on IWLWIFI && MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
@ -79,13 +45,13 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
depends on IWLAGN && IWLWIFI_DEBUG
depends on IWLWIFI && IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on IWLAGN
depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
@ -102,9 +68,57 @@ config IWLWIFI_DEVICE_TRACING
occur.
endmenu
config IWLAGN
tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
depends on IWLWIFI
---help---
Select to build the driver supporting the:
Intel Wireless WiFi Link Next-Gen AGN
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 iwlagn.
config IWL4965
bool "Intel Wireless WiFi 4965AGN"
depends on IWLAGN
---help---
This option enables support for Intel Wireless WiFi Link 4965AGN
config IWL5000
bool "Intel Wireless-N/Advanced-N/Ultimate-N WiFi Link"
depends on IWLAGN
---help---
This option enables support for use with the following hardware:
Intel Wireless WiFi Link 6250AGN Adapter
Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
Intel WiFi Link 1000BGN
Intel Wireless WiFi 5150AGN
Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
Intel 6005 Series Wi-Fi Adapters
Intel 6030 Series Wi-Fi Adapters
Intel Wireless WiFi Link 6150BGN 2 Adapter
Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
Intel 2000 Series Wi-Fi Adapters
config IWL_P2P
bool "iwlwifi experimental P2P support"
depends on IWLAGN
depends on IWL5000
help
This option enables experimental P2P support for some devices
based on microcode support. Since P2P support is still under
@ -118,3 +132,27 @@ config IWL_P2P
Say Y only if you want to experiment with P2P.
config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
depends on IWLWIFI
---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.

View File

@ -1,23 +1,36 @@
obj-$(CONFIG_IWLWIFI) += iwlcore.o
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
iwlcore-objs += iwl-scan.o iwl-led.o
iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
# If 3945 is selected only, iwl-legacy.o will be added
# to iwlcore-m above, but it needs to be built in.
iwlcore-objs += $(iwlcore-m)
CFLAGS_iwl-devtrace.o := -I$(src)
# AGN
obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o
iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
iwlagn-objs += iwl-rx.o iwl-tx.o iwl-sta.o
iwlagn-objs += iwl-scan.o iwl-led.o
iwlagn-objs += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
iwlagn-objs += iwl-5000.o
iwlagn-objs += iwl-6000.o
iwlagn-objs += iwl-1000.o
iwlagn-objs += iwl-2000.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
CFLAGS_iwl-devtrace.o := -I$(src)
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
iwlagn-$(CONFIG_IWL5000) += iwl-2000.o
# 3945
obj-$(CONFIG_IWL3945) += iwl3945.o
iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o
ccflags-y += -D__CHECK_ENDIAN__

View File

@ -0,0 +1,522 @@
/******************************************************************************
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2010 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 "iwl-3945-debugfs.h"
static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
{
int p = 0;
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
le32_to_cpu(priv->_3945.statistics.flag));
if (le32_to_cpu(priv->_3945.statistics.flag) &
UCODE_STATISTICS_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(priv->_3945.statistics.flag) &
UCODE_STATISTICS_FREQUENCY_MSK)
? "2.4 GHz" : "5.2 GHz");
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
(le32_to_cpu(priv->_3945.statistics.flag) &
UCODE_STATISTICS_NARROW_BAND_MSK)
? "enabled" : "disabled");
return p;
}
ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
ssize_t ret;
struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
struct iwl39_statistics_rx_non_phy *general, *accum_general;
struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/*
* The statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
ofdm = &priv->_3945.statistics.rx.ofdm;
cck = &priv->_3945.statistics.rx.cck;
general = &priv->_3945.statistics.rx.general;
accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
accum_cck = &priv->_3945.accum_statistics.rx.cck;
accum_general = &priv->_3945.accum_statistics.rx.general;
delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
delta_cck = &priv->_3945.delta_statistics.rx.cck;
delta_general = &priv->_3945.delta_statistics.rx.general;
max_ofdm = &priv->_3945.max_delta.rx.ofdm;
max_cck = &priv->_3945.max_delta.rx.cck;
max_general = &priv->_3945.max_delta.rx.general;
pos += iwl3945_statistics_flag(priv, 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;
}
ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
ssize_t ret;
struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/*
* The statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
tx = &priv->_3945.statistics.tx;
accum_tx = &priv->_3945.accum_statistics.tx;
delta_tx = &priv->_3945.delta_statistics.tx;
max_tx = &priv->_3945.max_delta.tx;
pos += iwl3945_statistics_flag(priv, 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;
}
ssize_t iwl3945_ucode_general_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
ssize_t ret;
struct iwl39_statistics_general *general, *accum_general;
struct iwl39_statistics_general *delta_general, *max_general;
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/*
* The statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
general = &priv->_3945.statistics.general;
dbg = &priv->_3945.statistics.general.dbg;
div = &priv->_3945.statistics.general.div;
accum_general = &priv->_3945.accum_statistics.general;
delta_general = &priv->_3945.delta_statistics.general;
max_general = &priv->_3945.max_delta.general;
accum_dbg = &priv->_3945.accum_statistics.general.dbg;
delta_dbg = &priv->_3945.delta_statistics.general.dbg;
max_dbg = &priv->_3945.max_delta.general.dbg;
accum_div = &priv->_3945.accum_statistics.general.div;
delta_div = &priv->_3945.delta_statistics.general.div;
max_div = &priv->_3945.max_delta.general.div;
pos += iwl3945_statistics_flag(priv, 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;
}

View File

@ -0,0 +1,60 @@
/******************************************************************************
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2010 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 "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl3945_ucode_general_stats_read(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos);
#else
static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos)
{
return 0;
}
static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos)
{
return 0;
}
static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
return 0;
}
#endif

View File

@ -0,0 +1,188 @@
/******************************************************************************
*
* 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 - 2010 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 - 2010 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 __iwl_3945_fh_h__
#define __iwl_3945_fh_h__
/************************************/
/* 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_TABLE (FH39_MEM_LOWER_BOUND + 0x140)
#define FH39_TFDB_TABLE (FH39_MEM_LOWER_BOUND + 0x180)
#define FH39_RCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x400)
#define FH39_RSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x4c0)
#define FH39_TCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x500)
#define FH39_TSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x680)
/* TFDB (Transmit Frame Buffer Descriptor) */
#define FH39_TFDB(_ch, buf) (FH39_TFDB_TABLE + \
((_ch) * 2 + (buf)) * 0x28)
#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch) (FH39_TFDB_TABLE + 0x50 * (_ch))
/* CBCC channel is [0,2] */
#define FH39_CBCC(_ch) (FH39_CBCC_TABLE + (_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_TABLE + (_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_TABLE + 0x000)
#define FH39_RSSR_STATUS (FH39_RSSR_TABLE + 0x004)
/* TCSR */
#define FH39_TCSR(_ch) (FH39_TCSR_TABLE + (_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_TABLE + 0x000)
#define FH39_TSSR_MSG_CONFIG (FH39_TSSR_TABLE + 0x008)
#define FH39_TSSR_TX_STATUS (FH39_TSSR_TABLE + 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 iwl3945_tfd_tb {
__le32 addr;
__le32 len;
} __packed;
struct iwl3945_tfd {
__le32 control_flags;
struct iwl3945_tfd_tb tbs[4];
u8 __pad[28];
} __packed;
#endif /* __iwl_3945_fh_h__ */

View File

@ -0,0 +1,294 @@
/******************************************************************************
*
* 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 - 2010 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 - 2010 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.
*
*****************************************************************************/
/*
* Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
* Please use iwl-commands.h for uCode API definitions.
* Please use iwl-3945.h for driver implementation definitions.
*/
#ifndef __iwl_3945_hw__
#define __iwl_3945_hw__
#include "iwl-eeprom.h"
/* RSSI to dBm */
#define IWL39_RSSI_OFFSET 95
#define IWL_DEFAULT_TX_POWER 0x0F
/*
* 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 index.
* 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 iwl3945_eeprom_txpower_sample {
u8 gain_index; /* index 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 indexes.
* 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 iwl3945_eeprom_txpower_group {
struct iwl3945_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 iwl3945_eeprom_temperature_corr {
u32 Ta;
u32 Tb;
u32 Tc;
u32 Td;
u32 Te;
} __packed;
/*
* EEPROM map
*/
struct iwl3945_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 or 4965 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. HT40 (40 MHz)
* channels (only for 4965, not supported by 3945) appear later in the EEPROM.
*
* 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 iwl_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 iwl_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 iwl_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 iwl_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 iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
u8 reserved9[194];
/*
* 3945 Txpower calibration data.
*/
#define IWL_NUM_TX_CALIB_GROUPS 5
struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
/* abs.ofs: 512 */
struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
u8 reserved16[172]; /* fill out to full 1024 byte block */
} __packed;
#define IWL3945_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 IWL39_NUM_QUEUES 5
#define IWL39_CMD_QUEUE_NUM 4
#define IWL_DEFAULT_TX_RETRY 15
/*********************************************/
#define RFD_SIZE 4
#define NUM_TFD_CHUNKS 4
#define RX_QUEUE_SIZE 256
#define RX_QUEUE_MASK 255
#define RX_QUEUE_SIZE_LOG 8
#define U32_PAD(n) ((4-(n))&0x3)
#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 IWL39_RTC_INST_LOWER_BOUND (0x000000)
#define IWL39_RTC_INST_UPPER_BOUND (0x014000)
#define IWL39_RTC_DATA_LOWER_BOUND (0x800000)
#define IWL39_RTC_DATA_UPPER_BOUND (0x808000)
#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
IWL39_RTC_INST_LOWER_BOUND)
#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
IWL39_RTC_DATA_LOWER_BOUND)
#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
/* Size of uCode instruction memory in bootstrap state machine */
#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
(addr < IWL39_RTC_DATA_UPPER_BOUND);
}
/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
* and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
struct iwl3945_shared {
__le32 tx_base_ptr[8];
} __packed;
static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
{
return le16_to_cpu(rate_n_flags) & 0xFF;
}
static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
{
return le16_to_cpu(rate_n_flags);
}
static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
{
return cpu_to_le16((u16)rate|flags);
}
#endif

View File

@ -0,0 +1,64 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2010 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/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
#include "iwl-commands.h"
#include "iwl-3945.h"
#include "iwl-core.h"
#include "iwl-dev.h"
#include "iwl-3945-led.h"
/* Send led command */
static int iwl3945_send_led_cmd(struct iwl_priv *priv,
struct iwl_led_cmd *led_cmd)
{
struct iwl_host_cmd cmd = {
.id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd),
.data = led_cmd,
.flags = CMD_ASYNC,
.callback = NULL,
};
return iwl_send_cmd(priv, &cmd);
}
const struct iwl_led_ops iwl3945_led_ops = {
.cmd = iwl3945_send_led_cmd,
};

View File

@ -0,0 +1,32 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2010 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 __iwl_3945_led_h__
#define __iwl_3945_led_h__
extern const struct iwl_led_ops iwl3945_led_ops;
#endif /* __iwl_3945_led_h__ */

View File

@ -0,0 +1,995 @@
/******************************************************************************
*
* Copyright(c) 2005 - 2010 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/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include "iwl-commands.h"
#include "iwl-3945.h"
#include "iwl-sta.h"
#define RS_NAME "iwl-3945-rs"
static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
};
static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
};
static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
};
static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
};
struct iwl3945_tpt_entry {
s8 min_rssi;
u8 index;
};
static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
{-60, IWL_RATE_54M_INDEX},
{-64, IWL_RATE_48M_INDEX},
{-72, IWL_RATE_36M_INDEX},
{-80, IWL_RATE_24M_INDEX},
{-84, IWL_RATE_18M_INDEX},
{-85, IWL_RATE_12M_INDEX},
{-87, IWL_RATE_9M_INDEX},
{-89, IWL_RATE_6M_INDEX}
};
static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
{-60, IWL_RATE_54M_INDEX},
{-64, IWL_RATE_48M_INDEX},
{-68, IWL_RATE_36M_INDEX},
{-80, IWL_RATE_24M_INDEX},
{-84, IWL_RATE_18M_INDEX},
{-85, IWL_RATE_12M_INDEX},
{-86, IWL_RATE_11M_INDEX},
{-88, IWL_RATE_5M_INDEX},
{-90, IWL_RATE_2M_INDEX},
{-92, IWL_RATE_1M_INDEX}
};
#define IWL_RATE_MAX_WINDOW 62
#define IWL_RATE_FLUSH (3*HZ)
#define IWL_RATE_WIN_FLUSH (HZ/2)
#define IWL39_RATE_HIGH_TH 11520
#define IWL_SUCCESS_UP_TH 8960
#define IWL_SUCCESS_DOWN_TH 10880
#define IWL_RATE_MIN_FAILURE_TH 6
#define IWL_RATE_MIN_SUCCESS_TH 8
#define IWL_RATE_DECREASE_TH 1920
#define IWL_RATE_RETRY_TH 15
static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
{
u32 index = 0;
u32 table_size = 0;
struct iwl3945_tpt_entry *tpt_table = NULL;
if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
rssi = IWL_MIN_RSSI_VAL;
switch (band) {
case IEEE80211_BAND_2GHZ:
tpt_table = iwl3945_tpt_table_g;
table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
break;
case IEEE80211_BAND_5GHZ:
tpt_table = iwl3945_tpt_table_a;
table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
break;
default:
BUG();
break;
}
while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
index++;
index = min(index, (table_size - 1));
return tpt_table[index].index;
}
static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
{
window->data = 0;
window->success_counter = 0;
window->success_ratio = -1;
window->counter = 0;
window->average_tpt = IWL_INVALID_VALUE;
window->stamp = 0;
}
/**
* iwl3945_rate_scale_flush_windows - flush out the rate scale windows
*
* Returns the number of windows that have gathered data but were
* not flushed. If there were any that were not flushed, then
* reschedule the rate flushing routine.
*/
static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
{
int unflushed = 0;
int i;
unsigned long flags;
struct iwl_priv *priv __maybe_unused = rs_sta->priv;
/*
* For each rate, if we have collected data on that rate
* and it has been more than IWL_RATE_WIN_FLUSH
* since we flushed, clear out the gathered statistics
*/
for (i = 0; i < IWL_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 +
IWL_RATE_WIN_FLUSH)) {
IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
"index %d\n",
rs_sta->win[i].counter, i);
iwl3945_clear_window(&rs_sta->win[i]);
} else
unflushed++;
spin_unlock_irqrestore(&rs_sta->lock, flags);
}
return unflushed;
}
#define IWL_RATE_FLUSH_MAX 5000 /* msec */
#define IWL_RATE_FLUSH_MIN 50 /* msec */
#define IWL_AVERAGE_PACKETS 1500
static void iwl3945_bg_rate_scale_flush(unsigned long data)
{
struct iwl3945_rs_sta *rs_sta = (void *)data;
struct iwl_priv *priv __maybe_unused = rs_sta->priv;
int unflushed = 0;
unsigned long flags;
u32 packet_count, duration, pps;
IWL_DEBUG_RATE(priv, "enter\n");
unflushed = iwl3945_rate_scale_flush_windows(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);
IWL_DEBUG_RATE(priv, "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 = (IWL_AVERAGE_PACKETS * 1000) / pps;
if (duration < IWL_RATE_FLUSH_MIN)
duration = IWL_RATE_FLUSH_MIN;
else if (duration > IWL_RATE_FLUSH_MAX)
duration = IWL_RATE_FLUSH_MAX;
} else
duration = IWL_RATE_FLUSH_MAX;
rs_sta->flush_time = msecs_to_jiffies(duration);
IWL_DEBUG_RATE(priv, "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 = IWL_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);
IWL_DEBUG_RATE(priv, "leave\n");
}
/**
* iwl3945_collect_tx_data - Update the success/failure sliding window
*
* We keep a sliding window of the last 64 packets transmitted
* at this rate. window->data contains the bitmask of successful
* packets.
*/
static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
struct iwl3945_rate_scale_data *window,
int success, int retries, int index)
{
unsigned long flags;
s32 fail_count;
struct iwl_priv *priv __maybe_unused = rs_sta->priv;
if (!retries) {
IWL_DEBUG_RATE(priv, "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 window; anything older isn't really relevant any more.
* If we have filled up the sliding window, 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 (window->counter >= IWL_RATE_MAX_WINDOW) {
/* remove earliest */
window->counter = IWL_RATE_MAX_WINDOW - 1;
if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
window->success_counter--;
}
}
/* Increment frames-attempted counter */
window->counter++;
/* Shift bitmap by one frame (throw away oldest history),
* OR in "1", and increment "success" if this
* frame was successful. */
window->data <<= 1;
if (success > 0) {
window->success_counter++;
window->data |= 0x1;
success--;
}
retries--;
}
/* Calculate current success ratio, avoid divide-by-0! */
if (window->counter > 0)
window->success_ratio = 128 * (100 * window->success_counter)
/ window->counter;
else
window->success_ratio = IWL_INVALID_VALUE;
fail_count = window->counter - window->success_counter;
/* Calculate average throughput, if we have enough history. */
if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
(window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
window->average_tpt = ((window->success_ratio *
rs_sta->expected_tpt[index] + 64) / 128);
else
window->average_tpt = IWL_INVALID_VALUE;
/* Tag this window as having been updated */
window->stamp = jiffies;
spin_unlock_irqrestore(&rs_sta->lock, flags);
}
/*
* Called after adding a new station to initialize rate scaling
*/
void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
{
struct ieee80211_hw *hw = priv->hw;
struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl3945_sta_priv *psta;
struct iwl3945_rs_sta *rs_sta;
struct ieee80211_supported_band *sband;
int i;
IWL_DEBUG_INFO(priv, "enter\n");
if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
goto out;
psta = (struct iwl3945_sta_priv *) sta->drv_priv;
rs_sta = &psta->rs_sta;
sband = hw->wiphy->bands[conf->channel->band];
rs_sta->priv = priv;
rs_sta->start_rate = IWL_RATE_INVALID;
/* default to just 802.11b */
rs_sta->expected_tpt = iwl3945_expected_tpt_b;
rs_sta->last_partial_flush = jiffies;
rs_sta->last_flush = jiffies;
rs_sta->flush_time = IWL_RATE_FLUSH;
rs_sta->last_tx_packets = 0;
rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
for (i = 0; i < IWL_RATE_COUNT_3945; i++)
iwl3945_clear_window(&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;
}
}
priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (sband->band == IEEE80211_BAND_5GHZ) {
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
IWL_FIRST_OFDM_RATE;
}
out:
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
IWL_DEBUG_INFO(priv, "leave\n");
}
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
return hw->priv;
}
/* rate scale requires free function to be implemented */
static void rs_free(void *priv)
{
return;
}
static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
struct iwl_priv *priv __maybe_unused = iwl_priv;
IWL_DEBUG_RATE(priv, "enter\n");
rs_sta = &psta->rs_sta;
spin_lock_init(&rs_sta->lock);
init_timer(&rs_sta->rate_scale_flush);
IWL_DEBUG_RATE(priv, "leave\n");
return rs_sta;
}
static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
void *priv_sta)
{
struct iwl3945_rs_sta *rs_sta = priv_sta;
/*
* Be careful not to use any members of iwl3945_rs_sta (like trying
* to use iwl_priv to print out debugging) since it may not be fully
* initialized at this point.
*/
del_timer_sync(&rs_sta->rate_scale_flush);
}
/**
* rs_tx_status - Update rate control values based on Tx results
*
* NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
* the hardware for each rate.
*/
static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
s8 retries = 0, current_count;
int scale_rate_index, first_index, last_index;
unsigned long flags;
struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE(priv, "enter\n");
retries = info->status.rates[0].count;
/* Sanity Check for retries */
if (retries > IWL_RATE_RETRY_TH)
retries = IWL_RATE_RETRY_TH;
first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
return;
}
if (!priv_sta) {
IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
return;
}
/* Treat uninitialized rate scaling data same as non-existing. */
if (!rs_sta->priv) {
IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
return;
}
rs_sta->tx_packets++;
scale_rate_index = first_index;
last_index = first_index;
/*
* Update the window 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
* priv value 'retry_rate' vs. rate specific
*
* On exit from this while loop last_index indicates the rate
* at which the frame was finally transmitted (or failed if no
* ACK)
*/
while (retries > 1) {
if ((retries - 1) < priv->retry_rate) {
current_count = (retries - 1);
last_index = scale_rate_index;
} else {
current_count = priv->retry_rate;
last_index = iwl3945_rs_next_rate(priv,
scale_rate_index);
}
/* Update this rate accounting for as many retries
* as was used for it (per current_count) */
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[scale_rate_index],
0, current_count, scale_rate_index);
IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
scale_rate_index, current_count);
retries -= current_count;
scale_rate_index = last_index;
}
/* Update the last index window with success/failure based on ACK */
IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
last_index,
(info->flags & IEEE80211_TX_STAT_ACK) ?
"success" : "failure");
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[last_index],
info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
/* We updated the rate scale window -- 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);
IWL_DEBUG_RATE(priv, "leave\n");
}
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
u8 index, u16 rate_mask, enum ieee80211_band band)
{
u8 high = IWL_RATE_INVALID;
u8 low = IWL_RATE_INVALID;
struct iwl_priv *priv __maybe_unused = rs_sta->priv;
/* 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 = index - 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 = index + 1;
for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
i++, mask <<= 1) {
if (rate_mask & mask) {
high = i;
break;
}
}
return (high << 8) | low;
}
low = index;
while (low != IWL_RATE_INVALID) {
if (rs_sta->tgg)
low = iwl3945_rates[low].prev_rs_tgg;
else
low = iwl3945_rates[low].prev_rs;
if (low == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << low))
break;
IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
}
high = index;
while (high != IWL_RATE_INVALID) {
if (rs_sta->tgg)
high = iwl3945_rates[high].next_rs_tgg;
else
high = iwl3945_rates[high].next_rs;
if (high == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << high))
break;
IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
}
return (high << 8) | low;
}
/**
* 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 index obtained below into the hw_mode's
* rate table and must reference the driver allocated rate table
*
*/
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
struct ieee80211_supported_band *sband = txrc->sband;
struct sk_buff *skb = txrc->skb;
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
int index;
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct iwl3945_rate_scale_data *window = NULL;
int current_tpt = IWL_INVALID_VALUE;
int low_tpt = IWL_INVALID_VALUE;
int high_tpt = IWL_INVALID_VALUE;
u32 fail_count;
s8 scale_action = 0;
unsigned long flags;
u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
s8 max_rate_idx = -1;
struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE(priv, "enter\n");
/* Treat uninitialized rate scaling data same as non-existing. */
if (rs_sta && !rs_sta->priv) {
IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
priv_sta = NULL;
}
if (rate_control_send_low(sta, priv_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 += IWL_FIRST_OFDM_RATE;
if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
max_rate_idx = -1;
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
rate_mask = rate_mask << IWL_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 != IWL_RATE_INVALID) {
if (rs_sta->start_rate < index &&
(rate_mask & (1 << rs_sta->start_rate)))
index = rs_sta->start_rate;
rs_sta->start_rate = IWL_RATE_INVALID;
}
/* force user max rate if set by user */
if ((max_rate_idx != -1) && (max_rate_idx < index)) {
if (rate_mask & (1 << max_rate_idx))
index = max_rate_idx;
}
window = &(rs_sta->win[index]);
fail_count = window->counter - window->success_counter;
if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
spin_unlock_irqrestore(&rs_sta->lock, flags);
IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
"counter: %d, success_counter: %d, "
"expected_tpt is %sNULL\n",
index,
window->counter,
window->success_counter,
rs_sta->expected_tpt ? "not " : "");
/* Can't calculate this yet; not enough history */
window->average_tpt = IWL_INVALID_VALUE;
goto out;
}
current_tpt = window->average_tpt;
high_low = iwl3945_get_adjacent_rate(rs_sta, index, 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 = IWL_RATE_INVALID;
/* Collect Measured throughputs of adjacent rates */
if (low != IWL_RATE_INVALID)
low_tpt = rs_sta->win[low].average_tpt;
if (high != IWL_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 ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
scale_action = -1;
/* No throughput measured yet for adjacent rates,
* try increase */
} else if ((low_tpt == IWL_INVALID_VALUE) &&
(high_tpt == IWL_INVALID_VALUE)) {
if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
scale_action = 1;
else if (low != IWL_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 != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) && (high_tpt < current_tpt)) {
IWL_DEBUG_RATE(priv, "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 != IWL_INVALID_VALUE) {
/* High rate has better throughput, Increase
* rate */
if (high_tpt > current_tpt &&
window->success_ratio >= IWL_RATE_INCREASE_TH)
scale_action = 1;
else {
IWL_DEBUG_RATE(priv,
"decrease rate because of high tpt\n");
scale_action = 0;
}
} else if (low_tpt != IWL_INVALID_VALUE) {
if (low_tpt > current_tpt) {
IWL_DEBUG_RATE(priv,
"decrease rate because of low tpt\n");
scale_action = -1;
} else if (window->success_ratio >= IWL_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 != IWL_RATE_INVALID) &&
((window->success_ratio > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * rs_sta->expected_tpt[low]))))
scale_action = 0;
switch (scale_action) {
case -1:
/* Decrese rate */
if (low != IWL_RATE_INVALID)
index = low;
break;
case 1:
/* Increase rate */
if (high != IWL_RATE_INVALID)
index = high;
break;
case 0:
default:
/* No change */
break;
}
IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
index, scale_action, low, high);
out:
rs_sta->last_txrate_idx = index;
if (sband->band == IEEE80211_BAND_5GHZ)
info->control.rates[0].idx = rs_sta->last_txrate_idx -
IWL_FIRST_OFDM_RATE;
else
info->control.rates[0].idx = rs_sta->last_txrate_idx;
IWL_DEBUG_RATE(priv, "leave: %d\n", index);
}
#ifdef CONFIG_MAC80211_DEBUGFS
static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t iwl3945_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 iwl3945_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 index=%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 < IWL_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 = iwl3945_sta_dbgfs_stats_table_read,
.open = iwl3945_open_file_generic,
.llseek = default_llseek,
};
static void iwl3945_add_debugfs(void *priv, void *priv_sta,
struct dentry *dir)
{
struct iwl3945_rs_sta *lq_sta = priv_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 iwl3945_remove_debugfs(void *priv, void *priv_sta)
{
struct iwl3945_rs_sta *lq_sta = priv_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 rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
}
static struct rate_control_ops rs_ops = {
.module = NULL,
.name = RS_NAME,
.tx_status = rs_tx_status,
.get_rate = rs_get_rate,
.rate_init = rs_rate_init_stub,
.alloc = rs_alloc,
.free = rs_free,
.alloc_sta = rs_alloc_sta,
.free_sta = rs_free_sta,
#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = iwl3945_add_debugfs,
.remove_sta_debugfs = iwl3945_remove_debugfs,
#endif
};
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
struct iwl_priv *priv = hw->priv;
s32 rssi = 0;
unsigned long flags;
struct iwl3945_rs_sta *rs_sta;
struct ieee80211_sta *sta;
struct iwl3945_sta_priv *psta;
IWL_DEBUG_RATE(priv, "enter\n");
rcu_read_lock();
sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
priv->stations[sta_id].sta.sta.addr);
if (!sta) {
IWL_DEBUG_RATE(priv, "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 (priv->band) {
case IEEE80211_BAND_2GHZ:
/* TODO: this always does G, not a regression */
if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
RXON_FLG_TGG_PROTECT_MSK) {
rs_sta->tgg = 1;
rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
} else
rs_sta->expected_tpt = iwl3945_expected_tpt_g;
break;
case IEEE80211_BAND_5GHZ:
rs_sta->expected_tpt = iwl3945_expected_tpt_a;
break;
case IEEE80211_NUM_BANDS:
BUG();
break;
}
spin_unlock_irqrestore(&rs_sta->lock, flags);
rssi = priv->_3945.last_rx_rssi;
if (rssi == 0)
rssi = IWL_MIN_RSSI_VAL;
IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
"%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
iwl3945_rates[rs_sta->start_rate].plcp);
rcu_read_unlock();
}
int iwl3945_rate_control_register(void)
{
return ieee80211_rate_control_register(&rs_ops);
}
void iwl3945_rate_control_unregister(void)
{
ieee80211_rate_control_unregister(&rs_ops);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,308 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2010 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
*
*****************************************************************************/
/*
* Please use this file (iwl-3945.h) for driver implementation definitions.
* Please use iwl-3945-commands.h for uCode API definitions.
* Please use iwl-3945-hw.h for hardware-related definitions.
*/
#ifndef __iwl_3945_h__
#define __iwl_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 iwl3945_hw_card_ids[];
#include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-fh.h"
#include "iwl-3945-hw.h"
#include "iwl-debug.h"
#include "iwl-power.h"
#include "iwl-dev.h"
#include "iwl-led.h"
/* Highest firmware API version supported */
#define IWL3945_UCODE_API_MAX 2
/* Lowest firmware API version supported */
#define IWL3945_UCODE_API_MIN 1
#define IWL3945_FW_PRE "iwlwifi-3945-"
#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_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 statistics 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 IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
/* Module parameters accessible from iwl-*.c */
extern struct iwl_mod_params iwl3945_mod_params;
struct iwl3945_rate_scale_data {
u64 data;
s32 success_counter;
s32 success_ratio;
s32 counter;
s32 average_tpt;
unsigned long stamp;
};
struct iwl3945_rs_sta {
spinlock_t lock;
struct iwl_priv *priv;
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 iwl3945_rate_scale_data win[IWL_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 agn!
*/
struct iwl3945_sta_priv {
struct iwl_station_priv_common common;
struct iwl3945_rs_sta rs_sta;
};
enum iwl3945_antenna {
IWL_ANTENNA_DIVERSITY,
IWL_ANTENNA_MAIN,
IWL_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 IWL_TX_FIFO_AC0 0
#define IWL_TX_FIFO_AC1 1
#define IWL_TX_FIFO_AC2 2
#define IWL_TX_FIFO_AC3 3
#define IWL_TX_FIFO_HCCA_1 5
#define IWL_TX_FIFO_HCCA_2 6
#define IWL_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 iwl3945_frame {
union {
struct ieee80211_hdr frame;
struct iwl3945_tx_beacon_cmd beacon;
u8 raw[IEEE80211_FRAME_LEN];
u8 cmd[360];
} u;
struct list_head list;
};
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
#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 IWL_SUPPORTED_RATES_IE_LEN 8
#define SCAN_INTERVAL 100
#define MAX_TID_COUNT 9
#define IWL_INVALID_RATE 0xFF
#define IWL_INVALID_VALUE -1
#define STA_PS_STATUS_WAKE 0
#define STA_PS_STATUS_SLEEP 1
struct iwl3945_ibss_seq {
u8 mac[ETH_ALEN];
u16 seq_num;
u16 frag_num;
unsigned long packet_time;
struct list_head list;
};
#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
x->u.rx_frame.stats.payload + \
x->u.rx_frame.stats.phy_count))
#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
IWL_RX_HDR(x)->payload + \
le16_to_cpu(IWL_RX_HDR(x)->len)))
#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
/******************************************************************************
*
* Functions implemented in iwl-base.c which are forward declared here
* for use by iwl-*.c
*
*****************************************************************************/
extern int iwl3945_calc_db_from_ratio(int sig_ratio);
extern void iwl3945_rx_replenish(void *data);
extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,int left);
extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
char **buf, bool display);
extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
/******************************************************************************
*
* Functions implemented in iwl-[34]*.c which are forward declared here
* for use by iwl-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 --
* iwl3945_ <-- Its part of iwlwifi (should be changed to iwl3945_)
* iwl3945_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
* iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
* iwl3945_bg_ <-- Called from work queue context
* iwl3945_mac_ <-- mac80211 callback
*
****************************************************************************/
extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len,
u8 reset, u8 pad);
extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl3945_frame *frame, u8 rate);
void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct iwl_device_cmd *cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr,
int sta_id, int tx_id);
extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl3945_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
extern void iwl3945_disable_events(struct iwl_priv *priv);
extern int iwl4965_get_temperature(const struct iwl_priv *priv);
extern void iwl3945_post_associate(struct iwl_priv *priv);
extern void iwl3945_config_ap(struct iwl_priv *priv);
extern int iwl3945_commit_rxon(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
/**
* iwl3945_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.
*/
extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
extern struct ieee80211_ops iwl3945_hw_ops;
/*
* Forward declare iwl-3945.c functions for iwl-base.c
*/
extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
extern const struct iwl_channel_info *iwl3945_get_channel_info(
const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
/* scanning */
int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
void iwl3945_post_scan(struct iwl_priv *priv);
/* rates */
extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
/* Requires full declaration of iwl_priv before including */
#include "iwl-io.h"
#endif

View File

@ -0,0 +1,792 @@
/******************************************************************************
*
* 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 - 2010 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 - 2010 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.
*
*****************************************************************************/
/*
* Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
* Use iwl-commands.h for uCode API definitions.
* Use iwl-dev.h for driver implementation definitions.
*/
#ifndef __iwl_4965_hw_h__
#define __iwl_4965_hw_h__
#include "iwl-fh.h"
/* EEPROM */
#define IWL4965_EEPROM_IMG_SIZE 1024
/*
* uCode queue management definitions ...
* The first queue used for block-ack aggregation is #7 (4965 only).
* All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
*/
#define IWL49_FIRST_AMPDU_QUEUE 7
/* Sizes and addresses for instruction and data memory (SRAM) in
* 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
#define IWL49_RTC_INST_LOWER_BOUND (0x000000)
#define IWL49_RTC_INST_UPPER_BOUND (0x018000)
#define IWL49_RTC_DATA_LOWER_BOUND (0x800000)
#define IWL49_RTC_DATA_UPPER_BOUND (0x80A000)
#define IWL49_RTC_INST_SIZE (IWL49_RTC_INST_UPPER_BOUND - \
IWL49_RTC_INST_LOWER_BOUND)
#define IWL49_RTC_DATA_SIZE (IWL49_RTC_DATA_UPPER_BOUND - \
IWL49_RTC_DATA_LOWER_BOUND)
#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
/* Size of uCode instruction memory in bootstrap state machine */
#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
(addr < IWL49_RTC_DATA_UPPER_BOUND);
}
/********************* START TEMPERATURE *************************************/
/**
* 4965 temperature calculation.
*
* The driver must calculate the device temperature before calculating
* a txpower setting (amplifier gain is temperature dependent). The
* calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
* values used for the life of the driver, and one of which (R4) is the
* real-time temperature indicator.
*
* uCode provides all 4 values to the driver via the "initialize alive"
* notification (see struct iwl4965_init_alive_resp). After the runtime uCode
* image loads, uCode updates the R4 value via statistics notifications
* (see STATISTICS_NOTIFICATION), which occur after each received beacon
* when associated, or can be requested via REPLY_STATISTICS_CMD.
*
* NOTE: uCode provides the R4 value as a 23-bit signed value. Driver
* must sign-extend to 32 bits before applying formula below.
*
* Formula:
*
* degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
*
* NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is
* an additional correction, which should be centered around 0 degrees
* Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for
* centering the 97/100 correction around 0 degrees K.
*
* Add 273 to Kelvin value to find degrees Celsius, for comparing current
* temperature with factory-measured temperatures when calculating txpower
* settings.
*/
#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
#define TEMPERATURE_CALIB_A_VAL 259
/* Limit range of calculated temperature to be between these Kelvin values */
#define IWL_TX_POWER_TEMPERATURE_MIN (263)
#define IWL_TX_POWER_TEMPERATURE_MAX (410)
#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
((t) > IWL_TX_POWER_TEMPERATURE_MAX))
/********************* END TEMPERATURE ***************************************/
/********************* START TXPOWER *****************************************/
/**
* 4965 txpower calculations rely on information from three sources:
*
* 1) EEPROM
* 2) "initialize" alive notification
* 3) statistics notifications
*
* EEPROM data consists of:
*
* 1) Regulatory information (max txpower and channel usage flags) is provided
* separately for each channel that can possibly supported by 4965.
* 40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
* (legacy) channels.
*
* See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
* for locations in EEPROM.
*
* 2) Factory txpower calibration information is provided separately for
* sub-bands of contiguous channels. 2.4GHz has just one sub-band,
* but 5 GHz has several sub-bands.
*
* In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
*
* See struct iwl4965_eeprom_calib_info (and the tree of structures
* contained within it) for format, and struct iwl4965_eeprom for
* locations in EEPROM.
*
* "Initialization alive" notification (see struct iwl4965_init_alive_resp)
* consists of:
*
* 1) Temperature calculation parameters.
*
* 2) Power supply voltage measurement.
*
* 3) Tx gain compensation to balance 2 transmitters for MIMO use.
*
* Statistics notifications deliver:
*
* 1) Current values for temperature param R4.
*/
/**
* To calculate a txpower setting for a given desired target txpower, channel,
* modulation bit rate, and transmitter chain (4965 has 2 transmitters to
* support MIMO and transmit diversity), driver must do the following:
*
* 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
* Do not exceed regulatory limit; reduce target txpower if necessary.
*
* If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
* 2 transmitters will be used simultaneously; driver must reduce the
* regulatory limit by 3 dB (half-power) for each transmitter, so the
* combined total output of the 2 transmitters is within regulatory limits.
*
*
* 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by
* backoff for this bit rate*. Do not exceed (saturation - backoff[rate]);
* reduce target txpower if necessary.
*
* Backoff values below are in 1/2 dB units (equivalent to steps in
* txpower gain tables):
*
* OFDM 6 - 36 MBit: 10 steps (5 dB)
* OFDM 48 MBit: 15 steps (7.5 dB)
* OFDM 54 MBit: 17 steps (8.5 dB)
* OFDM 60 MBit: 20 steps (10 dB)
* CCK all rates: 10 steps (5 dB)
*
* Backoff values apply to saturation txpower on a per-transmitter basis;
* when using MIMO (2 transmitters), each transmitter uses the same
* saturation level provided in EEPROM, and the same backoff values;
* no reduction (such as with regulatory txpower limits) is required.
*
* Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
* widths and 40 Mhz (.11n HT40) channel widths; there is no separate
* factory measurement for ht40 channels.
*
* The result of this step is the final target txpower. The rest of
* the steps figure out the proper settings for the device to achieve
* that target txpower.
*
*
* 3) Determine (EEPROM) calibration sub band for the target channel, by
* comparing against first and last channels in each sub band
* (see struct iwl4965_eeprom_calib_subband_info).
*
*
* 4) Linearly interpolate (EEPROM) factory calibration measurement sets,
* referencing the 2 factory-measured (sample) channels within the sub band.
*
* Interpolation is based on difference between target channel's frequency
* and the sample channels' frequencies. Since channel numbers are based
* on frequency (5 MHz between each channel number), this is equivalent
* to interpolating based on channel number differences.
*
* Note that the sample channels may or may not be the channels at the
* edges of the sub band. The target channel may be "outside" of the
* span of the sampled channels.
*
* Driver may choose the pair (for 2 Tx chains) of measurements (see
* struct iwl4965_eeprom_calib_ch_info) for which the actual measured
* txpower comes closest to the desired txpower. Usually, though,
* the middle set of measurements is closest to the regulatory limits,
* and is therefore a good choice for all txpower calculations (this
* assumes that high accuracy is needed for maximizing legal txpower,
* while lower txpower configurations do not need as much accuracy).
*
* Driver should interpolate both members of the chosen measurement pair,
* i.e. for both Tx chains (radio transmitters), unless the driver knows
* that only one of the chains will be used (e.g. only one tx antenna
* connected, but this should be unusual). The rate scaling algorithm
* switches antennas to find best performance, so both Tx chains will
* be used (although only one at a time) even for non-MIMO transmissions.
*
* Driver should interpolate factory values for temperature, gain table
* index, and actual power. The power amplifier detector values are
* not used by the driver.
*
* Sanity check: If the target channel happens to be one of the sample
* channels, the results should agree with the sample channel's
* measurements!
*
*
* 5) Find difference between desired txpower and (interpolated)
* factory-measured txpower. Using (interpolated) factory gain table index
* (shown elsewhere) as a starting point, adjust this index lower to
* increase txpower, or higher to decrease txpower, until the target
* txpower is reached. Each step in the gain table is 1/2 dB.
*
* For example, if factory measured txpower is 16 dBm, and target txpower
* is 13 dBm, add 6 steps to the factory gain index to reduce txpower
* by 3 dB.
*
*
* 6) Find difference between current device temperature and (interpolated)
* factory-measured temperature for sub-band. Factory values are in
* degrees Celsius. To calculate current temperature, see comments for
* "4965 temperature calculation".
*
* If current temperature is higher than factory temperature, driver must
* increase gain (lower gain table index), and vice verse.
*
* Temperature affects gain differently for different channels:
*
* 2.4 GHz all channels: 3.5 degrees per half-dB step
* 5 GHz channels 34-43: 4.5 degrees per half-dB step
* 5 GHz channels >= 44: 4.0 degrees per half-dB step
*
* NOTE: Temperature can increase rapidly when transmitting, especially
* with heavy traffic at high txpowers. Driver should update
* temperature calculations often under these conditions to
* maintain strong txpower in the face of rising temperature.
*
*
* 7) Find difference between current power supply voltage indicator
* (from "initialize alive") and factory-measured power supply voltage
* indicator (EEPROM).
*
* If the current voltage is higher (indicator is lower) than factory
* voltage, gain should be reduced (gain table index increased) by:
*
* (eeprom - current) / 7
*
* If the current voltage is lower (indicator is higher) than factory
* voltage, gain should be increased (gain table index decreased) by:
*
* 2 * (current - eeprom) / 7
*
* If number of index steps in either direction turns out to be > 2,
* something is wrong ... just use 0.
*
* NOTE: Voltage compensation is independent of band/channel.
*
* NOTE: "Initialize" uCode measures current voltage, which is assumed
* to be constant after this initial measurement. Voltage
* compensation for txpower (number of steps in gain table)
* may be calculated once and used until the next uCode bootload.
*
*
* 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
* adjust txpower for each transmitter chain, so txpower is balanced
* between the two chains. There are 5 pairs of tx_atten[group][chain]
* values in "initialize alive", one pair for each of 5 channel ranges:
*
* Group 0: 5 GHz channel 34-43
* Group 1: 5 GHz channel 44-70
* Group 2: 5 GHz channel 71-124
* Group 3: 5 GHz channel 125-200
* Group 4: 2.4 GHz all channels
*
* Add the tx_atten[group][chain] value to the index for the target chain.
* The values are signed, but are in pairs of 0 and a non-negative number,
* so as to reduce gain (if necessary) of the "hotter" channel. This
* avoids any need to double-check for regulatory compliance after
* this step.
*
*
* 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation
* value to the index:
*
* Hardware rev B: 9 steps (4.5 dB)
* Hardware rev C: 5 steps (2.5 dB)
*
* Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
* bits [3:2], 1 = B, 2 = C.
*
* NOTE: This compensation is in addition to any saturation backoff that
* might have been applied in an earlier step.
*
*
* 10) Select the gain table, based on band (2.4 vs 5 GHz).
*
* Limit the adjusted index to stay within the table!
*
*
* 11) Read gain table entries for DSP and radio gain, place into appropriate
* location(s) in command (struct iwl4965_txpowertable_cmd).
*/
/**
* When MIMO is used (2 transmitters operating simultaneously), driver should
* limit each transmitter to deliver a max of 3 dB below the regulatory limit
* for the device. That is, use half power for each transmitter, so total
* txpower is within regulatory limits.
*
* The value "6" represents number of steps in gain table to reduce power 3 dB.
* Each step is 1/2 dB.
*/
#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
/**
* CCK gain compensation.
*
* When calculating txpowers for CCK, after making sure that the target power
* is within regulatory and saturation limits, driver must additionally
* back off gain by adding these values to the gain table index.
*
* Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
* bits [3:2], 1 = B, 2 = C.
*/
#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
/*
* 4965 power supply voltage compensation for txpower
*/
#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V (7)
/**
* Gain tables.
*
* The following tables contain pair of values for setting txpower, i.e.
* gain settings for the output of the device's digital signal processor (DSP),
* and for the analog gain structure of the transmitter.
*
* Each entry in the gain tables represents a step of 1/2 dB. Note that these
* are *relative* steps, not indications of absolute output power. Output
* power varies with temperature, voltage, and channel frequency, and also
* requires consideration of average power (to satisfy regulatory constraints),
* and peak power (to avoid distortion of the output signal).
*
* Each entry contains two values:
* 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained
* linear value that multiplies the output of the digital signal processor,
* before being sent to the analog radio.
* 2) Radio gain. This sets the analog gain of the radio Tx path.
* It is a coarser setting, and behaves in a logarithmic (dB) fashion.
*
* EEPROM contains factory calibration data for txpower. This maps actual
* measured txpower levels to gain settings in the "well known" tables
* below ("well-known" means here that both factory calibration *and* the
* driver work with the same table).
*
* There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table
* has an extension (into negative indexes), in case the driver needs to
* boost power setting for high device temperatures (higher than would be
* present during factory calibration). A 5 Ghz EEPROM index of "40"
* corresponds to the 49th entry in the table used by the driver.
*/
#define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */
#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */
/**
* 2.4 GHz gain table
*
* Index Dsp gain Radio gain
* 0 110 0x3f (highest gain)
* 1 104 0x3f
* 2 98 0x3f
* 3 110 0x3e
* 4 104 0x3e
* 5 98 0x3e
* 6 110 0x3d
* 7 104 0x3d
* 8 98 0x3d
* 9 110 0x3c
* 10 104 0x3c
* 11 98 0x3c
* 12 110 0x3b
* 13 104 0x3b
* 14 98 0x3b
* 15 110 0x3a
* 16 104 0x3a
* 17 98 0x3a
* 18 110 0x39
* 19 104 0x39
* 20 98 0x39
* 21 110 0x38
* 22 104 0x38
* 23 98 0x38
* 24 110 0x37
* 25 104 0x37
* 26 98 0x37
* 27 110 0x36
* 28 104 0x36
* 29 98 0x36
* 30 110 0x35
* 31 104 0x35
* 32 98 0x35
* 33 110 0x34
* 34 104 0x34
* 35 98 0x34
* 36 110 0x33
* 37 104 0x33
* 38 98 0x33
* 39 110 0x32
* 40 104 0x32
* 41 98 0x32
* 42 110 0x31
* 43 104 0x31
* 44 98 0x31
* 45 110 0x30
* 46 104 0x30
* 47 98 0x30
* 48 110 0x6
* 49 104 0x6
* 50 98 0x6
* 51 110 0x5
* 52 104 0x5
* 53 98 0x5
* 54 110 0x4
* 55 104 0x4
* 56 98 0x4
* 57 110 0x3
* 58 104 0x3
* 59 98 0x3
* 60 110 0x2
* 61 104 0x2
* 62 98 0x2
* 63 110 0x1
* 64 104 0x1
* 65 98 0x1
* 66 110 0x0
* 67 104 0x0
* 68 98 0x0
* 69 97 0
* 70 96 0
* 71 95 0
* 72 94 0
* 73 93 0
* 74 92 0
* 75 91 0
* 76 90 0
* 77 89 0
* 78 88 0
* 79 87 0
* 80 86 0
* 81 85 0
* 82 84 0
* 83 83 0
* 84 82 0
* 85 81 0
* 86 80 0
* 87 79 0
* 88 78 0
* 89 77 0
* 90 76 0
* 91 75 0
* 92 74 0
* 93 73 0
* 94 72 0
* 95 71 0
* 96 70 0
* 97 69 0
* 98 68 0
*/
/**
* 5 GHz gain table
*
* Index Dsp gain Radio gain
* -9 123 0x3F (highest gain)
* -8 117 0x3F
* -7 110 0x3F
* -6 104 0x3F
* -5 98 0x3F
* -4 110 0x3E
* -3 104 0x3E
* -2 98 0x3E
* -1 110 0x3D
* 0 104 0x3D
* 1 98 0x3D
* 2 110 0x3C
* 3 104 0x3C
* 4 98 0x3C
* 5 110 0x3B
* 6 104 0x3B
* 7 98 0x3B
* 8 110 0x3A
* 9 104 0x3A
* 10 98 0x3A
* 11 110 0x39
* 12 104 0x39
* 13 98 0x39
* 14 110 0x38
* 15 104 0x38
* 16 98 0x38
* 17 110 0x37
* 18 104 0x37
* 19 98 0x37
* 20 110 0x36
* 21 104 0x36
* 22 98 0x36
* 23 110 0x35
* 24 104 0x35
* 25 98 0x35
* 26 110 0x34
* 27 104 0x34
* 28 98 0x34
* 29 110 0x33
* 30 104 0x33
* 31 98 0x33
* 32 110 0x32
* 33 104 0x32
* 34 98 0x32
* 35 110 0x31
* 36 104 0x31
* 37 98 0x31
* 38 110 0x30
* 39 104 0x30
* 40 98 0x30
* 41 110 0x25
* 42 104 0x25
* 43 98 0x25
* 44 110 0x24
* 45 104 0x24
* 46 98 0x24
* 47 110 0x23
* 48 104 0x23
* 49 98 0x23
* 50 110 0x22
* 51 104 0x18
* 52 98 0x18
* 53 110 0x17
* 54 104 0x17
* 55 98 0x17
* 56 110 0x16
* 57 104 0x16
* 58 98 0x16
* 59 110 0x15
* 60 104 0x15
* 61 98 0x15
* 62 110 0x14
* 63 104 0x14
* 64 98 0x14
* 65 110 0x13
* 66 104 0x13
* 67 98 0x13
* 68 110 0x12
* 69 104 0x08
* 70 98 0x08
* 71 110 0x07
* 72 104 0x07
* 73 98 0x07
* 74 110 0x06
* 75 104 0x06
* 76 98 0x06
* 77 110 0x05
* 78 104 0x05
* 79 98 0x05
* 80 110 0x04
* 81 104 0x04
* 82 98 0x04
* 83 110 0x03
* 84 104 0x03
* 85 98 0x03
* 86 110 0x02
* 87 104 0x02
* 88 98 0x02
* 89 110 0x01
* 90 104 0x01
* 91 98 0x01
* 92 110 0x00
* 93 104 0x00
* 94 98 0x00
* 95 93 0x00
* 96 88 0x00
* 97 83 0x00
* 98 78 0x00
*/
/**
* Sanity checks and default values for EEPROM regulatory levels.
* If EEPROM values fall outside MIN/MAX range, use default values.
*
* Regulatory limits refer to the maximum average txpower allowed by
* regulatory agencies in the geographies in which the device is meant
* to be operated. These limits are SKU-specific (i.e. geography-specific),
* and channel-specific; each channel has an individual regulatory limit
* listed in the EEPROM.
*
* Units are in half-dBm (i.e. "34" means 17 dBm).
*/
#define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34)
#define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34)
#define IWL_TX_POWER_REGULATORY_MIN (0)
#define IWL_TX_POWER_REGULATORY_MAX (34)
/**
* Sanity checks and default values for EEPROM saturation levels.
* If EEPROM values fall outside MIN/MAX range, use default values.
*
* Saturation is the highest level that the output power amplifier can produce
* without significant clipping distortion. This is a "peak" power level.
* Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
* require differing amounts of backoff, relative to their average power output,
* in order to avoid clipping distortion.
*
* Driver must make sure that it is violating neither the saturation limit,
* nor the regulatory limit, when calculating Tx power settings for various
* rates.
*
* Units are in half-dBm (i.e. "38" means 19 dBm).
*/
#define IWL_TX_POWER_DEFAULT_SATURATION_24 (38)
#define IWL_TX_POWER_DEFAULT_SATURATION_52 (38)
#define IWL_TX_POWER_SATURATION_MIN (20)
#define IWL_TX_POWER_SATURATION_MAX (50)
/**
* Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
* and thermal Txpower calibration.
*
* When calculating txpower, driver must compensate for current device
* temperature; higher temperature requires higher gain. Driver must calculate
* current temperature (see "4965 temperature calculation"), then compare vs.
* factory calibration temperature in EEPROM; if current temperature is higher
* than factory temperature, driver must *increase* gain by proportions shown
* in table below. If current temperature is lower than factory, driver must
* *decrease* gain.
*
* Different frequency ranges require different compensation, as shown below.
*/
/* Group 0, 5.2 GHz ch 34-43: 4.5 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
/* Group 1, 5.3 GHz ch 44-70: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
/* Group 2, 5.5 GHz ch 71-124: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
/* Group 3, 5.7 GHz ch 125-200: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
/* Group 4, 2.4 GHz all channels: 3.5 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
enum {
CALIB_CH_GROUP_1 = 0,
CALIB_CH_GROUP_2 = 1,
CALIB_CH_GROUP_3 = 2,
CALIB_CH_GROUP_4 = 3,
CALIB_CH_GROUP_5 = 4,
CALIB_CH_GROUP_MAX
};
/********************* END TXPOWER *****************************************/
/**
* Tx/Rx Queues
*
* Most communication between driver and 4965 is via queues of data buffers.
* For example, all commands that the driver issues to device's embedded
* controller (uCode) are via the command queue (one of the Tx queues). All
* uCode command responses/replies/notifications, including Rx frames, are
* conveyed from uCode to driver via the Rx queue.
*
* Most support for these queues, including handshake support, resides in
* structures in host DRAM, shared between the driver and the device. When
* allocating this memory, the driver must make sure that data written by
* the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
* cache memory), so DRAM and cache are consistent, and the device can
* immediately see changes made by the driver.
*
* 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
* up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array
* in DRAM containing 256 Transmit Frame Descriptors (TFDs).
*/
#define IWL49_NUM_FIFOS 7
#define IWL49_CMD_FIFO_NUM 4
#define IWL49_NUM_QUEUES 16
#define IWL49_NUM_AMPDU_QUEUES 8
/**
* struct iwl4965_schedq_bc_tbl
*
* Byte Count table
*
* Each Tx queue uses a byte-count table containing 320 entries:
* one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
* duplicate the first 64 entries (to avoid wrap-around within a Tx window;
* max Tx window is 64 TFDs).
*
* When driver sets up a new TFD, it must also enter the total byte count
* of the frame to be transmitted into the corresponding entry in the byte
* count table for the chosen Tx queue. If the TFD index is 0-63, the driver
* must duplicate the byte count entry in corresponding index 256-319.
*
* padding puts each byte count table on a 1024-byte boundary;
* 4965 assumes tables are separated by 1024 bytes.
*/
struct iwl4965_scd_bc_tbl {
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
} __packed;
#endif /* !__iwl_4965_hw_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -86,6 +86,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("iwl4965");
static int iwlagn_ant_coupling;
static bool iwlagn_bt_ch_announce = 1;
@ -3809,6 +3810,7 @@ static void iwlagn_bg_roc_done(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
#ifdef CONFIG_IWL5000
static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
@ -3864,6 +3866,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
return 0;
}
#endif
/*****************************************************************************
*
@ -4033,6 +4036,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
kfree(priv->scan_cmd);
}
#ifdef CONFIG_IWL5000
struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx,
.start = iwlagn_mac_start,
@ -4057,6 +4061,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.remain_on_channel = iwl_mac_remain_on_channel,
.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
};
#endif
static void iwl_hw_detect(struct iwl_priv *priv)
{
@ -4124,7 +4129,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (cfg->mod_params->disable_hw_scan) {
dev_printk(KERN_DEBUG, &(pdev->dev),
"sw scan support is deprecated\n");
#ifdef CONFIG_IWL5000
iwlagn_hw_ops.hw_scan = NULL;
#endif
#ifdef CONFIG_IWL4965
iwl4965_hw_ops.hw_scan = NULL;
#endif
}
hw = iwl_alloc_all(cfg);
@ -4503,6 +4513,12 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
/* Hardware specific file defines the PCI IDs table for that hardware module */
static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
#ifdef CONFIG_IWL4965
{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
#endif /* CONFIG_IWL4965 */
#ifdef CONFIG_IWL5000
/* 5100 Series WiFi */
{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
@ -4688,6 +4704,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)},
{IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)},
#endif /* CONFIG_IWL5000 */
{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);

View File

@ -43,6 +43,11 @@
#include "iwl-helpers.h"
MODULE_DESCRIPTION("iwl core");
MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
/*
* set bt_coex_active to true, uCode will do kill/defer
* every time the priority line is asserted (BT is sending signals on the
@ -60,12 +65,15 @@
* default: bt_coex_active = true (BT_COEX_ENABLE)
*/
bool bt_coex_active = true;
EXPORT_SYMBOL_GPL(bt_coex_active);
module_param(bt_coex_active, bool, S_IRUGO);
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
u32 iwl_debug_level;
EXPORT_SYMBOL(iwl_debug_level);
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(iwl_bcast_addr);
/* This function both allocates and initializes hw and priv. */
@ -90,6 +98,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
out:
return hw;
}
EXPORT_SYMBOL(iwl_alloc_all);
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
@ -263,6 +272,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
return 0;
}
EXPORT_SYMBOL(iwlcore_init_geos);
/*
* iwlcore_free_geos - undo allocations in iwlcore_init_geos
@ -273,6 +283,7 @@ void iwlcore_free_geos(struct iwl_priv *priv)
kfree(priv->ieee_rates);
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}
EXPORT_SYMBOL(iwlcore_free_geos);
static bool iwl_is_channel_extension(struct iwl_priv *priv,
enum ieee80211_band band,
@ -317,6 +328,7 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
le16_to_cpu(ctx->staging.channel),
ctx->ht.extension_chan_offset);
}
EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
@ -417,6 +429,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
sizeof(ctx->timing), &ctx->timing);
}
EXPORT_SYMBOL(iwl_send_rxon_timing);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
int hw_decrypt)
@ -429,6 +442,7 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
}
EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
/* validate RXON structure is valid */
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
@ -501,6 +515,7 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
}
return 0;
}
EXPORT_SYMBOL(iwl_check_rxon_cmd);
/**
* iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
@ -564,6 +579,7 @@ int iwl_full_rxon_required(struct iwl_priv *priv,
return 0;
}
EXPORT_SYMBOL(iwl_full_rxon_required);
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
@ -577,6 +593,7 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
else
return IWL_RATE_6M_PLCP;
}
EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
struct iwl_ht_config *ht_conf,
@ -653,6 +670,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
for_each_context(priv, ctx)
_iwl_set_rxon_ht(priv, ht_conf, ctx);
}
EXPORT_SYMBOL(iwl_set_rxon_ht);
/* Return valid, unused, channel for a passive scan to reset the RF */
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
@ -693,6 +711,7 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv,
return channel;
}
EXPORT_SYMBOL(iwl_get_single_channel_number);
/**
* iwl_set_rxon_channel - Set the band and channel values in staging RXON
@ -723,6 +742,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
return 0;
}
EXPORT_SYMBOL(iwl_set_rxon_channel);
void iwl_set_flags_for_band(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
@ -746,6 +766,7 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
}
}
EXPORT_SYMBOL(iwl_set_flags_for_band);
/*
* initialize rxon structure with default values from eeprom
@ -817,6 +838,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
}
EXPORT_SYMBOL(iwl_connection_init_rx_config);
void iwl_set_rate(struct iwl_priv *priv)
{
@ -849,6 +871,7 @@ void iwl_set_rate(struct iwl_priv *priv)
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
}
EXPORT_SYMBOL(iwl_set_rate);
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
@ -868,6 +891,7 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
mutex_unlock(&priv->mutex);
}
}
EXPORT_SYMBOL(iwl_chswitch_done);
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
@ -895,6 +919,7 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
}
}
}
EXPORT_SYMBOL(iwl_rx_csa);
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
@ -916,6 +941,7 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
EXPORT_SYMBOL(iwl_print_rx_config_cmd);
#endif
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
@ -995,6 +1021,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
}
EXPORT_SYMBOL(iwl_irq_handle_error);
static int iwl_apm_stop_master(struct iwl_priv *priv)
{
@ -1031,6 +1058,7 @@ void iwl_apm_stop(struct iwl_priv *priv)
*/
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
}
EXPORT_SYMBOL(iwl_apm_stop);
/*
@ -1145,6 +1173,7 @@ int iwl_apm_init(struct iwl_priv *priv)
out:
return ret;
}
EXPORT_SYMBOL(iwl_apm_init);
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
@ -1204,6 +1233,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
}
return ret;
}
EXPORT_SYMBOL(iwl_set_tx_power);
void iwl_send_bt_config(struct iwl_priv *priv)
{
@ -1227,6 +1257,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
EXPORT_SYMBOL(iwl_send_bt_config);
int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
{
@ -1244,6 +1275,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
}
EXPORT_SYMBOL(iwl_send_statistics_request);
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@ -1255,6 +1287,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@ -1266,6 +1299,7 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
}
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@ -1280,6 +1314,7 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info));
}
EXPORT_SYMBOL(iwl_rx_reply_error);
void iwl_clear_isr_stats(struct iwl_priv *priv)
{
@ -1331,6 +1366,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
}
EXPORT_SYMBOL(iwl_mac_conf_tx);
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
@ -1338,6 +1374,7 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
return priv->ibss_manager == IWL_IBSS_MANAGER;
}
EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
@ -1447,6 +1484,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
}
EXPORT_SYMBOL(iwl_mac_add_interface);
static void iwl_teardown_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif,
@ -1499,6 +1537,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
}
EXPORT_SYMBOL(iwl_mac_remove_interface);
int iwl_alloc_txq_mem(struct iwl_priv *priv)
{
@ -1513,12 +1552,14 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv)
}
return 0;
}
EXPORT_SYMBOL(iwl_alloc_txq_mem);
void iwl_free_txq_mem(struct iwl_priv *priv)
{
kfree(priv->txq);
priv->txq = NULL;
}
EXPORT_SYMBOL(iwl_free_txq_mem);
#ifdef CONFIG_IWLWIFI_DEBUGFS
@ -1557,6 +1598,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
iwl_reset_traffic_log(priv);
return 0;
}
EXPORT_SYMBOL(iwl_alloc_traffic_mem);
void iwl_free_traffic_mem(struct iwl_priv *priv)
{
@ -1566,6 +1608,7 @@ void iwl_free_traffic_mem(struct iwl_priv *priv)
kfree(priv->rx_traffic);
priv->rx_traffic = NULL;
}
EXPORT_SYMBOL(iwl_free_traffic_mem);
void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
u16 length, struct ieee80211_hdr *header)
@ -1590,6 +1633,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
}
}
EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
u16 length, struct ieee80211_hdr *header)
@ -1614,6 +1658,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
}
}
EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
const char *get_mgmt_string(int cmd)
{
@ -1750,6 +1795,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
stats->data_bytes += len;
}
}
EXPORT_SYMBOL(iwl_update_stats);
#endif
static void iwl_force_rf_reset(struct iwl_priv *priv)
@ -1888,6 +1934,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_unlock(&priv->mutex);
return err;
}
EXPORT_SYMBOL(iwl_mac_change_interface);
/*
* On every watchdog tick we check (latest) time stamp. If it does not
@ -1959,6 +2006,7 @@ void iwl_bg_watchdog(unsigned long data)
mod_timer(&priv->watchdog, jiffies +
msecs_to_jiffies(IWL_WD_TICK(timeout)));
}
EXPORT_SYMBOL(iwl_bg_watchdog);
void iwl_setup_watchdog(struct iwl_priv *priv)
{
@ -1970,6 +2018,7 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
else
del_timer(&priv->watchdog);
}
EXPORT_SYMBOL(iwl_setup_watchdog);
/*
* extended beacon time format
@ -1995,6 +2044,7 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
}
EXPORT_SYMBOL(iwl_usecs_to_beacons);
/* base is usually what we get from ucode with each received frame,
* the same as HW timer counter counting down
@ -2022,6 +2072,7 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
return cpu_to_le32(res);
}
EXPORT_SYMBOL(iwl_add_beacon_time);
#ifdef CONFIG_PM
@ -2041,6 +2092,7 @@ int iwl_pci_suspend(struct device *device)
return 0;
}
EXPORT_SYMBOL(iwl_pci_suspend);
int iwl_pci_resume(struct device *device)
{
@ -2069,6 +2121,7 @@ int iwl_pci_resume(struct device *device)
return 0;
}
EXPORT_SYMBOL(iwl_pci_resume);
const struct dev_pm_ops iwl_pm_ops = {
.suspend = iwl_pci_suspend,
@ -2078,5 +2131,6 @@ const struct dev_pm_ops iwl_pm_ops = {
.poweroff = iwl_pci_suspend,
.restore = iwl_pci_resume,
};
EXPORT_SYMBOL(iwl_pm_ops);
#endif /* CONFIG_PM */

View File

@ -1788,6 +1788,7 @@ err:
iwl_dbgfs_unregister(priv);
return -ENOMEM;
}
EXPORT_SYMBOL(iwl_dbgfs_register);
/**
* Remove the debugfs files and directories
@ -1801,6 +1802,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
debugfs_remove_recursive(priv->debugfs_dir);
priv->debugfs_dir = NULL;
}
EXPORT_SYMBOL(iwl_dbgfs_unregister);

View File

@ -43,14 +43,14 @@
#include "iwl-prph.h"
#include "iwl-fh.h"
#include "iwl-debug.h"
#include "iwl-4965-hw.h"
#include "iwl-3945-hw.h"
#include "iwl-agn-hw.h"
#include "iwl-led.h"
#include "iwl-power.h"
#include "iwl-agn-rs.h"
#include "iwl-agn-tt.h"
#define U32_PAD(n) ((4-(n))&0x3)
struct iwl_tx_queue;
/* CT-KILL constants */

View File

@ -222,6 +222,7 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
return &priv->eeprom[offset];
}
EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
static int iwl_init_otp_access(struct iwl_priv *priv)
{
@ -381,6 +382,7 @@ const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
{
return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
}
EXPORT_SYMBOL(iwl_eeprom_query_addr);
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
{
@ -388,6 +390,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
return 0;
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
}
EXPORT_SYMBOL(iwl_eeprom_query16);
/**
* iwl_eeprom_init - read EEPROM contents
@ -506,12 +509,14 @@ err:
alloc_err:
return ret;
}
EXPORT_SYMBOL(iwl_eeprom_init);
void iwl_eeprom_free(struct iwl_priv *priv)
{
kfree(priv->eeprom);
priv->eeprom = NULL;
}
EXPORT_SYMBOL(iwl_eeprom_free);
static void iwl_init_band_reference(const struct iwl_priv *priv,
int eep_band, int *eeprom_ch_count,
@ -774,6 +779,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
return 0;
}
EXPORT_SYMBOL(iwl_init_channel_map);
/*
* iwl_free_channel_map - undo allocations in iwl_init_channel_map
@ -783,6 +789,7 @@ void iwl_free_channel_map(struct iwl_priv *priv)
kfree(priv->channel_info);
priv->channel_count = 0;
}
EXPORT_SYMBOL(iwl_free_channel_map);
/**
* iwl_get_channel_info - Find driver's private channel info
@ -811,3 +818,4 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
return NULL;
}
EXPORT_SYMBOL(iwl_get_channel_info);

View File

@ -114,6 +114,7 @@ const char *get_cmd_string(u8 cmd)
}
}
EXPORT_SYMBOL(get_cmd_string);
#define HOST_COMPLETE_TIMEOUT (HZ / 2)
@ -252,6 +253,7 @@ out:
mutex_unlock(&priv->sync_cmd_mutex);
return ret;
}
EXPORT_SYMBOL(iwl_send_cmd_sync);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
@ -260,6 +262,7 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return iwl_send_cmd_sync(priv, cmd);
}
EXPORT_SYMBOL(iwl_send_cmd);
int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
{
@ -271,6 +274,7 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
return iwl_send_cmd_sync(priv, &cmd);
}
EXPORT_SYMBOL(iwl_send_cmd_pdu);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
u8 id, u16 len, const void *data,
@ -289,3 +293,4 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
return iwl_send_cmd_async(priv, &cmd);
}
EXPORT_SYMBOL(iwl_send_cmd_pdu_async);

View File

@ -175,6 +175,7 @@ void iwl_leds_init(struct iwl_priv *priv)
priv->led_registered = true;
}
EXPORT_SYMBOL(iwl_leds_init);
void iwl_leds_exit(struct iwl_priv *priv)
{
@ -184,3 +185,4 @@ void iwl_leds_exit(struct iwl_priv *priv)
led_classdev_unregister(&priv->led);
kfree(priv->led.name);
}
EXPORT_SYMBOL(iwl_leds_exit);

View File

@ -0,0 +1,657 @@
/******************************************************************************
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2010 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 <linux/kernel.h>
#include <net/mac80211.h>
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-helpers.h"
#include "iwl-legacy.h"
static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!ctx->is_active)
return;
ctx->qos_data.def_qos_parm.qos_flags = 0;
if (ctx->qos_data.qos_active)
ctx->qos_data.def_qos_parm.qos_flags |=
QOS_PARAM_FLG_UPDATE_EDCA_MSK;
if (ctx->ht.enabled)
ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm, NULL);
}
/**
* iwl_legacy_mac_config - mac80211 config callback
*/
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct iwl_priv *priv = hw->priv;
const struct iwl_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
struct ieee80211_channel *channel = conf->channel;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
struct iwl_rxon_context *ctx;
unsigned long flags = 0;
int ret = 0;
u16 ch;
int scan_active = 0;
bool ht_changed[NUM_IWL_RXON_CTX] = {};
if (WARN_ON(!priv->cfg->ops->legacy))
return -EOPNOTSUPP;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
channel->hw_value, changed);
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
scan_active = 1;
IWL_DEBUG_MAC80211(priv, "scan active\n");
}
if (changed & (IEEE80211_CONF_CHANGE_SMPS |
IEEE80211_CONF_CHANGE_CHANNEL)) {
/* mac80211 uses static for non-HT which is what we want */
priv->current_ht_config.smps = conf->smps_mode;
/*
* Recalculate chain counts.
*
* If monitor mode is enabled then mac80211 will
* set up the SM PS mode to OFF if an HT channel is
* configured.
*/
if (priv->cfg->ops->hcmd->set_rxon_chain)
for_each_context(priv, ctx)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
}
/* during scanning mac80211 will delay channel setting until
* scan finish with changed = 0
*/
if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
if (scan_active)
goto set_ch_out;
ch = channel->hw_value;
ch_info = iwl_get_channel_info(priv, channel->band, ch);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
ret = -EINVAL;
goto set_ch_out;
}
spin_lock_irqsave(&priv->lock, flags);
for_each_context(priv, ctx) {
/* Configure HT40 channels */
if (ctx->ht.enabled != conf_is_ht(conf)) {
ctx->ht.enabled = conf_is_ht(conf);
ht_changed[ctx->ctxid] = true;
}
if (ctx->ht.enabled) {
if (conf_is_ht40_minus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
ctx->ht.is_40mhz = true;
} else if (conf_is_ht40_plus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
ctx->ht.is_40mhz = true;
} else {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_NONE;
ctx->ht.is_40mhz = false;
}
} else
ctx->ht.is_40mhz = false;
/*
* Default to no protection. Protection mode will
* later be set from BSS config in iwl_ht_conf
*/
ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
/* if we are switching from ht to 2.4 clear flags
* from any ht related info since 2.4 does not
* support ht */
if ((le16_to_cpu(ctx->staging.channel) != ch))
ctx->staging.flags = 0;
iwl_set_rxon_channel(priv, channel, ctx);
iwl_set_rxon_ht(priv, ht_conf);
iwl_set_flags_for_band(priv, ctx, channel->band,
ctx->vif);
}
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->cfg->ops->legacy->update_bcast_stations)
ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
set_ch_out:
/* The list of supported rates and rate mask can be different
* for each band; since the band may have changed, reset
* the rate mask to what mac80211 lists */
iwl_set_rate(priv);
}
if (changed & (IEEE80211_CONF_CHANGE_PS |
IEEE80211_CONF_CHANGE_IDLE)) {
ret = iwl_power_update_mode(priv, false);
if (ret)
IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
priv->tx_power_user_lmt, conf->power_level);
iwl_set_tx_power(priv, conf->power_level, false);
}
if (!iwl_is_ready(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out;
}
if (scan_active)
goto out;
for_each_context(priv, ctx) {
if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
iwlcore_commit_rxon(priv, ctx);
else
IWL_DEBUG_INFO(priv,
"Not re-sending same RXON configuration.\n");
if (ht_changed[ctx->ctxid])
iwl_update_qos(priv, ctx);
}
out:
IWL_DEBUG_MAC80211(priv, "leave\n");
mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_legacy_mac_config);
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
/* IBSS can only be the IWL_RXON_CTX_BSS context */
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (WARN_ON(!priv->cfg->ops->legacy))
return;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
spin_lock_irqsave(&priv->lock, flags);
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
spin_unlock_irqrestore(&priv->lock, flags);
spin_lock_irqsave(&priv->lock, flags);
/* new association get rid of ibss beacon skb */
if (priv->beacon_skb)
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL;
priv->timestamp = 0;
spin_unlock_irqrestore(&priv->lock, flags);
iwl_scan_cancel_timeout(priv, 100);
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->mutex);
return;
}
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwlcore_commit_rxon(priv, ctx);
iwl_set_rate(priv);
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
static void iwl_ht_conf(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
struct ieee80211_sta *sta;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_ASSOC(priv, "enter:\n");
if (!ctx->ht.enabled)
return;
ctx->ht.protection =
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
ctx->ht.non_gf_sta_present =
!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
ht_conf->single_chain_sufficient = false;
switch (vif->type) {
case NL80211_IFTYPE_STATION:
rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (sta) {
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
int maxstreams;
maxstreams = (ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
maxstreams += 1;
if ((ht_cap->mcs.rx_mask[1] == 0) &&
(ht_cap->mcs.rx_mask[2] == 0))
ht_conf->single_chain_sufficient = true;
if (maxstreams <= 1)
ht_conf->single_chain_sufficient = true;
} else {
/*
* If at all, this can only happen through a race
* when the AP disconnects us while we're still
* setting up the connection, in that case mac80211
* will soon tell us about that.
*/
ht_conf->single_chain_sufficient = true;
}
rcu_read_unlock();
break;
case NL80211_IFTYPE_ADHOC:
ht_conf->single_chain_sufficient = true;
break;
default:
break;
}
IWL_DEBUG_ASSOC(priv, "leave\n");
}
static inline void iwl_set_no_assoc(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
/*
* inform the ucode that there is no longer an
* association and that no more packets should be
* sent
*/
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
ctx->staging.assoc_id = 0;
iwlcore_commit_rxon(priv, ctx);
}
static void iwlcore_beacon_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
__le64 timestamp;
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
if (!skb)
return;
IWL_DEBUG_MAC80211(priv, "enter\n");
lockdep_assert_held(&priv->mutex);
if (!priv->beacon_ctx) {
IWL_ERR(priv, "update beacon but no beacon context!\n");
dev_kfree_skb(skb);
return;
}
spin_lock_irqsave(&priv->lock, flags);
if (priv->beacon_skb)
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = skb;
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
priv->timestamp = le64_to_cpu(timestamp);
IWL_DEBUG_MAC80211(priv, "leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return;
}
priv->cfg->ops->legacy->post_associate(priv);
}
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
int ret;
if (WARN_ON(!priv->cfg->ops->legacy))
return;
IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
if (!iwl_is_alive(priv))
return;
mutex_lock(&priv->mutex);
if (changes & BSS_CHANGED_QOS) {
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
ctx->qos_data.qos_active = bss_conf->qos;
iwl_update_qos(priv, ctx);
spin_unlock_irqrestore(&priv->lock, flags);
}
if (changes & BSS_CHANGED_BEACON_ENABLED) {
/*
* the add_interface code must make sure we only ever
* have a single interface that could be beaconing at
* any time.
*/
if (vif->bss_conf.enable_beacon)
priv->beacon_ctx = ctx;
else
priv->beacon_ctx = NULL;
}
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = ieee80211_beacon_get(hw, vif);
}
if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
iwl_send_rxon_timing(priv, ctx);
if (changes & BSS_CHANGED_BSSID) {
IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
/*
* If there is currently a HW scan going on in the
* background then we need to cancel it else the RXON
* below/in post_associate will fail.
*/
if (iwl_scan_cancel_timeout(priv, 100)) {
IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
mutex_unlock(&priv->mutex);
return;
}
/* mac80211 only sets assoc when in STATION mode */
if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
memcpy(ctx->staging.bssid_addr,
bss_conf->bssid, ETH_ALEN);
/* currently needed in a few places */
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
} else {
ctx->staging.filter_flags &=
~RXON_FILTER_ASSOC_MSK;
}
}
/*
* This needs to be after setting the BSSID in case
* mac80211 decides to do both changes at once because
* it will invoke post_associate.
*/
if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
iwlcore_beacon_update(hw, vif);
if (changes & BSS_CHANGED_ERP_PREAMBLE) {
IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
}
if (changes & BSS_CHANGED_ERP_CTS_PROT) {
IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
else
ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
if (bss_conf->use_cts_prot)
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
else
ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
}
if (changes & BSS_CHANGED_BASIC_RATES) {
/* XXX use this information
*
* To do that, remove code from iwl_set_rate() and put something
* like this here:
*
if (A-band)
ctx->staging.ofdm_basic_rates =
bss_conf->basic_rates;
else
ctx->staging.ofdm_basic_rates =
bss_conf->basic_rates >> 4;
ctx->staging.cck_basic_rates =
bss_conf->basic_rates & 0xF;
*/
}
if (changes & BSS_CHANGED_HT) {
iwl_ht_conf(priv, vif);
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
}
if (changes & BSS_CHANGED_ASSOC) {
IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
if (bss_conf->assoc) {
priv->timestamp = bss_conf->timestamp;
if (!iwl_is_rfkill(priv))
priv->cfg->ops->legacy->post_associate(priv);
} else
iwl_set_no_assoc(priv, vif);
}
if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
changes);
ret = iwl_send_rxon_assoc(priv, ctx);
if (!ret) {
/* Sync active_rxon with latest change. */
memcpy((void *)&ctx->active,
&ctx->staging,
sizeof(struct iwl_rxon_cmd));
}
}
if (changes & BSS_CHANGED_BEACON_ENABLED) {
if (vif->bss_conf.enable_beacon) {
memcpy(ctx->staging.bssid_addr,
bss_conf->bssid, ETH_ALEN);
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
priv->cfg->ops->legacy->config_ap(priv);
} else
iwl_set_no_assoc(priv, vif);
}
if (changes & BSS_CHANGED_IBSS) {
ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
bss_conf->ibss_joined);
if (ret)
IWL_ERR(priv, "failed to %s IBSS station %pM\n",
bss_conf->ibss_joined ? "add" : "remove",
bss_conf->bssid);
}
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
irqreturn_t iwl_isr_legacy(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
unsigned long flags;
if (!priv)
return IRQ_NONE;
spin_lock_irqsave(&priv->lock, flags);
/* Disable (but don't clear!) interrupts here to avoid
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
inta = iwl_read32(priv, CSR_INT);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
* or due to sporadic interrupts thrown from our NIC. */
if (!inta && !inta_fh) {
IWL_DEBUG_ISR(priv,
"Ignore interrupt, inta == 0, inta_fh == 0\n");
goto none;
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared. It might have already raised
* an interrupt */
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
inta &= ~CSR_INT_BIT_SCD;
/* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta || inta_fh))
tasklet_schedule(&priv->irq_tasklet);
unplugged:
spin_unlock_irqrestore(&priv->lock, flags);
return IRQ_HANDLED;
none:
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if disabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
iwl_enable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return IRQ_NONE;
}
EXPORT_SYMBOL(iwl_isr_legacy);
/*
* iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
* function.
*/
void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
__le16 fc, __le32 *tx_flags)
{
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
*tx_flags |= TX_CMD_FLG_RTS_MSK;
*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
if (!ieee80211_is_mgmt(fc))
return;
switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
case cpu_to_le16(IEEE80211_STYPE_AUTH):
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
*tx_flags |= TX_CMD_FLG_CTS_MSK;
break;
}
} else if (info->control.rates[0].flags &
IEEE80211_TX_RC_USE_CTS_PROTECT) {
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
*tx_flags |= TX_CMD_FLG_CTS_MSK;
*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
}
}
EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);

View File

@ -0,0 +1,79 @@
/******************************************************************************
*
* 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 - 2010 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 - 2010 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 __iwl_legacy_h__
#define __iwl_legacy_h__
/* mac80211 handlers */
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
__le16 fc, __le32 *tx_flags);
irqreturn_t iwl_isr_legacy(int irq, void *data);
#endif /* __iwl_legacy_h__ */

View File

@ -425,6 +425,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
return ret;
}
EXPORT_SYMBOL(iwl_power_set_mode);
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
@ -433,6 +434,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
iwl_power_build_cmd(priv, &cmd);
return iwl_power_set_mode(priv, &cmd, force);
}
EXPORT_SYMBOL(iwl_power_update_mode);
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
@ -446,3 +448,4 @@ void iwl_power_initialize(struct iwl_priv *priv)
memset(&priv->power_data.sleep_cmd, 0,
sizeof(priv->power_data.sleep_cmd));
}
EXPORT_SYMBOL(iwl_power_initialize);

View File

@ -118,6 +118,7 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q)
s = 0;
return s;
}
EXPORT_SYMBOL(iwl_rx_queue_space);
/**
* iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
@ -169,6 +170,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
exit_unlock:
spin_unlock_irqrestore(&q->lock, flags);
}
EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
int iwl_rx_queue_alloc(struct iwl_priv *priv)
{
@ -209,6 +211,7 @@ err_rb:
err_bd:
return -ENOMEM;
}
EXPORT_SYMBOL(iwl_rx_queue_alloc);
void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
@ -226,6 +229,7 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
memcpy(&priv->measure_report, report, sizeof(*report));
priv->measurement_status |= MEASUREMENT_READY;
}
EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
void iwl_recover_from_statistics(struct iwl_priv *priv,
struct iwl_rx_packet *pkt)
@ -245,6 +249,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
!priv->cfg->ops->lib->check_plcp_health(priv, pkt))
iwl_force_reset(priv, IWL_RF_RESET, false);
}
EXPORT_SYMBOL(iwl_recover_from_statistics);
/*
* returns non-zero if packet should be dropped
@ -297,3 +302,4 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
}
return 0;
}
EXPORT_SYMBOL(iwl_set_decrypted_flag);

View File

@ -155,6 +155,7 @@ int iwl_scan_cancel(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->abort_scan);
return 0;
}
EXPORT_SYMBOL(iwl_scan_cancel);
/**
* iwl_scan_cancel_timeout - Cancel any currently executing HW scan
@ -179,6 +180,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
return test_bit(STATUS_SCAN_HW, &priv->status);
}
EXPORT_SYMBOL(iwl_scan_cancel_timeout);
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl_rx_reply_scan(struct iwl_priv *priv,
@ -286,6 +288,7 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
iwl_rx_scan_complete_notif;
}
EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
enum ieee80211_band band,
@ -298,6 +301,7 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
return IWL_ACTIVE_DWELL_TIME_24 +
IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
}
EXPORT_SYMBOL(iwl_get_active_dwell_time);
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
enum ieee80211_band band,
@ -329,6 +333,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
return passive;
}
EXPORT_SYMBOL(iwl_get_passive_dwell_time);
void iwl_init_scan_params(struct iwl_priv *priv)
{
@ -338,6 +343,7 @@ void iwl_init_scan_params(struct iwl_priv *priv)
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
}
EXPORT_SYMBOL(iwl_init_scan_params);
static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
struct ieee80211_vif *vif,
@ -433,6 +439,7 @@ out_unlock:
return ret;
}
EXPORT_SYMBOL(iwl_mac_hw_scan);
/*
* internal short scan, this function should only been called while associated.
@ -529,6 +536,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
return (u16)len;
}
EXPORT_SYMBOL(iwl_fill_probe_req);
static void iwl_bg_abort_scan(struct work_struct *work)
{
@ -613,6 +621,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
}
EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
{
@ -626,3 +635,4 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
mutex_unlock(&priv->mutex);
}
}
EXPORT_SYMBOL(iwl_cancel_scan_deferred_work);

View File

@ -169,6 +169,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
return ret;
}
EXPORT_SYMBOL(iwl_send_add_sta);
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
struct ieee80211_sta *sta,
@ -315,6 +316,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return sta_id;
}
EXPORT_SYMBOL_GPL(iwl_prep_station);
#define STA_WAIT_TIMEOUT (HZ/2)
@ -377,6 +379,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
*sta_id_r = sta_id;
return ret;
}
EXPORT_SYMBOL(iwl_add_station_common);
/**
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
@ -510,6 +513,7 @@ out_err:
spin_unlock_irqrestore(&priv->sta_lock, flags);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(iwl_remove_station);
/**
* iwl_clear_ucode_stations - clear ucode station table bits
@ -544,6 +548,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
if (!cleared)
IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
}
EXPORT_SYMBOL(iwl_clear_ucode_stations);
/**
* iwl_restore_stations() - Restore driver known stations to device
@ -620,6 +625,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
else
IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n");
}
EXPORT_SYMBOL(iwl_restore_stations);
void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
@ -662,6 +668,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
priv->stations[sta_id].sta.sta.addr, ret);
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
}
EXPORT_SYMBOL(iwl_reprogram_ap_sta);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
@ -673,6 +680,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
return WEP_INVALID_OFFSET;
}
EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
{
@ -692,6 +700,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
}
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl_dump_lq_cmd(struct iwl_priv *priv,
@ -801,6 +810,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
}
return ret;
}
EXPORT_SYMBOL(iwl_send_lq_cmd);
int iwl_mac_sta_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -822,3 +832,4 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_mac_sta_remove);

View File

@ -84,6 +84,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
}
txq->need_update = 0;
}
EXPORT_SYMBOL(iwl_txq_update_write_ptr);
/**
* iwl_tx_queue_free - Deallocate DMA queue.
@ -130,6 +131,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
EXPORT_SYMBOL(iwl_tx_queue_free);
/**
* iwl_cmd_queue_free - Deallocate DMA queue.
@ -191,6 +193,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
EXPORT_SYMBOL(iwl_cmd_queue_free);
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
@ -230,6 +233,7 @@ int iwl_queue_space(const struct iwl_queue *q)
s = 0;
return s;
}
EXPORT_SYMBOL(iwl_queue_space);
/**
@ -380,6 +384,7 @@ out_free_arrays:
return -ENOMEM;
}
EXPORT_SYMBOL(iwl_tx_queue_init);
void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id)
@ -399,6 +404,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
/* Tell device where to find queue */
priv->cfg->ops->lib->txq_init(priv, txq);
}
EXPORT_SYMBOL(iwl_tx_queue_reset);
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@ -635,3 +641,4 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
}
meta->flags = 0;
}
EXPORT_SYMBOL(iwl_tx_cmd_complete);

File diff suppressed because it is too large Load Diff