M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
@@ -0,0 +1,144 @@
config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
depends on PCI && MAC80211 && HAS_IOMEM
select FW_LOADER
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGERS
select MAC80211_LEDS
select IWLDVM
---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 iwlwifi.
config IWLDVM
tristate "Intel Wireless WiFi"
depends on IWLWIFI
menu "Debugging Options"
depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlwifi driver"
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
This will result in the kernel module being ~100k larger. You can
control which debug output is sent to the kernel log by setting the
value in
/sys/module/iwlwifi/parameters/debug
This entry will only exist if this option is enabled.
To set a value, simply echo an 8-byte hex value to the same file:
% echo 0x43fff > /sys/module/iwlwifi/parameters/debug
You can find the list of debug mask values in:
drivers/net/wireless/iwlwifi/iwl-debug.h
If this is your first time using this driver, you should say Y here
as the debug information can assist others in helping you resolve
any problems you may encounter.
config IWLWIFI_DEBUGFS
bool "iwlwifi debugfs support"
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
driver's state at runtime.
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
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 IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
accesses, sent to the device. If you say yes, iwlwifi will
register with the ftrace framework for event tracing and dump
all this information to the ringbuffer, you may need to
increase the ringbuffer size. See the ftrace documentation
for more information.
When tracing is not enabled, this option still has some
(though rather small) overhead.
If unsure, say Y so we can help you better when problems
occur.
endmenu
config IWLWIFI_DEVICE_TESTMODE
def_bool y
depends on IWLWIFI
depends on NL80211_TESTMODE
help
This option enables the testmode support for iwlwifi device through
NL80211_TESTMODE. This provide the capabilities of enable user space
validation applications to interacts with the device through the
generic netlink message via NL80211_TESTMODE channel.
config IWLWIFI_P2P
def_bool y
bool "iwlwifi experimental P2P support"
depends on IWLWIFI
help
This option enables experimental P2P support for some devices
based on microcode support. Since P2P support is still under
development, this option may even enable it for some devices
now that turn out to not support it in the future due to
microcode restrictions.
To determine if your microcode supports the experimental P2P
offered by this option, check if the driver advertises AP
support when it is loaded.
Say Y only if you want to experiment with P2P.
config IWLWIFI_EXPERIMENTAL_MFP
bool "support MFP (802.11w) even if uCode doesn't advertise"
depends on IWLWIFI
help
This option enables experimental MFP (802.11W) support
even if the microcode doesn't advertise it.
Say Y only if you want to experiment with MFP.
@@ -0,0 +1,19 @@
# common
obj-$(CONFIG_IWLWIFI) += iwlwifi.o
iwlwifi-objs += iwl-io.o
iwlwifi-objs += iwl-drv.o
iwlwifi-objs += iwl-debug.o
iwlwifi-objs += iwl-notif-wait.o
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
obj-$(CONFIG_IWLDVM) += dvm/
CFLAGS_iwl-devtrace.o := -I$(src)
@@ -0,0 +1,119 @@
/******************************************************************************
*
* 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) 2007 - 2012 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 - 2012 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-agn-hw.h) only for hardware-related definitions.
*/
#ifndef __iwl_agn_hw_h__
#define __iwl_agn_hw_h__
#define IWLAGN_RTC_INST_LOWER_BOUND (0x000000)
#define IWLAGN_RTC_INST_UPPER_BOUND (0x020000)
#define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000)
#define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000)
#define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \
IWLAGN_RTC_INST_LOWER_BOUND)
#define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \
IWLAGN_RTC_DATA_LOWER_BOUND)
#define IWL60_RTC_INST_LOWER_BOUND (0x000000)
#define IWL60_RTC_INST_UPPER_BOUND (0x040000)
#define IWL60_RTC_DATA_LOWER_BOUND (0x800000)
#define IWL60_RTC_DATA_UPPER_BOUND (0x814000)
#define IWL60_RTC_INST_SIZE \
(IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND)
#define IWL60_RTC_DATA_SIZE \
(IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND)
/* RSSI to dBm */
#define IWLAGN_RSSI_OFFSET 44
#define IWLAGN_DEFAULT_TX_RETRY 15
#define IWLAGN_MGMT_DFAULT_RETRY_LIMIT 3
#define IWLAGN_RTS_DFAULT_RETRY_LIMIT 60
#define IWLAGN_BAR_DFAULT_RETRY_LIMIT 60
#define IWLAGN_LOW_RETRY_LIMIT 7
/* Limit range of txpower output target to be between these values */
#define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */
#define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */
/* EEPROM */
#define IWLAGN_EEPROM_IMG_SIZE 2048
/* OTP */
/* lower blocks contain EEPROM image and calibration data */
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
/* high blocks contain PAPD data */
#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
#define OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */
#define IWLAGN_NUM_QUEUES 20
#endif /* __iwl_agn_hw_h__ */
@@ -0,0 +1,475 @@
/******************************************************************************
*
* 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 - 2012 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 - 2012 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_csr_h__
#define __iwl_csr_h__
/*
* CSR (control and status registers)
*
* CSR registers are mapped directly into PCI bus space, and are accessible
* whenever platform supplies power to device, even when device is in
* low power states due to driver-invoked device resets
* (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
*
* Use iwl_write32() and iwl_read32() family to access these registers;
* these provide simple PCI bus access, without waking up the MAC.
* Do not use iwl_write_direct32() family for these registers;
* no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
* The MAC (uCode processor, etc.) does not need to be powered up for accessing
* the CSR registers.
*
* NOTE: Device does need to be awake in order to read this memory
* via CSR_EEPROM and CSR_OTP registers
*/
#define CSR_BASE (0x000)
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
#define CSR_GP_CNTRL (CSR_BASE+0x024)
/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
/*
* Hardware revision info
* Bit fields:
* 31-16: Reserved
* 15-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions
* 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
* 1-0: "Dash" (-) value, as in A-1, etc.
*/
#define CSR_HW_REV (CSR_BASE+0x028)
/*
* EEPROM and OTP (one-time-programmable) memory reads
*
* NOTE: Device must be awake, initialized via apm_ops.init(),
* in order to read.
*/
#define CSR_EEPROM_REG (CSR_BASE+0x02c)
#define CSR_EEPROM_GP (CSR_BASE+0x030)
#define CSR_OTP_GP_REG (CSR_BASE+0x034)
#define CSR_GIO_REG (CSR_BASE+0x03C)
#define CSR_GP_UCODE_REG (CSR_BASE+0x048)
#define CSR_GP_DRIVER_REG (CSR_BASE+0x050)
/*
* UCODE-DRIVER GP (general purpose) mailbox registers.
* SET/CLR registers set/clear bit(s) if "1" is written.
*/
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
#define CSR_LED_REG (CSR_BASE+0x094)
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
/* Analog phase-lock-loop configuration */
#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
/*
* CSR Hardware Revision Workaround Register. Indicates hardware rev;
* "step" determines CCK backoff for txpower calculation. Used for 4965 only.
* See also CSR_HW_REV register.
* Bit fields:
* 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
* 1-0: "Dash" (-) value, as in C-1, etc.
*/
#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240)
#define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250)
/* Bits for CSR_HW_IF_CONFIG_REG */
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE (0x00000C00)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH (0x00003000)
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP (0x0000C000)
#define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH (0)
#define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP (2)
#define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER (6)
#define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE (10)
#define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH (12)
#define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP (14)
#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
#define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/
#define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/
/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
* acknowledged (reset) by host writing "1" to flagged bits. */
#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */
#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */
#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
CSR_INT_BIT_HW_ERR | \
CSR_INT_BIT_FH_TX | \
CSR_INT_BIT_SW_ERR | \
CSR_INT_BIT_RF_KILL | \
CSR_INT_BIT_SW_RX | \
CSR_INT_BIT_WAKEUP | \
CSR_INT_BIT_ALIVE)
/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
CSR_FH_INT_BIT_RX_CHNL1 | \
CSR_FH_INT_BIT_RX_CHNL0)
#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
CSR_FH_INT_BIT_TX_CHNL0)
/* GPIO */
#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC (0x00000200)
/* RESET */
#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
#define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000)
/*
* GP (general purpose) CONTROL REGISTER
* Bit fields:
* 27: HW_RF_KILL_SW
* Indicates state of (platform's) hardware RF-Kill switch
* 26-24: POWER_SAVE_TYPE
* Indicates current power-saving mode:
* 000 -- No power saving
* 001 -- MAC power-down
* 010 -- PHY (radio) power-down
* 011 -- Error
* 9-6: SYS_CONFIG
* Indicates current system configuration, reflecting pins on chip
* as forced high/low by device circuit board.
* 4: GOING_TO_SLEEP
* Indicates MAC is entering a power-saving sleep power-down.
* Not a good time to access device-internal resources.
* 3: MAC_ACCESS_REQ
* Host sets this to request and maintain MAC wakeup, to allow host
* access to device-internal resources. Host must wait for
* MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
* device registers.
* 2: INIT_DONE
* Host sets this to put device into fully operational D0 power mode.
* Host resets this after SW_RESET to put device into low power mode.
* 0: MAC_CLOCK_READY
* Indicates MAC (ucode processor, etc.) is powered up and can run.
* Internal resources are accessible.
* NOTE: This does not indicate that the processor is actually running.
* NOTE: This does not indicate that device has completed
* init or post-power-down restore of internal SRAM memory.
* Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
* SRAM is restored and uCode is in normal operation mode.
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
* do not need to save/restore it.
* NOTE: After device reset, this bit remains "0" until host sets
* INIT_DONE
*/
#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
/* HW REV */
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
#define CSR_HW_REV_TYPE_5300 (0x0000020)
#define CSR_HW_REV_TYPE_5350 (0x0000030)
#define CSR_HW_REV_TYPE_5100 (0x0000050)
#define CSR_HW_REV_TYPE_5150 (0x0000040)
#define CSR_HW_REV_TYPE_1000 (0x0000060)
#define CSR_HW_REV_TYPE_6x00 (0x0000070)
#define CSR_HW_REV_TYPE_6x50 (0x0000080)
#define CSR_HW_REV_TYPE_6150 (0x0000084)
#define CSR_HW_REV_TYPE_6x05 (0x00000B0)
#define CSR_HW_REV_TYPE_6x30 CSR_HW_REV_TYPE_6x05
#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
#define CSR_HW_REV_TYPE_2x30 (0x00000C0)
#define CSR_HW_REV_TYPE_2x00 (0x0000100)
#define CSR_HW_REV_TYPE_105 (0x0000110)
#define CSR_HW_REV_TYPE_135 (0x0000120)
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC)
#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000)
/* EEPROM GP */
#define CSR_EEPROM_GP_VALID_MSK (0x00000007) /* signature */
#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
#define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000)
#define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001)
#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002)
#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004)
/* One-time-programmable memory general purpose reg */
#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */
#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */
#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */
#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */
/* GP REG */
#define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */
#define CSR_GP_REG_NO_POWER_SAVE (0x00000000)
#define CSR_GP_REG_MAC_POWER_SAVE (0x01000000)
#define CSR_GP_REG_PHY_POWER_SAVE (0x02000000)
#define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000)
/* CSR GIO */
#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002)
/*
* UCODE-DRIVER GP (general purpose) mailbox register 1
* Host driver and uCode write and/or read this register to communicate with
* each other.
* Bit fields:
* 4: UCODE_DISABLE
* Host sets this to request permanent halt of uCode, same as
* sending CARD_STATE command with "halt" bit set.
* 3: CT_KILL_EXIT
* Host sets this to request exit from CT_KILL state, i.e. host thinks
* device temperature is low enough to continue normal operation.
* 2: CMD_BLOCKED
* Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)
* to release uCode to clear all Tx and command queues, enter
* unassociated mode, and power down.
* NOTE: Some devices also use HBUS_TARG_MBX_C register for this bit.
* 1: SW_BIT_RFKILL
* Host sets this when issuing CARD_STATE command to request
* device sleep.
* 0: MAC_SLEEP
* uCode sets this when preparing a power-saving power-down.
* uCode resets this when power-up is complete and SRAM is sane.
* NOTE: device saves internal SRAM data to host when powering down,
* and must restore this data after powering back up.
* MAC_SLEEP is the best indication that restore is complete.
* Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
* do not need to save/restore it.
*/
#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE (0x00000020)
/* GP Driver */
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
#define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008)
#define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER (0x00000080)
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
/* LED */
#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
#define CSR_LED_REG_TRUN_ON (0x78)
#define CSR_LED_REG_TRUN_OFF (0x38)
/* ANA_PLL */
#define CSR50_ANA_PLL_CFG_VAL (0x00880300)
/* HPET MEM debug */
#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000)
/* DRAM INT TABLE */
#define CSR_DRAM_INT_TBL_ENABLE (1 << 31)
#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)
/*
* HBUS (Host-side Bus)
*
* HBUS registers are mapped directly into PCI bus space, but are used
* to indirectly access device's internal memory or registers that
* may be powered-down.
*
* Use iwl_write_direct32()/iwl_read_direct32() family for these registers;
* host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
* to make sure the MAC (uCode processor, etc.) is powered up for accessing
* internal resources.
*
* Do not use iwl_write32()/iwl_read32() family to access these registers;
* these provide only simple PCI bus access, without waking up the MAC.
*/
#define HBUS_BASE (0x400)
/*
* Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
* structures, error log, event log, verifying uCode load).
* First write to address register, then read from or write to data register
* to complete the job. Once the address register is set up, accesses to
* data registers auto-increment the address by one dword.
* Bit usage for address registers (read or write):
* 0-31: memory address within device
*/
#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */
#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
/*
* Registers for accessing device's internal peripheral registers
* (e.g. SCD, BSM, etc.). First write to address register,
* then read from or write to data register to complete the job.
* Bit usage for address registers (read or write):
* 0-15: register address (offset) within device
* 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
*/
#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
/* Used to enable DBGM */
#define HBUS_TARG_TEST_REG (HBUS_BASE+0x05c)
/*
* Per-Tx-queue write pointer (index, really!)
* Indicates index to next TFD that driver will fill (1 past latest filled).
* Bit usage:
* 0-7: queue write index
* 11-8: queue selector
*/
#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
/**********************************************************
* CSR values
**********************************************************/
/*
* host interrupt timeout value
* used with setting interrupt coalescing timer
* the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
*
* default interrupt coalescing timer is 64 x 32 = 2048 usecs
* default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
*/
#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
#endif /* !__iwl_csr_h__ */
@@ -0,0 +1,185 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project.
*
* 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_debug_h__
#define __iwl_debug_h__
#include "iwl-modparams.h"
static inline bool iwl_have_debug_level(u32 level)
{
return iwlwifi_mod_params.debug_level & level;
}
void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace,
const char *fmt, ...) __printf(4, 5);
void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3);
void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3);
void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);
/* No matter what is m (priv, bus, trans), this will work */
#define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a)
#define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a)
#define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a)
#define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a)
#define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a)
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
void __iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...) __printf(5, 6);
#else
__printf(5, 6) static inline void
__iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function,
const char *fmt, ...)
{}
#endif
#define iwl_print_hex_error(m, p, len) \
do { \
print_hex_dump(KERN_ERR, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
#define IWL_DEBUG(m, level, fmt, args...) \
__iwl_dbg((m)->dev, level, false, __func__, fmt, ##args)
#define IWL_DEBUG_DEV(dev, level, fmt, args...) \
__iwl_dbg((dev), level, false, __func__, fmt, ##args)
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
__iwl_dbg((m)->dev, level, true, __func__, fmt, ##args)
#ifdef CONFIG_IWLWIFI_DEBUG
#define iwl_print_hex_dump(m, level, p, len) \
do { \
if (iwl_have_debug_level(level)) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
#else
#define iwl_print_hex_dump(m, level, p, len)
#endif /* CONFIG_IWLWIFI_DEBUG */
/*
* To use the debug system:
*
* If you are defining a new debug classification, simply add it to the #define
* list here in the form of
*
* #define IWL_DL_xxxx VALUE
*
* where xxxx should be the name of the classification (for example, WEP).
*
* You then need to either add a IWL_xxxx_DEBUG() macro definition for your
* classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
* to send output to that classification.
*
* The active debug levels can be accessed via files
*
* /sys/module/iwlwifi/parameters/debug
* when CONFIG_IWLWIFI_DEBUG=y.
*
* /sys/kernel/debug/phy0/iwlwifi/debug/debug_level
* when CONFIG_IWLWIFI_DEBUGFS=y.
*
*/
/* 0x0000000F - 0x00000001 */
#define IWL_DL_INFO 0x00000001
#define IWL_DL_MAC80211 0x00000002
#define IWL_DL_HCMD 0x00000004
#define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */
#define IWL_DL_EEPROM 0x00000040
#define IWL_DL_RADIO 0x00000080
/* 0x00000F00 - 0x00000100 */
#define IWL_DL_POWER 0x00000100
#define IWL_DL_TEMP 0x00000200
#define IWL_DL_SCAN 0x00000800
/* 0x0000F000 - 0x00001000 */
#define IWL_DL_ASSOC 0x00001000
#define IWL_DL_DROP 0x00002000
#define IWL_DL_COEX 0x00008000
/* 0x000F0000 - 0x00010000 */
#define IWL_DL_FW 0x00010000
#define IWL_DL_RF_KILL 0x00020000
#define IWL_DL_FW_ERRORS 0x00040000
#define IWL_DL_LED 0x00080000
/* 0x00F00000 - 0x00100000 */
#define IWL_DL_RATE 0x00100000
#define IWL_DL_CALIB 0x00200000
#define IWL_DL_WEP 0x00400000
#define IWL_DL_TX 0x00800000
/* 0x0F000000 - 0x01000000 */
#define IWL_DL_RX 0x01000000
#define IWL_DL_ISR 0x02000000
#define IWL_DL_HT 0x04000000
/* 0xF0000000 - 0x10000000 */
#define IWL_DL_11H 0x10000000
#define IWL_DL_STATS 0x20000000
#define IWL_DL_TX_REPLY 0x40000000
#define IWL_DL_TX_QUEUES 0x80000000
#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
#define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a)
#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
#define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a)
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_COEX(p, f, a...) IWL_DEBUG(p, IWL_DL_COEX, f, ## a)
#define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
#define IWL_DEBUG_RATE_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
#define IWL_DEBUG_ASSOC(p, f, a...) \
IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_HT(p, f, a...) IWL_DEBUG(p, IWL_DL_HT, f, ## a)
#define IWL_DEBUG_STATS(p, f, a...) IWL_DEBUG(p, IWL_DL_STATS, f, ## a)
#define IWL_DEBUG_STATS_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a)
#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a)
#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)
#endif
@@ -0,0 +1,50 @@
/******************************************************************************
*
* Copyright(c) 2009 - 2012 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/module.h>
/* sparse doesn't like tracepoint macros */
#ifndef __CHECKER__
#include "iwl-trans.h"
#define CREATE_TRACE_POINTS
#include "iwl-devtrace.h"
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_info);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_warn);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_crit);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_err);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dbg);
#endif
@@ -0,0 +1,395 @@
/******************************************************************************
*
* Copyright(c) 2009 - 2012 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
*
*****************************************************************************/
#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
#define __IWLWIFI_DEVICE_TRACE
#include <linux/tracepoint.h>
#include <linux/device.h>
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
#undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \
static inline void trace_ ## name(proto) {}
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(...)
#undef DEFINE_EVENT
#define DEFINE_EVENT(evt_class, name, proto, ...) \
static inline void trace_ ## name(proto) {}
#endif
#define DEV_ENTRY __string(dev, dev_name(dev))
#define DEV_ASSIGN __assign_str(dev, dev_name(dev))
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_io
TRACE_EVENT(iwlwifi_dev_ioread32,
TP_PROTO(const struct device *dev, u32 offs, u32 val),
TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, offs)
__field(u32, val)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
TP_printk("[%s] read io[%#x] = %#x",
__get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_iowrite8,
TP_PROTO(const struct device *dev, u32 offs, u8 val),
TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, offs)
__field(u8, val)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
TP_printk("[%s] write io[%#x] = %#x)",
__get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_iowrite32,
TP_PROTO(const struct device *dev, u32 offs, u32 val),
TP_ARGS(dev, offs, val),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, offs)
__field(u32, val)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->offs = offs;
__entry->val = val;
),
TP_printk("[%s] write io[%#x] = %#x)",
__get_str(dev), __entry->offs, __entry->val)
);
TRACE_EVENT(iwlwifi_dev_irq,
TP_PROTO(const struct device *dev),
TP_ARGS(dev),
TP_STRUCT__entry(
DEV_ENTRY
),
TP_fast_assign(
DEV_ASSIGN;
),
/* TP_printk("") doesn't compile */
TP_printk("%d", 0)
);
TRACE_EVENT(iwlwifi_dev_ict_read,
TP_PROTO(const struct device *dev, u32 index, u32 value),
TP_ARGS(dev, index, value),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, index)
__field(u32, value)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->index = index;
__entry->value = value;
),
TP_printk("[%s] read ict[%d] = %#.8x",
__get_str(dev), __entry->index, __entry->value)
);
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_ucode
TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, time)
__field(u32, data)
__field(u32, ev)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->time = time;
__entry->data = data;
__entry->ev = ev;
),
TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
__get_str(dev), __entry->time, __entry->data, __entry->ev)
);
TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
TP_ARGS(dev, wraps, n_entry, p_entry),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, wraps)
__field(u32, n_entry)
__field(u32, p_entry)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->wraps = wraps;
__entry->n_entry = n_entry;
__entry->p_entry = p_entry;
),
TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
__get_str(dev), __entry->wraps, __entry->n_entry,
__entry->p_entry)
);
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_msg
#define MAX_MSG_LEN 110
DECLARE_EVENT_CLASS(iwlwifi_msg_event,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
TP_STRUCT__entry(
__dynamic_array(char, msg, MAX_MSG_LEN)
),
TP_fast_assign(
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
MAX_MSG_LEN, vaf->fmt,
*vaf->va) >= MAX_MSG_LEN);
),
TP_printk("%s", __get_str(msg))
);
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_warn,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_info,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_crit,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
TRACE_EVENT(iwlwifi_dbg,
TP_PROTO(u32 level, bool in_interrupt, const char *function,
struct va_format *vaf),
TP_ARGS(level, in_interrupt, function, vaf),
TP_STRUCT__entry(
__field(u32, level)
__field(u8, in_interrupt)
__string(function, function)
__dynamic_array(char, msg, MAX_MSG_LEN)
),
TP_fast_assign(
__entry->level = level;
__entry->in_interrupt = in_interrupt;
__assign_str(function, function);
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
MAX_MSG_LEN, vaf->fmt,
*vaf->va) >= MAX_MSG_LEN);
),
TP_printk("%s", (char *)__get_dynamic_array(msg))
);
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi
TRACE_EVENT(iwlwifi_dev_hcmd,
TP_PROTO(const struct device *dev, u32 flags,
const void *hcmd0, size_t len0,
const void *hcmd1, size_t len1,
const void *hcmd2, size_t len2),
TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
TP_STRUCT__entry(
DEV_ENTRY
__dynamic_array(u8, hcmd0, len0)
__dynamic_array(u8, hcmd1, len1)
__dynamic_array(u8, hcmd2, len2)
__field(u32, flags)
),
TP_fast_assign(
DEV_ASSIGN;
memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
__entry->flags = flags;
),
TP_printk("[%s] hcmd %#.2x (%ssync)",
__get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0],
__entry->flags & CMD_ASYNC ? "a" : "")
);
TRACE_EVENT(iwlwifi_dev_rx,
TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
TP_ARGS(dev, rxbuf, len),
TP_STRUCT__entry(
DEV_ENTRY
__dynamic_array(u8, rxbuf, len)
),
TP_fast_assign(
DEV_ASSIGN;
memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
),
TP_printk("[%s] RX cmd %#.2x",
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
);
TRACE_EVENT(iwlwifi_dev_tx,
TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
void *buf0, size_t buf0_len,
void *buf1, size_t buf1_len),
TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
TP_STRUCT__entry(
DEV_ENTRY
__field(size_t, framelen)
__dynamic_array(u8, tfd, tfdlen)
/*
* Do not insert between or below these items,
* we want to keep the frame together (except
* for the possible padding).
*/
__dynamic_array(u8, buf0, buf0_len)
__dynamic_array(u8, buf1, buf1_len)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->framelen = buf0_len + buf1_len;
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
),
TP_printk("[%s] TX %.2x (%zu bytes)",
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
__entry->framelen)
);
TRACE_EVENT(iwlwifi_dev_ucode_error,
TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
u32 data1, u32 data2, u32 line, u32 blink1,
u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
u32 brd_ver),
TP_ARGS(dev, desc, tsf_low, data1, data2, line,
blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
gp3, ucode_ver, hw_ver, brd_ver),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, desc)
__field(u32, tsf_low)
__field(u32, data1)
__field(u32, data2)
__field(u32, line)
__field(u32, blink1)
__field(u32, blink2)
__field(u32, ilink1)
__field(u32, ilink2)
__field(u32, bcon_time)
__field(u32, gp1)
__field(u32, gp2)
__field(u32, gp3)
__field(u32, ucode_ver)
__field(u32, hw_ver)
__field(u32, brd_ver)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->desc = desc;
__entry->tsf_low = tsf_low;
__entry->data1 = data1;
__entry->data2 = data2;
__entry->line = line;
__entry->blink1 = blink1;
__entry->blink2 = blink2;
__entry->ilink1 = ilink1;
__entry->ilink2 = ilink2;
__entry->bcon_time = bcon_time;
__entry->gp1 = gp1;
__entry->gp2 = gp2;
__entry->gp3 = gp3;
__entry->ucode_ver = ucode_ver;
__entry->hw_ver = hw_ver;
__entry->brd_ver = brd_ver;
),
TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
"blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
"bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
"hw 0x%08X brd 0x%08X",
__get_str(dev), __entry->desc, __entry->tsf_low,
__entry->data1,
__entry->data2, __entry->line, __entry->blink1,
__entry->blink2, __entry->ilink1, __entry->ilink2,
__entry->bcon_time, __entry->gp1, __entry->gp2,
__entry->gp3, __entry->ucode_ver, __entry->hw_ver,
__entry->brd_ver)
);
TRACE_EVENT(iwlwifi_dev_ucode_event,
TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry(
DEV_ENTRY
__field(u32, time)
__field(u32, data)
__field(u32, ev)
),
TP_fast_assign(
DEV_ASSIGN;
__entry->time = time;
__entry->data = data;
__entry->ev = ev;
),
TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
__get_str(dev), __entry->time, __entry->data, __entry->ev)
);
#endif /* __IWLWIFI_DEVICE_TRACE */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE iwl-devtrace
#include <trace/define_trace.h>
@@ -0,0 +1,535 @@
/******************************************************************************
*
* 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 - 2012 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 - 2012 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_fh_h__
#define __iwl_fh_h__
#include <linux/types.h>
/****************************/
/* 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 FH_MEM_LOWER_BOUND (0x1000)
#define FH_MEM_UPPER_BOUND (0x2000)
/**
* Keep-Warm (KW) buffer base address.
*
* Driver must allocate a 4KByte buffer that is for keeping the
* host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
* DRAM access when doing Txing or Rxing. The dummy accesses prevent host
* from going into a power-savings mode that would cause higher DRAM latency,
* and possible data over/under-runs, before all Tx/Rx is complete.
*
* Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
* of the buffer, which must be 4K aligned. Once this is set up, the device
* automatically invokes keep-warm accesses when normal accesses might not
* be sufficient to maintain fast DRAM response.
*
* Bit fields:
* 31-0: Keep-warm buffer physical base address [35:4], must be 4K aligned
*/
#define FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C)
/**
* TFD Circular Buffers Base (CBBC) addresses
*
* Device has 16 base pointer registers, one for each of 16 host-DRAM-resident
* circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
* (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04
* bytes from one another. Each TFD circular buffer in DRAM must be 256-byte
* aligned (address bits 0-7 must be 0).
* Later devices have 20 (5000 series) or 30 (higher) queues, but the registers
* for them are in different places.
*
* Bit fields in each pointer register:
* 27-0: TFD CB physical base address [35:8], must be 256-byte aligned
*/
#define FH_MEM_CBBC_0_15_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_MEM_CBBC_0_15_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10)
#define FH_MEM_CBBC_16_19_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBF0)
#define FH_MEM_CBBC_16_19_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_CBBC_20_31_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xB20)
#define FH_MEM_CBBC_20_31_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xB80)
/* Find TFD CB base pointer for given queue */
static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
{
if (chnl < 16)
return FH_MEM_CBBC_0_15_LOWER_BOUND + 4 * chnl;
if (chnl < 20)
return FH_MEM_CBBC_16_19_LOWER_BOUND + 4 * (chnl - 16);
WARN_ON_ONCE(chnl >= 32);
return FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20);
}
/**
* Rx SRAM Control and Status Registers (RSCSR)
*
* These registers provide handshake between driver and device for the Rx queue
* (this queue handles *all* command responses, notifications, Rx data, etc.
* sent from uCode to host driver). Unlike Tx, there is only one Rx
* queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can
* concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
* Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
* mapping between RBDs and RBs.
*
* Driver must allocate host DRAM memory for the following, and set the
* physical address of each into device registers:
*
* 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
* entries (although any power of 2, up to 4096, is selectable by driver).
* Each entry (1 dword) points to a receive buffer (RB) of consistent size
* (typically 4K, although 8K or 16K are also selectable by driver).
* Driver sets up RB size and number of RBDs in the CB via Rx config
* register FH_MEM_RCSR_CHNL0_CONFIG_REG.
*
* Bit fields within one RBD:
* 27-0: Receive Buffer physical address bits [35:8], 256-byte aligned
*
* Driver sets physical address [35:8] of base of RBD circular buffer
* into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
*
* 2) Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers
* (RBs) have been filled, via a "write pointer", actually the index of
* the RB's corresponding RBD within the circular buffer. Driver sets
* physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
*
* Bit fields in lower dword of Rx status buffer (upper dword not used
* by driver:
* 31-12: Not used by driver
* 11- 0: Index of last filled Rx buffer descriptor
* (device writes, driver reads this value)
*
* As the driver prepares Receive Buffers (RBs) for device to fill, driver must
* enter pointers to these RBs into contiguous RBD circular buffer entries,
* and update the device's "write" index register,
* FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
*
* This "write" index corresponds to the *next* RBD that the driver will make
* available, i.e. one RBD past the tail of the ready-to-fill RBDs within
* the circular buffer. This value should initially be 0 (before preparing any
* RBs), should be 8 after preparing the first 8 RBs (for example), and must
* wrap back to 0 at the end of the circular buffer (but don't wrap before
* "read" index has advanced past 1! See below).
* NOTE: DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
*
* As the device fills RBs (referenced from contiguous RBDs within the circular
* buffer), it updates the Rx status buffer in host DRAM, 2) described above,
* to tell the driver the index of the latest filled RBD. The driver must
* read this "read" index from DRAM after receiving an Rx interrupt from device
*
* The driver must also internally keep track of a third index, which is the
* next RBD to process. When receiving an Rx interrupt, driver should process
* all filled but unprocessed RBs up to, but not including, the RB
* corresponding to the "read" index. For example, if "read" index becomes "1",
* driver may process the RB pointed to by RBD 0. Depending on volume of
* traffic, there may be many RBs to process.
*
* If read index == write index, device thinks there is no room to put new data.
* Due to this, the maximum number of filled RBs is 255, instead of 256. To
* be safe, make sure that there is a gap of at least 2 RBDs between "write"
* and "read" indexes; that is, make sure that there are no more than 254
* buffers waiting to be filled.
*/
#define FH_MEM_RSCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBC0)
#define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND)
/**
* Physical base address of 8-byte Rx Status buffer.
* Bit fields:
* 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
*/
#define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0)
/**
* Physical base address of Rx Buffer Descriptor Circular Buffer.
* Bit fields:
* 27-0: RBD CD physical base address [35:8], must be 256-byte aligned.
*/
#define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004)
/**
* Rx write pointer (index, really!).
* Bit fields:
* 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1.
* NOTE: For 256-entry circular buffer, use only bits [7:0].
*/
#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008)
#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
/**
* Rx Config/Status Registers (RCSR)
* Rx Config Reg for channel 0 (only channel used)
*
* Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
* normal operation (see bit fields).
*
* Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
* Driver should poll FH_MEM_RSSR_RX_STATUS_REG for
* FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
*
* Bit fields:
* 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
* '10' operate normally
* 29-24: reserved
* 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
* min "5" for 32 RBDs, max "12" for 4096 RBDs.
* 19-18: reserved
* 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
* '10' 12K, '11' 16K.
* 15-14: reserved
* 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
* 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
* typical value 0x10 (about 1/2 msec)
* 3- 0: reserved
*/
#define FH_MEM_RCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xCC0)
#define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND)
#define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0)
#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */
#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */
#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK (0x00030000) /* bits 16-17 */
#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20)
#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4)
#define RX_RB_TIMEOUT (0x10)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000)
#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K (0x00010000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000)
#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000)
#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
/**
* Rx Shared Status Registers (RSSR)
*
* After stopping Rx DMA channel (writing 0 to
* FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
* FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
*
* Bit fields:
* 24: 1 = Channel 0 is idle
*
* FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
* contain default values that should not be altered by the driver.
*/
#define FH_MEM_RSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC40)
#define FH_MEM_RSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
#define FH_MEM_RSSR_SHARED_CTRL_REG (FH_MEM_RSSR_LOWER_BOUND)
#define FH_MEM_RSSR_RX_STATUS_REG (FH_MEM_RSSR_LOWER_BOUND + 0x004)
#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
(FH_MEM_RSSR_LOWER_BOUND + 0x008)
#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
/* TFDB Area - TFDs buffer table */
#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900)
#define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958)
#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
/**
* Transmit DMA Channel Control/Status Registers (TCSR)
*
* Device has one configuration register for each of 8 Tx DMA/FIFO channels
* supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
* which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
*
* To use a Tx DMA channel, driver must initialize its
* FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
*
* FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
* FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
*
* All other bits should be 0.
*
* Bit fields:
* 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
* '10' operate normally
* 29- 4: Reserved, set to "0"
* 3: Enable internal DMA requests (1, normal operation), disable (0)
* 2- 0: Reserved, set to "0"
*/
#define FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
/* Find Control/Status reg for given Tx DMA/FIFO channel */
#define FH_TCSR_CHNL_NUM (8)
/* TCSR: tx_config register values */
#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV (0x00000001)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE (0x00000008)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000)
#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
/**
* Tx Shared Status Registers (TSSR)
*
* After stopping Tx DMA channel (writing 0 to
* FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
* FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
* (channel's buffers empty | no pending requests).
*
* Bit fields:
* 31-24: 1 = Channel buffers empty (channel 7:0)
* 23-16: 1 = No pending requests (channel 7:0)
*/
#define FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0)
#define FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0)
#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
/**
* Bit fields for TSSR(Tx Shared Status & Control) error status register:
* 31: Indicates an address error when accessed to internal memory
* uCode/driver must write "1" in order to clear this flag
* 30: Indicates that Host did not send the expected number of dwords to FH
* uCode/driver must write "1" in order to clear this flag
* 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
* command was received from the scheduler while the TRB was already full
* with previous command
* uCode/driver must write "1" in order to clear this flag
* 7-0: Each status bit indicates a channel's TxCredit error. When an error
* bit is set, it indicates that the FH has received a full indication
* from the RTC TxFIFO and the current value of the TxCredit counter was
* not equal to zero. This mean that the credit mechanism was not
* synchronized to the TxFIFO status
* uCode/driver must write "1" in order to clear this flag
*/
#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018)
#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
/* Tx service channels */
#define FH_SRVC_CHNL (9)
#define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8)
#define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98)
#define FH_TX_TRB_REG(_chan) (FH_MEM_LOWER_BOUND + 0x958 + (_chan) * 4)
/* Instruct FH to increment the retry count of a packet when
* it is brought from the memory to TX-FIFO
*/
#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
#define RX_QUEUE_SIZE 256
#define RX_QUEUE_MASK 255
#define RX_QUEUE_SIZE_LOG 8
/*
* RX related structures and functions
*/
#define RX_FREE_BUFFERS 64
#define RX_LOW_WATERMARK 8
/**
* struct iwl_rb_status - reseve buffer status
* host memory mapped FH registers
* @closed_rb_num [0:11] - Indicates the index of the RB which was closed
* @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
* @finished_rb_num [0:11] - Indicates the index of the current RB
* in which the last frame was written to
* @finished_fr_num [0:11] - Indicates the index of the RX Frame
* which was transferred
*/
struct iwl_rb_status {
__le16 closed_rb_num;
__le16 closed_fr_num;
__le16 finished_rb_num;
__le16 finished_fr_nam;
__le32 __unused;
} __packed;
#define TFD_QUEUE_SIZE_MAX (256)
#define TFD_QUEUE_SIZE_BC_DUP (64)
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
#define IWL_NUM_OF_TBS 20
static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
{
return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
}
/**
* struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
*
* This structure contains dma address and length of transmission address
*
* @lo: low [31:0] portion of the dma address of TX buffer
* every even is unaligned on 16 bit boundary
* @hi_n_len 0-3 [35:32] portion of dma
* 4-15 length of the tx buffer
*/
struct iwl_tfd_tb {
__le32 lo;
__le16 hi_n_len;
} __packed;
/**
* struct iwl_tfd
*
* Transmit Frame Descriptor (TFD)
*
* @ __reserved1[3] reserved
* @ num_tbs 0-4 number of active tbs
* 5 reserved
* 6-7 padding (not used)
* @ tbs[20] transmit frame buffer descriptors
* @ __pad padding
*
* Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
* Both driver and device share these circular buffers, each of which must be
* contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
*
* Driver must indicate the physical address of the base of each
* circular buffer via the FH_MEM_CBBC_QUEUE registers.
*
* Each TFD contains pointer/size information for up to 20 data buffers
* in host DRAM. These buffers collectively contain the (one) frame described
* by the TFD. Each buffer must be a single contiguous block of memory within
* itself, but buffers may be scattered in host DRAM. Each buffer has max size
* of (4K - 4). The concatenates all of a TFD's buffers into a single
* Tx frame, up to 8 KBytes in size.
*
* A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
*/
struct iwl_tfd {
u8 __reserved1[3];
u8 num_tbs;
struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
__le32 __pad;
} __packed;
/* Keep Warm Size */
#define IWL_KW_SIZE 0x1000 /* 4k */
/* Fixed (non-configurable) rx data from phy */
/**
* struct iwlagn_schedq_bc_tbl scheduler byte count table
* base physical address provided by SCD_DRAM_BASE_ADDR
* @tfd_offset 0-12 - tx command byte count
* 12-16 - station index
*/
struct iwlagn_scd_bc_tbl {
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
} __packed;
#endif /* !__iwl_fh_h__ */
@@ -0,0 +1,354 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project.
*
* 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/delay.h>
#include <linux/device.h>
#include <linux/export.h>
#include "iwl-io.h"
#include"iwl-csr.h"
#include "iwl-debug.h"
#define IWL_POLL_INTERVAL 10 /* microseconds */
static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
}
static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
}
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
__iwl_set_bit(trans, reg, mask);
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bit);
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
__iwl_clear_bit(trans, reg, mask);
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_clear_bit);
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
{
unsigned long flags;
u32 v;
#ifdef CONFIG_IWLWIFI_DEBUG
WARN_ON_ONCE(value & ~mask);
#endif
spin_lock_irqsave(&trans->reg_lock, flags);
v = iwl_read32(trans, reg);
v &= ~mask;
v |= value;
iwl_write32(trans, reg, v);
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bits_mask);
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout)
{
int t = 0;
do {
if ((iwl_read32(trans, addr) & mask) == (bits & mask))
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
EXPORT_SYMBOL_GPL(iwl_poll_bit);
int iwl_grab_nic_access_silent(struct iwl_trans *trans)
{
int ret;
lockdep_assert_held(&trans->reg_lock);
/* this bit wakes up the NIC */
__iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/*
* These bits say the device is running, and should keep running for
* at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
* but they do not indicate that embedded SRAM is restored yet;
* 3945 and 4965 have volatile SRAM, and must save/restore contents
* to/from host DRAM when sleeping/waking for power-saving.
* Each direction takes approximately 1/4 millisecond; with this
* overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
* series of register accesses are expected (e.g. reading Event Log),
* to keep device from sleeping.
*
* CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
* SRAM is okay/restored. We don't check that here because this call
* is just for hardware register access; but GP1 MAC_SLEEP check is a
* good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
*
* 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling.
*/
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (ret < 0) {
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
return -EIO;
}
return 0;
}
EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent);
bool iwl_grab_nic_access(struct iwl_trans *trans)
{
int ret = iwl_grab_nic_access_silent(trans);
if (unlikely(ret)) {
u32 val = iwl_read32(trans, CSR_GP_CNTRL);
WARN_ONCE(1, "Timeout waiting for hardware access "
"(CSR_GP_CNTRL 0x%08x)\n", val);
return false;
}
return true;
}
EXPORT_SYMBOL_GPL(iwl_grab_nic_access);
void iwl_release_nic_access(struct iwl_trans *trans)
{
lockdep_assert_held(&trans->reg_lock);
__iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/*
* Above we read the CSR_GP_CNTRL register, which will flush
* any previous writes, but we need the write that clears the
* MAC_ACCESS_REQ bit to be performed before any other writes
* scheduled on different CPUs (after we drop reg_lock).
*/
mmiowb();
}
EXPORT_SYMBOL_GPL(iwl_release_nic_access);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
{
u32 value;
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans);
value = iwl_read32(trans, reg);
iwl_release_nic_access(trans);
spin_unlock_irqrestore(&trans->reg_lock, flags);
return value;
}
EXPORT_SYMBOL_GPL(iwl_read_direct32);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, reg, value);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_write_direct32);
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout)
{
int t = 0;
do {
if ((iwl_read_direct32(trans, addr) & mask) == mask)
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
EXPORT_SYMBOL_GPL(iwl_poll_direct_bit);
static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
{
iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
}
static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
{
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
}
u32 iwl_read_prph(struct iwl_trans *trans, u32 reg)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans);
val = __iwl_read_prph(trans, reg);
iwl_release_nic_access(trans);
spin_unlock_irqrestore(&trans->reg_lock, flags);
return val;
}
EXPORT_SYMBOL_GPL(iwl_read_prph);
void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, addr, val);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_write_prph);
void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, reg,
__iwl_read_prph(trans, reg) | mask);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
u32 bits, u32 mask)
{
unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, reg,
(__iwl_read_prph(trans, reg) & mask) | bits);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
{
unsigned long flags;
u32 val;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
val = __iwl_read_prph(trans, reg);
__iwl_write_prph(trans, reg, (val & ~mask));
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
{
unsigned long flags;
int offs;
u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
for (offs = 0; offs < dwords; offs++)
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords);
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
{
u32 value;
_iwl_read_targ_mem_dwords(trans, addr, &value, 1);
return value;
}
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
{
unsigned long flags;
int offs, result = 0;
u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags);
if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
for (offs = 0; offs < dwords; offs++)
iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
iwl_release_nic_access(trans);
} else
result = -EBUSY;
spin_unlock_irqrestore(&trans->reg_lock, flags);
return result;
}
EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords);
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val)
{
return _iwl_write_targ_mem_dwords(trans, addr, &val, 1);
}
EXPORT_SYMBOL_GPL(iwl_write_targ_mem);
@@ -0,0 +1,94 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project.
*
* 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_io_h__
#define __iwl_io_h__
#include "iwl-devtrace.h"
#include "iwl-trans.h"
static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
iwl_trans_write8(trans, ofs, val);
}
static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
iwl_trans_write32(trans, ofs, val);
}
static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
{
u32 val = iwl_trans_read32(trans, ofs);
trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
return val;
}
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value);
int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout);
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout);
int iwl_grab_nic_access_silent(struct iwl_trans *trans);
bool iwl_grab_nic_access(struct iwl_trans *trans);
void iwl_release_nic_access(struct iwl_trans *trans);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
u32 iwl_read_prph(struct iwl_trans *trans, u32 reg);
void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask);
void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
#define iwl_read_targ_mem_bytes(trans, addr, buf, bufsize) \
do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
_iwl_read_targ_mem_dwords(trans, addr, buf, \
(bufsize) / sizeof(u32));\
} while (0)
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
#endif
@@ -0,0 +1,257 @@
/******************************************************************************
*
* 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 - 2012 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 - 2012 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_prph_h__
#define __iwl_prph_h__
/*
* Registers in this file are internal, not PCI bus memory mapped.
* Driver accesses these via HBUS_TARG_PRPH_* registers.
*/
#define PRPH_BASE (0x00000)
#define PRPH_END (0xFFFFF)
/* APMG (power management) constants */
#define APMG_BASE (PRPH_BASE + 0x3000)
#define APMG_CLK_CTRL_REG (APMG_BASE + 0x0000)
#define APMG_CLK_EN_REG (APMG_BASE + 0x0004)
#define APMG_CLK_DIS_REG (APMG_BASE + 0x0008)
#define APMG_PS_CTRL_REG (APMG_BASE + 0x000c)
#define APMG_PCIDEV_STT_REG (APMG_BASE + 0x0010)
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMS_CLK_VAL_MRB_FUNC_MODE (0x00000001)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000)
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
/**
* Tx Scheduler
*
* The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
* (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
* host DRAM. It steers each frame's Tx command (which contains the frame
* data) into one of up to 7 prioritized Tx DMA FIFO channels within the
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
* but one DMA channel may take input from several queues.
*
* Tx DMA FIFOs have dedicated purposes.
*
* For 5000 series and up, they are used differently
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
*
* 0 -- EDCA BK (background) frames, lowest priority
* 1 -- EDCA BE (best effort) frames, normal priority
* 2 -- EDCA VI (video) frames, higher priority
* 3 -- EDCA VO (voice) and management frames, highest priority
* 4 -- unused
* 5 -- unused
* 6 -- unused
* 7 -- Commands
*
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
* In addition, driver can map the remaining queues to Tx DMA/FIFO
* channels 0-3 to support 11n aggregation via EDCA DMA channels.
*
* The driver sets up each queue to work in one of two modes:
*
* 1) Scheduler-Ack, in which the scheduler automatically supports a
* block-ack (BA) window of up to 64 TFDs. In this mode, each queue
* contains TFDs for a unique combination of Recipient Address (RA)
* and Traffic Identifier (TID), that is, traffic of a given
* Quality-Of-Service (QOS) priority, destined for a single station.
*
* In scheduler-ack mode, the scheduler keeps track of the Tx status of
* each frame within the BA window, including whether it's been transmitted,
* and whether it's been acknowledged by the receiving station. The device
* automatically processes block-acks received from the receiving STA,
* and reschedules un-acked frames to be retransmitted (successful
* Tx completion may end up being out-of-order).
*
* The driver must maintain the queue's Byte Count table in host DRAM
* for this mode.
* This mode does not support fragmentation.
*
* 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
* The device may automatically retry Tx, but will retry only one frame
* at a time, until receiving ACK from receiving station, or reaching
* retry limit and giving up.
*
* The command queue (#4/#9) must use this mode!
* This mode does not require use of the Byte Count table in host DRAM.
*
* Driver controls scheduler operation via 3 means:
* 1) Scheduler registers
* 2) Shared scheduler data base in internal SRAM
* 3) Shared data in host DRAM
*
* Initialization:
*
* When loading, driver should allocate memory for:
* 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs.
* 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory
* (1024 bytes for each queue).
*
* After receiving "Alive" response from uCode, driver must initialize
* the scheduler (especially for queue #4/#9, the command queue, otherwise
* the driver can't issue commands!):
*/
#define SCD_MEM_LOWER_BOUND (0x0000)
/**
* Max Tx window size is the max number of contiguous TFDs that the scheduler
* can keep track of at one time when creating block-ack chains of frames.
* Note that "64" matches the number of ack bits in a block-ack packet.
*/
#define SCD_WIN_SIZE 64
#define SCD_FRAME_LIMIT 64
#define SCD_TXFIFO_POS_TID (0)
#define SCD_TXFIFO_POS_RA (4)
#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
/* agn SCD */
#define SCD_QUEUE_STTS_REG_POS_TXF (0)
#define SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
#define SCD_QUEUE_STTS_REG_POS_WSL (4)
#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
#define SCD_QUEUE_STTS_REG_MSK (0x017F0000)
#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
/* Context Data */
#define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600)
#define SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
/* Tx status */
#define SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)
#define SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
/* Translation Data */
#define SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)
#define SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808)
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
#define SCD_BASE (PRPH_BASE + 0xa02c00)
#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0)
#define SCD_DRAM_BASE_ADDR (SCD_BASE + 0x8)
#define SCD_AIT (SCD_BASE + 0x0c)
#define SCD_TXFACT (SCD_BASE + 0x10)
#define SCD_ACTIVE (SCD_BASE + 0x14)
#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8)
#define SCD_CHAINEXT_EN (SCD_BASE + 0x244)
#define SCD_AGGR_SEL (SCD_BASE + 0x248)
#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108)
static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x18 + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x284 + (chnl - 20) * 4;
}
static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x68 + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x2B4 + (chnl - 20) * 4;
}
static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
{
if (chnl < 20)
return SCD_BASE + 0x10c + chnl * 4;
WARN_ON_ONCE(chnl >= 32);
return SCD_BASE + 0x384 + (chnl - 20) * 4;
}
/*********************** END TX SCHEDULER *************************************/
#endif /* __iwl_prph_h__ */
@@ -0,0 +1,309 @@
/******************************************************************************
*
* 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) 2010 - 2012 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) 2010 - 2012 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_TESTMODE_H__
#define __IWL_TESTMODE_H__
#include <linux/types.h>
/*
* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
* from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX).
* The command ID is carried with IWL_TM_ATTR_COMMAND.
*
* @IWL_TM_CMD_APP2DEV_UCODE:
* commands from user application to the uCode,
* the actual uCode host command ID is carried with
* IWL_TM_ATTR_UCODE_CMD_ID
*
* @IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
* @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
* @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
* commands from user applicaiton to access register
*
* @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name
* @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image
* @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration
* @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image
* @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data
* @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS
* commands fom user space for pure driver level operations
*
* @IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
* @IWL_TM_CMD_APP2DEV_END_TRACE:
* @IWL_TM_CMD_APP2DEV_READ_TRACE:
* commands fom user space for uCode trace operations
*
* @IWL_TM_CMD_DEV2APP_SYNC_RSP:
* commands from kernel space to carry the synchronous response
* to user application
* @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:
* commands from kernel space to multicast the spontaneous messages
* to user application, or reply of host commands
* @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
* commands from kernel space to carry the eeprom response
* to user application
*
* @IWL_TM_CMD_APP2DEV_OWNERSHIP:
* commands from user application to own change the ownership of the uCode
* if application has the ownership, the only host command from
* testmode will deliver to uCode. Default owner is driver
*
* @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Wake On Wireless LAN uCode image
* @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version
* @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device
* @IWL_TM_CMD_APP2DEV_GET_FW_INFO:
* retrieve information of existing loaded uCode image
*
* @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
* @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
* @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
* Commands to read/write data from periphery or SRAM memory ranges.
* Fore reading, a READ command is sent from the userspace and the data
* is returned when the user calls a DUMP command.
* For writing, only a WRITE command is used.
* @IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
* Command to enable/disable notifications (currently RX packets) from the
* driver to userspace.
*/
enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_UCODE = 1,
IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 = 2,
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 = 3,
IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8 = 4,
IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5,
IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6,
IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7,
IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8,
IWL_TM_CMD_APP2DEV_GET_EEPROM = 9,
IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10,
IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11,
IWL_TM_CMD_APP2DEV_END_TRACE = 12,
IWL_TM_CMD_APP2DEV_READ_TRACE = 13,
IWL_TM_CMD_DEV2APP_SYNC_RSP = 14,
IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15,
IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16,
IWL_TM_CMD_APP2DEV_OWNERSHIP = 17,
RESERVED_18 = 18,
RESERVED_19 = 19,
RESERVED_20 = 20,
RESERVED_21 = 21,
IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22,
IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23,
IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24,
IWL_TM_CMD_APP2DEV_GET_FW_INFO = 25,
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29,
IWL_TM_CMD_MAX = 30,
};
/*
* Atrribute filed in testmode command
* See enum iwl_tm_cmd_t.
*
* @IWL_TM_ATTR_NOT_APPLICABLE:
* The attribute is not applicable or invalid
* @IWL_TM_ATTR_COMMAND:
* From user space to kernel space:
* the command either destines to ucode, driver, or register;
* From kernel space to user space:
* the command either carries synchronous response,
* or the spontaneous message multicast from the device;
*
* @IWL_TM_ATTR_UCODE_CMD_ID:
* @IWL_TM_ATTR_UCODE_CMD_DATA:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
* The mandatory fields are :
* IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
* IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
* to the ucode
*
* @IWL_TM_ATTR_REG_OFFSET:
* @IWL_TM_ATTR_REG_VALUE8:
* @IWL_TM_ATTR_REG_VALUE32:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
* The mandatory fields are:
* IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
* IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value
*
* @IWL_TM_ATTR_SYNC_RSP:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
* The mandatory fields are:
* IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
* application command
*
* @IWL_TM_ATTR_UCODE_RX_PKT:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
* The mandatory fields are:
* IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
* application
*
* @IWL_TM_ATTR_EEPROM:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
* The mandatory fields are:
* IWL_TM_ATTR_EEPROM for the data content responging to the user
* application
*
* @IWL_TM_ATTR_TRACE_ADDR:
* @IWL_TM_ATTR_TRACE_SIZE:
* @IWL_TM_ATTR_TRACE_DUMP:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
* The mandatory fields are:
* IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
* IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size
* IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump
*
* @IWL_TM_ATTR_FIXRATE:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
* The mandatory fields are:
* IWL_TM_ATTR_FIXRATE for the fixed rate
*
* @IWL_TM_ATTR_UCODE_OWNER:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
* The mandatory fields are:
* IWL_TM_ATTR_UCODE_OWNER for the new owner
*
* @IWL_TM_ATTR_MEM_ADDR:
* @IWL_TM_ATTR_BUFFER_SIZE:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ
* or IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE.
* The mandatory fields are:
* IWL_TM_ATTR_MEM_ADDR for the address in SRAM/periphery to read/write
* IWL_TM_ATTR_BUFFER_SIZE for the buffer size of data to read/write.
*
* @IWL_TM_ATTR_BUFFER_DUMP:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP,
* IWL_TM_ATTR_BUFFER_DUMP is used for the data that was read.
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE,
* this attribute contains the data to write.
*
* @IWL_TM_ATTR_FW_VERSION:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION,
* IWL_TM_ATTR_FW_VERSION for the uCode version
*
* @IWL_TM_ATTR_DEVICE_ID:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID,
* IWL_TM_ATTR_DEVICE_ID for the device ID information
*
* @IWL_TM_ATTR_FW_TYPE:
* @IWL_TM_ATTR_FW_INST_SIZE:
* @IWL_TM_ATTR_FW_DATA_SIZE:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_INFO,
* The mandatory fields are:
* IWL_TM_ATTR_FW_TYPE for the uCode type (INIT/RUNTIME/...)
* IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section
* IWL_TM_ATTR_FW_DATA_SIZE for the size of data section
*
* @IWL_TM_ATTR_UCODE_CMD_SKB:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
* indicates that the user wants to receive the response of the command
* in a reply SKB. If it's not present, the response is not returned.
* @IWL_TM_ATTR_ENABLE_NOTIFICATIONS:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this
* flag enables (if present) or disables (if not) the forwarding
* to userspace.
*/
enum iwl_tm_attr_t {
IWL_TM_ATTR_NOT_APPLICABLE = 0,
IWL_TM_ATTR_COMMAND = 1,
IWL_TM_ATTR_UCODE_CMD_ID = 2,
IWL_TM_ATTR_UCODE_CMD_DATA = 3,
IWL_TM_ATTR_REG_OFFSET = 4,
IWL_TM_ATTR_REG_VALUE8 = 5,
IWL_TM_ATTR_REG_VALUE32 = 6,
IWL_TM_ATTR_SYNC_RSP = 7,
IWL_TM_ATTR_UCODE_RX_PKT = 8,
IWL_TM_ATTR_EEPROM = 9,
IWL_TM_ATTR_TRACE_ADDR = 10,
IWL_TM_ATTR_TRACE_SIZE = 11,
IWL_TM_ATTR_TRACE_DUMP = 12,
IWL_TM_ATTR_FIXRATE = 13,
IWL_TM_ATTR_UCODE_OWNER = 14,
IWL_TM_ATTR_MEM_ADDR = 15,
IWL_TM_ATTR_BUFFER_SIZE = 16,
IWL_TM_ATTR_BUFFER_DUMP = 17,
IWL_TM_ATTR_FW_VERSION = 18,
IWL_TM_ATTR_DEVICE_ID = 19,
IWL_TM_ATTR_FW_TYPE = 20,
IWL_TM_ATTR_FW_INST_SIZE = 21,
IWL_TM_ATTR_FW_DATA_SIZE = 22,
IWL_TM_ATTR_UCODE_CMD_SKB = 23,
IWL_TM_ATTR_ENABLE_NOTIFICATION = 24,
IWL_TM_ATTR_MAX = 25,
};
/* uCode trace buffer */
#define TRACE_BUFF_SIZE_MAX 0x200000
#define TRACE_BUFF_SIZE_MIN 0x20000
#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
#define TRACE_BUFF_PADD 0x2000
/* Maximum data size of each dump it packet */
#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024)
/* Address offset of data segment in SRAM */
#define SRAM_DATA_SEG_OFFSET 0x800000
#endif
@@ -0,0 +1,655 @@
/******************************************************************************
*
* 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) 2007 - 2012 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 - 2012 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_trans_h__
#define __iwl_trans_h__
#include <linux/ieee80211.h>
#include <linux/mm.h> /* for page_address */
#include "iwl-debug.h"
#include "iwl-config.h"
#include "iwl-fw.h"
/**
* DOC: Transport layer - what is it ?
*
* The tranport layer is the layer that deals with the HW directly. It provides
* an abstraction of the underlying HW to the upper layer. The transport layer
* doesn't provide any policy, algorithm or anything of this kind, but only
* mechanisms to make the HW do something.It is not completely stateless but
* close to it.
* We will have an implementation for each different supported bus.
*/
/**
* DOC: Life cycle of the transport layer
*
* The transport layer has a very precise life cycle.
*
* 1) A helper function is called during the module initialization and
* registers the bus driver's ops with the transport's alloc function.
* 2) Bus's probe calls to the transport layer's allocation functions.
* Of course this function is bus specific.
* 3) This allocation functions will spawn the upper layer which will
* register mac80211.
*
* 4) At some point (i.e. mac80211's start call), the op_mode will call
* the following sequence:
* start_hw
* start_fw
*
* 5) Then when finished (or reset):
* stop_fw (a.k.a. stop device for the moment)
* stop_hw
*
* 6) Eventually, the free function will be called.
*/
/**
* DOC: Host command section
*
* A host command is a commaned issued by the upper layer to the fw. There are
* several versions of fw that have several APIs. The transport layer is
* completely agnostic to these differences.
* The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
*/
#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 SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
#define SEQ_TO_INDEX(s) ((s) & 0xff)
#define INDEX_TO_SEQ(i) ((i) & 0xff)
#define SEQ_RX_FRAME cpu_to_le16(0x8000)
/**
* struct iwl_cmd_header
*
* This header format appears in the beginning of each command sent from the
* driver, and each response/notification received from uCode.
*/
struct iwl_cmd_header {
u8 cmd; /* Command ID: REPLY_RXON, etc. */
u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
/*
* The driver sets up the sequence number to values of its choosing.
* uCode does not use this value, but passes it back to the driver
* when sending the response to each driver-originated command, so
* the driver can match the response to the command. Since the values
* don't get used by uCode, the driver may set up an arbitrary format.
*
* There is one exception: uCode sets bit 15 when it originates
* the response/notification, i.e. when the response/notification
* is not a direct response to a command sent by the driver. For
* example, uCode issues REPLY_RX when it sends a received frame
* to the driver; it is not a direct response to any driver command.
*
* The Linux driver uses the following format:
*
* 0:7 tfd index - position within TX queue
* 8:12 TX queue id
* 13:14 reserved
* 15 unsolicited RX or uCode-originated notification
*/
__le16 sequence;
} __packed;
/* iwl_cmd_header flags value */
#define IWL_CMD_FAILED_MSK 0x40
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
#define FH_RSCSR_FRAME_INVALID 0x55550000
#define FH_RSCSR_FRAME_ALIGN 0x40
struct iwl_rx_packet {
/*
* The first 4 bytes of the RX frame header contain both the RX frame
* size and some flags.
* Bit fields:
* 31: flag flush RB request
* 30: flag ignore TC (terminal counter) request
* 29: flag fast IRQ request
* 28-14: Reserved
* 13-00: RX frame size
*/
__le32 len_n_flags;
struct iwl_cmd_header hdr;
u8 data[];
} __packed;
/**
* enum CMD_MODE - how to send the host commands ?
*
* @CMD_SYNC: The caller will be stalled until the fw responds to the command
* @CMD_ASYNC: Return right away and don't want for the response
* @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
* response.
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
*/
enum CMD_MODE {
CMD_SYNC = 0,
CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1),
CMD_ON_DEMAND = BIT(2),
};
#define DEF_CMD_PAYLOAD_SIZE 320
/**
* struct iwl_device_cmd
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for commands that
* aren't fully copied and use other TFD space.
*/
struct iwl_device_cmd {
struct iwl_cmd_header hdr; /* uCode API */
u8 payload[DEF_CMD_PAYLOAD_SIZE];
} __packed;
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
#define IWL_MAX_CMD_TFDS 2
/**
* struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
*
* IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
* ring. The transport layer doesn't map the command's buffer to DMA, but
* rather copies it to an previously allocated DMA buffer. This flag tells
* the transport layer not to copy the command, but to map the existing
* buffer. This can save memcpy and is worth with very big comamnds.
*/
enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_NOCOPY = BIT(0),
};
/**
* struct iwl_host_cmd - Host command to the uCode
*
* @data: array of chunks that composes the data of the host command
* @resp_pkt: response packet, if %CMD_WANT_SKB was set
* @_rx_page_order: (internally used to free response packet)
* @_rx_page_addr: (internally used to free response packet)
* @handler_status: return value of the handler of the command
* (put in setup_rx_handlers) - valid for SYNC mode only
* @flags: can be CMD_*
* @len: array of the lenths of the chunks in data
* @dataflags: IWL_HCMD_DFL_*
* @id: id of the host command
*/
struct iwl_host_cmd {
const void *data[IWL_MAX_CMD_TFDS];
struct iwl_rx_packet *resp_pkt;
unsigned long _rx_page_addr;
u32 _rx_page_order;
int handler_status;
u32 flags;
u16 len[IWL_MAX_CMD_TFDS];
u8 dataflags[IWL_MAX_CMD_TFDS];
u8 id;
};
static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
{
free_pages(cmd->_rx_page_addr, cmd->_rx_page_order);
}
struct iwl_rx_cmd_buffer {
struct page *_page;
int _offset;
bool _page_stolen;
unsigned int truesize;
};
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
{
return (void *)((unsigned long)page_address(r->_page) + r->_offset);
}
static inline int rxb_offset(struct iwl_rx_cmd_buffer *r)
{
return r->_offset;
}
static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
{
r->_page_stolen = true;
get_page(r->_page);
return r->_page;
}
#define MAX_NO_RECLAIM_CMDS 6
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
/*
* Maximum number of HW queues the transport layer
* currently supports
*/
#define IWL_MAX_HW_QUEUES 32
#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
#define IWL_FRAME_LIMIT 64
/**
* struct iwl_trans_config - transport configuration
*
* @op_mode: pointer to the upper layer.
* @cmd_queue: the index of the command queue.
* Must be set before start_fw.
* @cmd_fifo: the fifo for host commands
* @no_reclaim_cmds: Some devices erroneously don't set the
* SEQ_RX_FRAME bit on some notifications, this is the
* list of such notifications to filter. Max length is
* %MAX_NO_RECLAIM_CMDS.
* @n_no_reclaim_cmds: # of commands in list
* @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs,
* if unset 4k will be the RX buffer size
* @queue_watchdog_timeout: time (in ms) after which queues
* are considered stuck and will trigger device restart
* @command_names: array of command names, must be 256 entries
* (one for each command); for debugging only
*/
struct iwl_trans_config {
struct iwl_op_mode *op_mode;
u8 cmd_queue;
u8 cmd_fifo;
const u8 *no_reclaim_cmds;
int n_no_reclaim_cmds;
bool rx_buf_size_8k;
unsigned int queue_watchdog_timeout;
const char **command_names;
};
struct iwl_trans;
/**
* struct iwl_trans_ops - transport specific operations
*
* All the handlers MUST be implemented
*
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* May sleep
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
* will still issue interrupt if the HW RF kill is triggered unless
* op_mode_leaving is true.
* May sleep
* @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image.
* May sleep
* @fw_alive: called when the fw sends alive notification
* May sleep
* @stop_device:stops the whole device (embedded CPU put to reset)
* May sleep
* @wowlan_suspend: put the device into the correct mode for WoWLAN during
* suspend. This is optional, if not implemented WoWLAN will not be
* supported. This callback may sleep.
* @send_cmd:send a host command
* May sleep only if CMD_SYNC is set
* @tx: send an skb
* Must be atomic
* @reclaim: free packet until ssn. Returns a list of freed packets.
* Must be atomic
* @txq_enable: setup a queue. To setup an AC queue, use the
* iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before
* this one. The op_mode must not configure the HCMD queue. May sleep.
* @txq_disable: de-configure a Tx queue to send AMPDUs
* Must be atomic
* @wait_tx_queue_empty: wait until all tx queues are empty
* May sleep
* @dbgfs_register: add the dbgfs files under this directory. Files will be
* automatically deleted.
* @suspend: stop the device unless WoWLAN is configured
* @resume: resume activity of the device
* @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR
* @configure: configure parameters required by the transport layer from
* the op_mode. May be called several times before start_fw, can't be
* called after that.
* @set_pmi: set the power pmi state
*/
struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans);
void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
void (*fw_alive)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans);
void (*wowlan_suspend)(struct iwl_trans *trans);
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, int queue);
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
struct sk_buff_head *skbs);
void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo,
int sta_id, int tid, int frame_limit, u16 ssn);
void (*txq_disable)(struct iwl_trans *trans, int queue);
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
#ifdef CONFIG_PM_SLEEP
int (*suspend)(struct iwl_trans *trans);
int (*resume)(struct iwl_trans *trans);
#endif
void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state);
};
/**
* enum iwl_trans_state - state of the transport layer
*
* @IWL_TRANS_NO_FW: no fw has sent an alive response
* @IWL_TRANS_FW_ALIVE: a fw has sent an alive response
*/
enum iwl_trans_state {
IWL_TRANS_NO_FW = 0,
IWL_TRANS_FW_ALIVE = 1,
};
/**
* struct iwl_trans - transport common data
*
* @ops - pointer to iwl_trans_ops
* @op_mode - pointer to the op_mode
* @cfg - pointer to the configuration
* @reg_lock - protect hw register access
* @dev - pointer to struct device * that represents the device
* @hw_id: a u32 with the ID of the device / subdevice.
* Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported
* @wait_command_queue: the wait_queue for SYNC host commands
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_headroom: room needed for the transport's private use before the
* device_cmd for Tx - for internal use only
* The user should use iwl_trans_{alloc,free}_tx_cmd.
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
struct iwl_op_mode *op_mode;
const struct iwl_cfg *cfg;
enum iwl_trans_state state;
spinlock_t reg_lock;
struct device *dev;
u32 hw_rev;
u32 hw_id;
char hw_id_str[52];
bool pm_support;
wait_queue_head_t wait_command_queue;
/* The following fields are internal only */
struct kmem_cache *dev_cmd_pool;
size_t dev_cmd_headroom;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
};
static inline void iwl_trans_configure(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg)
{
/*
* only set the op_mode for the moment. Later on, this function will do
* more
*/
trans->op_mode = trans_cfg->op_mode;
trans->ops->configure(trans, trans_cfg);
}
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
{
might_sleep();
return trans->ops->start_hw(trans);
}
static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
bool op_mode_leaving)
{
might_sleep();
trans->ops->stop_hw(trans, op_mode_leaving);
trans->state = IWL_TRANS_NO_FW;
}
static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
{
might_sleep();
trans->state = IWL_TRANS_FW_ALIVE;
trans->ops->fw_alive(trans);
}
static inline int iwl_trans_start_fw(struct iwl_trans *trans,
const struct fw_img *fw)
{
might_sleep();
return trans->ops->start_fw(trans, fw);
}
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
{
might_sleep();
trans->ops->stop_device(trans);
trans->state = IWL_TRANS_NO_FW;
}
static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
{
might_sleep();
trans->ops->wowlan_suspend(trans);
}
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
return trans->ops->send_cmd(trans, cmd);
}
static inline struct iwl_device_cmd *
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
{
u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
if (unlikely(dev_cmd_ptr == NULL))
return NULL;
return (struct iwl_device_cmd *)
(dev_cmd_ptr + trans->dev_cmd_headroom);
}
static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
struct iwl_device_cmd *dev_cmd)
{
u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom;
kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr);
}
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, int queue)
{
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
return trans->ops->tx(trans, skb, dev_cmd, queue);
}
static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
int ssn, struct sk_buff_head *skbs)
{
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
trans->ops->reclaim(trans, queue, ssn, skbs);
}
static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue)
{
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
trans->ops->txq_disable(trans, queue);
}
static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
int fifo, int sta_id, int tid,
int frame_limit, u16 ssn)
{
might_sleep();
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,
frame_limit, ssn);
}
static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
int fifo)
{
iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
}
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
{
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
"%s bad state = %d", __func__, trans->state);
return trans->ops->wait_tx_queue_empty(trans);
}
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
{
return trans->ops->dbgfs_register(trans, dir);
}
#ifdef CONFIG_PM_SLEEP
static inline int iwl_trans_suspend(struct iwl_trans *trans)
{
return trans->ops->suspend(trans);
}
static inline int iwl_trans_resume(struct iwl_trans *trans)
{
return trans->ops->resume(trans);
}
#endif
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trans->ops->write8(trans, ofs, val);
}
static inline void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
trans->ops->write32(trans, ofs, val);
}
static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
{
return trans->ops->read32(trans, ofs);
}
static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
{
trans->ops->set_pmi(trans, state);
}
/*****************************************************
* driver (transport) register/unregister functions
******************************************************/
int __must_check iwl_pci_register_driver(void);
void iwl_pci_unregister_driver(void);
#endif /* __iwl_trans_h__ */