提交 8ca151b5 编写于 作者: J Johannes Berg

iwlwifi: add the MVM driver

Newer firmware revisions have a completely new
firmware API. This is the new driver for this
new API.

I've listed the people who directly contributed
code, but many others from various teams have
contributed in other ways.

Cc: Alexander Bondar <alexander.bondar@intel.com>
Cc: Amit Beka <amit.beka@intel.com>
Cc: Amnon Paz <amnonx.paz@intel.com>
Cc: Assaf Krauss <assaf.krauss@intel.com>
Cc: David Spinadel <david.spinadel@intel.com>
Cc: Dor Shaish <dor.shaish@intel.com>
Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Cc: Eytan Lifshitz <eytan.lifshitz@intel.com>
Cc: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
上级 b1e1adfa
......@@ -43,8 +43,20 @@ config IWLWIFI
module will be called iwlwifi.
config IWLDVM
tristate "Intel Wireless WiFi"
tristate "Intel Wireless WiFi DVM Firmware support"
depends on IWLWIFI
help
This is the driver supporting the DVM firmware which is
currently the only firmware available for existing devices.
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on IWLWIFI
help
This is the driver supporting the MVM firmware which is
currently only available for 7000 series devices.
Say yes if you have such a device.
menu "Debugging Options"
depends on IWLWIFI
......
......@@ -17,5 +17,6 @@ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
obj-$(CONFIG_IWLDVM) += dvm/
obj-$(CONFIG_IWLMVM) += mvm/
CFLAGS_iwl-devtrace.o := -I$(src)
......@@ -116,6 +116,7 @@ do { \
#define IWL_DL_HCMD 0x00000004
#define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */
#define IWL_DL_TE 0x00000020
#define IWL_DL_EEPROM 0x00000040
#define IWL_DL_RADIO 0x00000080
/* 0x00000F00 - 0x00000100 */
......@@ -156,6 +157,7 @@ do { \
#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_TE(p, f, a...) IWL_DEBUG(p, IWL_DL_TE, 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)
......
......@@ -139,8 +139,10 @@ struct iwl_drv {
#endif
};
#define DVM_OP_MODE 0
#define MVM_OP_MODE 1
enum {
DVM_OP_MODE = 0,
MVM_OP_MODE = 1,
};
/* Protects the table contents, i.e. the ops pointer & drv list */
static struct mutex iwlwifi_opmode_table_mtx;
......@@ -149,8 +151,8 @@ static struct iwlwifi_opmode_table {
const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */
struct list_head drv; /* list of devices using this op_mode */
} iwlwifi_opmode_table[] = { /* ops set when driver is initialized */
{ .name = "iwldvm", .ops = NULL },
{ .name = "iwlmvm", .ops = NULL },
[DVM_OP_MODE] = { .name = "iwldvm", .ops = NULL },
[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
};
/*
......@@ -963,7 +965,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
release_firmware(ucode_raw);
mutex_lock(&iwlwifi_opmode_table_mtx);
op = &iwlwifi_opmode_table[DVM_OP_MODE];
if (fw->mvm_fw)
op = &iwlwifi_opmode_table[MVM_OP_MODE];
else
op = &iwlwifi_opmode_table[DVM_OP_MODE];
/* add this device to the list of devices using this op_mode */
list_add_tail(&drv->list, &op->drv);
......
......@@ -166,6 +166,7 @@ struct iwl_tlv_calib_ctrl {
* @inst_evtlog_ptr: event log offset for runtime ucode.
* @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset for runtime ucode.
* @mvm_fw: indicates this is MVM firmware
*/
struct iwl_fw {
u32 ucode_ver;
......
obj-$(CONFIG_IWLMVM) += iwlmvm.o
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
iwlmvm-y += scan.o time-event.o rs.o
iwlmvm-y += power.o
iwlmvm-y += led.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <net/mac80211.h>
#include "fw-api.h"
#include "mvm.h"
struct iwl_mvm_iface_iterator_data {
struct ieee80211_vif *ignore_vif;
int idx;
struct iwl_mvm_phy_ctxt *phyctxt;
u16 ids[MAX_MACS_IN_BINDING];
u16 colors[MAX_MACS_IN_BINDING];
};
static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
struct iwl_mvm_iface_iterator_data *data)
{
struct iwl_binding_cmd cmd;
struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
int i, ret;
u32 status;
memset(&cmd, 0, sizeof(cmd));
cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
phyctxt->color));
cmd.action = cpu_to_le32(action);
cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
phyctxt->color));
for (i = 0; i < MAX_MACS_IN_BINDING; i++)
cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
for (i = 0; i < data->idx; i++)
cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
data->colors[i]));
status = 0;
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
sizeof(cmd), &cmd, &status);
if (ret) {
IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
action, ret);
return ret;
}
if (status) {
IWL_ERR(mvm, "Binding command failed: %u\n", status);
ret = -EIO;
}
return ret;
}
static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_iface_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (vif == data->ignore_vif)
return;
if (mvmvif->phy_ctxt != data->phyctxt)
return;
if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
return;
data->ids[data->idx] = mvmvif->id;
data->colors[data->idx] = mvmvif->color;
data->idx++;
}
static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *phyctxt,
bool add)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_iface_iterator_data data = {
.ignore_vif = vif,
.phyctxt = phyctxt,
};
u32 action = FW_CTXT_ACTION_MODIFY;
lockdep_assert_held(&mvm->mutex);
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_iface_iterator,
&data);
/*
* If there are no other interfaces yet we
* need to create a new binding.
*/
if (data.idx == 0) {
if (add)
action = FW_CTXT_ACTION_ADD;
else
action = FW_CTXT_ACTION_REMOVE;
}
if (add) {
if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
return -EINVAL;
data.ids[data.idx] = mvmvif->id;
data.colors[data.idx] = mvmvif->color;
data.idx++;
}
return iwl_mvm_binding_cmd(mvm, action, &data);
}
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
}
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
return -EINVAL;
return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
}
此差异已折叠。
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include "mvm.h"
#include "sta.h"
#include "iwl-io.h"
struct iwl_dbgfs_mvm_ctx {
struct iwl_mvm *mvm;
struct ieee80211_vif *vif;
};
static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
char buf[16];
int buf_size, ret;
u32 scd_q_msk;
if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%x", &scd_q_msk) != 1)
return -EINVAL;
IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
mutex_lock(&mvm->mutex);
ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
mutex_unlock(&mvm->mutex);
return ret;
}
static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
struct ieee80211_sta *sta;
char buf[8];
int buf_size, sta_id, drain, ret;
if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
return -EINVAL;
mutex_lock(&mvm->mutex);
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta))
ret = -ENOENT;
else
ret = iwl_mvm_drain_sta(mvm, (void *)sta->drv_priv, drain) ? :
count;
mutex_unlock(&mvm->mutex);
return ret;
}
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
const struct fw_img *img;
int ofs, len, pos = 0;
size_t bufsz, ret;
char *buf;
u8 *ptr;
/* default is to dump the entire data segment */
if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) {
mvm->dbgfs_sram_offset = 0x800000;
if (!mvm->ucode_loaded)
return -EINVAL;
img = &mvm->fw->img[mvm->cur_ucode];
mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
}
len = mvm->dbgfs_sram_len;
bufsz = len * 4 + 256;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ptr = kzalloc(len, GFP_KERNEL);
if (!ptr) {
kfree(buf);
return -ENOMEM;
}
pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len);
pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
mvm->dbgfs_sram_offset);
iwl_trans_read_mem_bytes(mvm->trans,
mvm->dbgfs_sram_offset,
ptr, len);
for (ofs = 0; ofs < len; ofs += 16) {
pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
bufsz - pos, false);
pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
kfree(ptr);
return ret;
}
static ssize_t iwl_dbgfs_sram_write(struct file *file,
const char __user *user_buf, size_t count,
loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
char buf[64];
int buf_size;
u32 offset, len;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
if ((offset & 0x3) || (len & 0x3))
return -EINVAL;
mvm->dbgfs_sram_offset = offset;
mvm->dbgfs_sram_len = len;
} else {
mvm->dbgfs_sram_offset = 0;
mvm->dbgfs_sram_len = 0;
}
return count;
}
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
struct ieee80211_sta *sta;
char buf[400];
int i, pos = 0, bufsz = sizeof(buf);
mutex_lock(&mvm->mutex);
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (!sta)
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
else if (IS_ERR(sta))
pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
PTR_ERR(sta));
else
pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
sta->addr);
}
mutex_unlock(&mvm->mutex);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_power_down_allow_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
char buf[8] = {};
int allow;
if (!mvm->ucode_loaded)
return -EIO;
if (copy_from_user(buf, user_buf, sizeof(buf)))
return -EFAULT;
if (sscanf(buf, "%d", &allow) != 1)
return -EINVAL;
IWL_DEBUG_POWER(mvm, "%s device power down\n",
allow ? "allow" : "prevent");
/*
* TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it
*/
return count;
}
static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
char buf[8] = {};
int allow;
if (copy_from_user(buf, user_buf, sizeof(buf)))
return -EFAULT;
if (sscanf(buf, "%d", &allow) != 1)
return -EINVAL;
IWL_DEBUG_POWER(mvm, "%s device power down in d3\n",
allow ? "allow" : "prevent");
/*
* TODO: When WoWLAN FW alive notification happens, driver will send
* REPLY_DEBUG_CMD setting power_down_allow flag according to
* mvm->prevent_power_down_d3
*/
mvm->prevent_power_down_d3 = !allow;
return count;
}
#define MVM_DEBUGFS_READ_FILE_OPS(name) \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.read = iwl_dbgfs_##name##_read, \
.open = iwl_dbgfs_open_file_generic, \
.llseek = generic_file_llseek, \
}
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.read = iwl_dbgfs_##name##_read, \
.open = iwl_dbgfs_open_file_generic, \
.llseek = generic_file_llseek, \
};
#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.open = iwl_dbgfs_open_file_generic, \
.llseek = generic_file_llseek, \
};
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \
if (!debugfs_create_file(#name, mode, parent, mvm, \
&iwl_dbgfs_##name##_ops)) \
goto err; \
} while (0)
#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
if (!debugfs_create_file(#name, mode, parent, vif, \
&iwl_dbgfs_##name##_ops)) \
goto err; \
} while (0)
/* Device wide debugfs entries */
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
MVM_DEBUGFS_READ_FILE_OPS(stations);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
{
char buf[100];
mvm->debugfs_dir = dbgfs_dir;
MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
/*
* Create a symlink with mac80211. It will be removed when mac80211
* exists (before the opmode exists which removes the target.)
*/
snprintf(buf, 100, "../../%s/%s",
dbgfs_dir->d_parent->d_parent->d_name.name,
dbgfs_dir->d_parent->d_name.name);
if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
goto err;
return 0;
err:
IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
return -ENOMEM;
}
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_d3_h__
#define __fw_api_d3_h__
/**
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
*/
enum iwl_d3_wakeup_flags {
IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
/**
* struct iwl_d3_manager_config - D3 manager configuration command
* @min_sleep_time: minimum sleep time (in usec)
* @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags
*
* The structure is used for the D3_CONFIG_CMD command.
*/
struct iwl_d3_manager_config {
__le32 min_sleep_time;
__le32 wakeup_flags;
} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */
/* TODO: OFFLOADS_QUERY_API_S_VER_1 */
/**
* enum iwl_d3_proto_offloads - enabled protocol offloads
* @IWL_D3_PROTO_OFFLOAD_ARP: ARP data is enabled
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
*/
enum iwl_proto_offloads {
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
};
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2
/**
* struct iwl_proto_offload_cmd - ARP/NS offload configuration
* @enabled: enable flags
* @remote_ipv4_addr: remote address to answer to (or zero if all)
* @host_ipv4_addr: our IPv4 address to respond to queries for
* @arp_mac_addr: our MAC address for ARP responses
* @remote_ipv6_addr: remote address to answer to (or zero if all)
* @solicited_node_ipv6_addr: broken -- solicited node address exists
* for each target address
* @target_ipv6_addr: our target addresses
* @ndp_mac_addr: neighbor soliciation response MAC address
*/
struct iwl_proto_offload_cmd {
__le32 enabled;
__be32 remote_ipv4_addr;
__be32 host_ipv4_addr;
u8 arp_mac_addr[ETH_ALEN];
__le16 reserved1;
u8 remote_ipv6_addr[16];
u8 solicited_node_ipv6_addr[16];
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16];
u8 ndp_mac_addr[ETH_ALEN];
__le16 reserved2;
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
/*
* WOWLAN_PATTERNS
*/
#define IWL_WOWLAN_MIN_PATTERN_LEN 16
#define IWL_WOWLAN_MAX_PATTERN_LEN 128
struct iwl_wowlan_pattern {
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
u8 mask_size;
u8 pattern_size;
__le16 reserved;
} __packed; /* WOWLAN_PATTERN_API_S_VER_1 */
#define IWL_WOWLAN_MAX_PATTERNS 20
struct iwl_wowlan_patterns_cmd {
__le32 n_patterns;
struct iwl_wowlan_pattern patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
IWL_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
IWL_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(5),
IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(6),
IWL_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(7),
IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT = BIT(8),
IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS = BIT(9),
IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE = BIT(10),
/* BIT(11) reserved */
IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET = BIT(12),
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
struct iwl_wowlan_config_cmd {
__le32 wakeup_filter;
__le16 non_qos_seq;
__le16 qos_seq[8];
u8 wowlan_ba_teardown_tids;
u8 is_11n_connection;
} __packed; /* WOWLAN_CONFIG_API_S_VER_2 */
/*
* WOWLAN_TSC_RSC_PARAMS
*/
#define IWL_NUM_RSC 16
struct tkip_sc {
__le16 iv16;
__le16 pad;
__le32 iv32;
} __packed; /* TKIP_SC_API_U_VER_1 */
struct iwl_tkip_rsc_tsc {
struct tkip_sc unicast_rsc[IWL_NUM_RSC];
struct tkip_sc multicast_rsc[IWL_NUM_RSC];
struct tkip_sc tsc;
} __packed; /* TKIP_TSC_RSC_API_S_VER_1 */
struct aes_sc {
__le64 pn;
} __packed; /* TKIP_AES_SC_API_U_VER_1 */
struct iwl_aes_rsc_tsc {
struct aes_sc unicast_rsc[IWL_NUM_RSC];
struct aes_sc multicast_rsc[IWL_NUM_RSC];
struct aes_sc tsc;
} __packed; /* AES_TSC_RSC_API_S_VER_1 */
union iwl_all_tsc_rsc {
struct iwl_tkip_rsc_tsc tkip;
struct iwl_aes_rsc_tsc aes;
}; /* ALL_TSC_RSC_API_S_VER_2 */
struct iwl_wowlan_rsc_tsc_params_cmd {
union iwl_all_tsc_rsc all_tsc_rsc;
} __packed; /* ALL_TSC_RSC_API_S_VER_2 */
#define IWL_MIC_KEY_SIZE 8
struct iwl_mic_keys {
u8 tx[IWL_MIC_KEY_SIZE];
u8 rx_unicast[IWL_MIC_KEY_SIZE];
u8 rx_mcast[IWL_MIC_KEY_SIZE];
} __packed; /* MIC_KEYS_API_S_VER_1 */
#define IWL_P1K_SIZE 5
struct iwl_p1k_cache {
__le16 p1k[IWL_P1K_SIZE];
} __packed;
#define IWL_NUM_RX_P1K_CACHE 2
struct iwl_wowlan_tkip_params_cmd {
struct iwl_mic_keys mic_keys;
struct iwl_p1k_cache tx;
struct iwl_p1k_cache rx_uni[IWL_NUM_RX_P1K_CACHE];
struct iwl_p1k_cache rx_multi[IWL_NUM_RX_P1K_CACHE];
} __packed; /* WOWLAN_TKIP_SETTING_API_S_VER_1 */
#define IWL_KCK_MAX_SIZE 32
#define IWL_KEK_MAX_SIZE 32
struct iwl_wowlan_kek_kck_material_cmd {
u8 kck[IWL_KCK_MAX_SIZE];
u8 kek[IWL_KEK_MAX_SIZE];
__le16 kck_len;
__le16 kek_len;
__le64 replay_ctr;
} __packed; /* KEK_KCK_MATERIAL_API_S_VER_2 */
#define RF_KILL_INDICATOR_FOR_WOWLAN 0x87
enum iwl_wowlan_rekey_status {
IWL_WOWLAN_REKEY_POST_REKEY = 0,
IWL_WOWLAN_REKEY_WHILE_REKEY = 1,
}; /* WOWLAN_REKEY_STATUS_API_E_VER_1 */
enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS = 0,
IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_BY_PATTERN = BIT(1),
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON = BIT(2),
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH = BIT(3),
IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE = BIT(4),
IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED = BIT(5),
IWL_WOWLAN_WAKEUP_BY_UCODE_ERROR = BIT(6),
IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST = BIT(7),
IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11),
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_status {
__le64 replay_ctr;
__le16 pattern_number;
__le16 non_qos_seq_ctr;
__le16 qos_seq_ctr[8];
__le32 wakeup_reasons;
__le32 rekey_status;
__le32 num_of_gtk_rekeys;
__le32 transmitted_ndps;
__le32 received_beacons;
__le32 wake_packet_length;
__le32 wake_packet_bufsize;
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
} __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
/* TODO: NetDetect API */
#endif /* __fw_api_d3_h__ */
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_mac_h__
#define __fw_api_mac_h__
/*
* The first MAC indices (starting from 0)
* are available to the driver, AUX follows
*/
#define MAC_INDEX_AUX 4
#define MAC_INDEX_MIN_DRIVER 0
#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX
#define AC_NUM 4 /* Number of access categories */
/**
* enum iwl_mac_protection_flags - MAC context flags
* @MAC_PROT_FLG_TGG_PROTECT: 11g protection when transmitting OFDM frames,
* this will require CCK RTS/CTS2self.
* RTS/CTS will protect full burst time.
* @MAC_PROT_FLG_HT_PROT: enable HT protection
* @MAC_PROT_FLG_FAT_PROT: protect 40 MHz transmissions
* @MAC_PROT_FLG_SELF_CTS_EN: allow CTS2self
*/
enum iwl_mac_protection_flags {
MAC_PROT_FLG_TGG_PROTECT = BIT(3),
MAC_PROT_FLG_HT_PROT = BIT(23),
MAC_PROT_FLG_FAT_PROT = BIT(24),
MAC_PROT_FLG_SELF_CTS_EN = BIT(30),
};
#define MAC_FLG_SHORT_SLOT BIT(4)
#define MAC_FLG_SHORT_PREAMBLE BIT(5)
/**
* enum iwl_mac_types - Supported MAC types
* @FW_MAC_TYPE_FIRST: lowest supported MAC type
* @FW_MAC_TYPE_AUX: Auxiliary MAC (internal)
* @FW_MAC_TYPE_LISTENER: monitor MAC type (?)
* @FW_MAC_TYPE_PIBSS: Pseudo-IBSS
* @FW_MAC_TYPE_IBSS: IBSS
* @FW_MAC_TYPE_BSS_STA: BSS (managed) station
* @FW_MAC_TYPE_P2P_DEVICE: P2P Device
* @FW_MAC_TYPE_P2P_STA: P2P client
* @FW_MAC_TYPE_GO: P2P GO
* @FW_MAC_TYPE_TEST: ?
* @FW_MAC_TYPE_MAX: highest support MAC type
*/
enum iwl_mac_types {
FW_MAC_TYPE_FIRST = 1,
FW_MAC_TYPE_AUX = FW_MAC_TYPE_FIRST,
FW_MAC_TYPE_LISTENER,
FW_MAC_TYPE_PIBSS,
FW_MAC_TYPE_IBSS,
FW_MAC_TYPE_BSS_STA,
FW_MAC_TYPE_P2P_DEVICE,
FW_MAC_TYPE_P2P_STA,
FW_MAC_TYPE_GO,
FW_MAC_TYPE_TEST,
FW_MAC_TYPE_MAX = FW_MAC_TYPE_TEST
}; /* MAC_CONTEXT_TYPE_API_E_VER_1 */
/**
* enum iwl_tsf_id - TSF hw timer ID
* @TSF_ID_A: use TSF A
* @TSF_ID_B: use TSF B
* @TSF_ID_C: use TSF C
* @TSF_ID_D: use TSF D
* @NUM_TSF_IDS: number of TSF timers available
*/
enum iwl_tsf_id {
TSF_ID_A = 0,
TSF_ID_B = 1,
TSF_ID_C = 2,
TSF_ID_D = 3,
NUM_TSF_IDS = 4,
}; /* TSF_ID_API_E_VER_1 */
/**
* struct iwl_mac_data_ap - configuration data for AP MAC context
* @beacon_time: beacon transmit time in system time
* @beacon_tsf: beacon transmit time in TSF
* @bi: beacon interval in TU
* @bi_reciprocal: 2^32 / bi
* @dtim_interval: dtim transmit time in TU
* @dtim_reciprocal: 2^32 / dtim_interval
* @mcast_qid: queue ID for multicast traffic
* @beacon_template: beacon template ID
*/
struct iwl_mac_data_ap {
__le32 beacon_time;
__le64 beacon_tsf;
__le32 bi;
__le32 bi_reciprocal;
__le32 dtim_interval;
__le32 dtim_reciprocal;
__le32 mcast_qid;
__le32 beacon_template;
} __packed; /* AP_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_ibss - configuration data for IBSS MAC context
* @beacon_time: beacon transmit time in system time
* @beacon_tsf: beacon transmit time in TSF
* @bi: beacon interval in TU
* @bi_reciprocal: 2^32 / bi
*/
struct iwl_mac_data_ibss {
__le32 beacon_time;
__le64 beacon_tsf;
__le32 bi;
__le32 bi_reciprocal;
} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_sta - configuration data for station MAC context
* @is_assoc: 1 for associated state, 0 otherwise
* @dtim_time: DTIM arrival time in system time
* @dtim_tsf: DTIM arrival time in TSF
* @bi: beacon interval in TU, applicable only when associated
* @bi_reciprocal: 2^32 / bi , applicable only when associated
* @dtim_interval: DTIM interval in TU, applicable only when associated
* @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated
* @listen_interval: in beacon intervals, applicable only when associated
* @assoc_id: unique ID assigned by the AP during association
*/
struct iwl_mac_data_sta {
__le32 is_assoc;
__le32 dtim_time;
__le64 dtim_tsf;
__le32 bi;
__le32 bi_reciprocal;
__le32 dtim_interval;
__le32 dtim_reciprocal;
__le32 listen_interval;
__le32 assoc_id;
__le32 assoc_beacon_arrive_time;
} __packed; /* STA_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_go - configuration data for P2P GO MAC context
* @ap: iwl_mac_data_ap struct with most config data
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
* @opp_ps_enabled: indicate that opportunistic PS allowed
*/
struct iwl_mac_data_go {
struct iwl_mac_data_ap ap;
__le32 ctwin;
__le32 opp_ps_enabled;
} __packed; /* GO_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_p2p_sta - configuration data for P2P client MAC context
* @sta: iwl_mac_data_sta struct with most config data
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
*/
struct iwl_mac_data_p2p_sta {
struct iwl_mac_data_sta sta;
__le32 ctwin;
} __packed; /* P2P_STA_MAC_DATA_API_S_VER_1 */
/**
* struct iwl_mac_data_pibss - Pseudo IBSS config data
* @stats_interval: interval in TU between statistics notifications to host.
*/
struct iwl_mac_data_pibss {
__le32 stats_interval;
} __packed; /* PIBSS_MAC_DATA_API_S_VER_1 */
/*
* struct iwl_mac_data_p2p_dev - configuration data for the P2P Device MAC
* context.
* @is_disc_extended: if set to true, P2P Device discoverability is enabled on
* other channels as well. This should be to true only in case that the
* device is discoverable and there is an active GO. Note that setting this
* field when not needed, will increase the number of interrupts and have
* effect on the platform power, as this setting opens the Rx filters on
* all macs.
*/
struct iwl_mac_data_p2p_dev {
__le32 is_disc_extended;
} __packed; /* _P2P_DEV_MAC_DATA_API_S_VER_1 */
/**
* enum iwl_mac_filter_flags - MAC context filter flags
* @MAC_FILTER_IN_PROMISC: accept all data frames
* @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and
* control frames to the host
* @MAC_FILTER_ACCEPT_GRP: accept multicast frames
* @MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames
* @MAC_FILTER_DIS_GRP_DECRYPT: don't decrypt multicast frames
* @MAC_FILTER_IN_BEACON: transfer foreign BSS's beacons to host
* (in station mode when associated)
* @MAC_FILTER_OUT_BCAST: filter out all broadcast frames
* @MAC_FILTER_IN_CRC32: extract FCS and append it to frames
* @MAC_FILTER_IN_PROBE_REQUEST: pass probe requests to host
*/
enum iwl_mac_filter_flags {
MAC_FILTER_IN_PROMISC = BIT(0),
MAC_FILTER_IN_CONTROL_AND_MGMT = BIT(1),
MAC_FILTER_ACCEPT_GRP = BIT(2),
MAC_FILTER_DIS_DECRYPT = BIT(3),
MAC_FILTER_DIS_GRP_DECRYPT = BIT(4),
MAC_FILTER_IN_BEACON = BIT(6),
MAC_FILTER_OUT_BCAST = BIT(8),
MAC_FILTER_IN_CRC32 = BIT(11),
MAC_FILTER_IN_PROBE_REQUEST = BIT(12),
};
/**
* enum iwl_mac_qos_flags - QoS flags
* @MAC_QOS_FLG_UPDATE_EDCA: ?
* @MAC_QOS_FLG_TGN: HT is enabled
* @MAC_QOS_FLG_TXOP_TYPE: ?
*
*/
enum iwl_mac_qos_flags {
MAC_QOS_FLG_UPDATE_EDCA = BIT(0),
MAC_QOS_FLG_TGN = BIT(1),
MAC_QOS_FLG_TXOP_TYPE = BIT(4),
};
/**
* struct iwl_ac_qos - QOS timing params for MAC_CONTEXT_CMD
* @cw_min: Contention window, start value in numbers of slots.
* Should be a power-of-2, minus 1. Device's default is 0x0f.
* @cw_max: Contention window, max value in numbers of slots.
* Should be a power-of-2, minus 1. Device's default is 0x3f.
* @aifsn: Number of slots in Arbitration Interframe Space (before
* performing random backoff timing prior to Tx). Device default 1.
* @fifos_mask: FIFOs used by this MAC for this AC
* @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0.
*
* One instance of this config struct for each of 4 EDCA access categories
* in struct iwl_qosparam_cmd.
*
* Device will automatically increase contention window by (2*CW) + 1 for each
* transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
* value, to cap the CW value.
*/
struct iwl_ac_qos {
__le16 cw_min;
__le16 cw_max;
u8 aifsn;
u8 fifos_mask;
__le16 edca_txop;
} __packed; /* AC_QOS_API_S_VER_2 */
/**
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @mac_type: one of FW_MAC_TYPE_*
* @tsd_id: TSF HW timer, one of TSF_ID_*
* @node_addr: MAC address
* @bssid_addr: BSSID
* @cck_rates: basic rates available for CCK
* @ofdm_rates: basic rates available for OFDM
* @protection_flags: combination of MAC_PROT_FLG_FLAG_*
* @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise
* @short_slot: 0x10 for enabling short slots, 0 otherwise
* @filter_flags: combination of MAC_FILTER_*
* @qos_flags: from MAC_QOS_FLG_*
* @ac: one iwl_mac_qos configuration for each AC
* @mac_specific: one of struct iwl_mac_data_*, according to mac_type
*/
struct iwl_mac_ctx_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* MAC_CONTEXT_COMMON_DATA_API_S_VER_1 */
__le32 mac_type;
__le32 tsf_id;
u8 node_addr[6];
__le16 reserved_for_node_addr;
u8 bssid_addr[6];
__le16 reserved_for_bssid_addr;
__le32 cck_rates;
__le32 ofdm_rates;
__le32 protection_flags;
__le32 cck_short_preamble;
__le32 short_slot;
__le32 filter_flags;
/* MAC_QOS_PARAM_API_S_VER_1 */
__le32 qos_flags;
struct iwl_ac_qos ac[AC_NUM+1];
/* MAC_CONTEXT_COMMON_DATA_API_S */
union {
struct iwl_mac_data_ap ap;
struct iwl_mac_data_go go;
struct iwl_mac_data_sta sta;
struct iwl_mac_data_p2p_sta p2p_sta;
struct iwl_mac_data_p2p_dev p2p_dev;
struct iwl_mac_data_pibss pibss;
struct iwl_mac_data_ibss ibss;
};
} __packed; /* MAC_CONTEXT_CMD_API_S_VER_1 */
static inline u32 iwl_mvm_reciprocal(u32 v)
{
if (!v)
return 0;
return 0xFFFFFFFF / v;
}
#endif /* __fw_api_mac_h__ */
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_power_h__
#define __fw_api_power_h__
/* Power Management Commands, Responses, Notifications */
/**
* enum iwl_scan_flags - masks for power table command flags
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
* '1' Driver enables PM (use rest of parameters)
* @POWER_FLAGS_SLEEP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* '1' PM could sleep over DTIM till listen Interval.
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
* @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
* access categories are both delivery and trigger enabled.
* @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
*/
enum iwl_power_flags {
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(0),
POWER_FLAGS_SLEEP_OVER_DTIM_MSK = BIT(1),
POWER_FLAGS_LPRX_ENA_MSK = BIT(2),
POWER_FLAGS_SNOOZE_ENA_MSK = BIT(3),
POWER_FLAGS_BT_SCO_ENA = BIT(4),
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(5)
};
/**
* struct iwl_powertable_cmd - Power Table Command
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
*
* @id_and_color: MAC contex identifier
* @action: Action on context - no action, add new,
* modify existent, remove
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
* @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
* PSM transition - uAPSD
* @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
* PSM transition - uAPSD
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
* @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
* @snooze_interval: TBD
* @snooze_window: TBD
* @snooze_step: TBD
* @qndp_tid: TBD
* @uapsd_ac_flags: TBD
* @uapsd_max_sp: TBD
*/
struct iwl_powertable_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
__le16 flags;
u8 reserved;
__le16 keep_alive_seconds;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
__le32 rx_data_timeout_uapsd;
__le32 tx_data_timeout_uapsd;
u8 lprx_rssi_threshold;
u8 num_skip_dtim;
__le16 snooze_interval;
__le16 snooze_window;
u8 snooze_step;
u8 qndp_tid;
u8 uapsd_ac_flags;
u8 uapsd_max_sp;
} __packed;
#endif
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_rs_h__
#define __fw_api_rs_h__
#include "fw-api-mac.h"
/*
* These serve as indexes into
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
*/
enum {
IWL_RATE_1M_INDEX = 0,
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
IWL_RATE_2M_INDEX,
IWL_RATE_5M_INDEX,
IWL_RATE_11M_INDEX,
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
IWL_RATE_6M_INDEX,
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
IWL_RATE_9M_INDEX,
IWL_RATE_12M_INDEX,
IWL_RATE_18M_INDEX,
IWL_RATE_24M_INDEX,
IWL_RATE_36M_INDEX,
IWL_RATE_48M_INDEX,
IWL_RATE_54M_INDEX,
IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX,
IWL_RATE_60M_INDEX,
IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
IWL_RATE_COUNT,
};
#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
/* fw API values for legacy bit rates, both OFDM and CCK */
enum {
IWL_RATE_6M_PLCP = 13,
IWL_RATE_9M_PLCP = 15,
IWL_RATE_12M_PLCP = 5,
IWL_RATE_18M_PLCP = 7,
IWL_RATE_24M_PLCP = 9,
IWL_RATE_36M_PLCP = 11,
IWL_RATE_48M_PLCP = 1,
IWL_RATE_54M_PLCP = 3,
IWL_RATE_1M_PLCP = 10,
IWL_RATE_2M_PLCP = 20,
IWL_RATE_5M_PLCP = 55,
IWL_RATE_11M_PLCP = 110,
};
/*
* rate_n_flags bit fields
*
* The 32-bit value has different layouts in the low 8 bites depending on the
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
* for CCK and OFDM).
*
* High-throughput (HT) rate format
* bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM)
* Very High-throughput (VHT) rate format
* bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM)
* Legacy OFDM rate format for bits 7:0
* bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM)
* Legacy CCK rate format for bits 7:0:
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK)
*/
/* Bit 8: (1) HT format, (0) legacy or VHT format */
#define RATE_MCS_HT_POS 8
#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS)
/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */
#define RATE_MCS_CCK_POS 9
#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS)
/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */
#define RATE_MCS_VHT_POS 26
#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS)
/*
* High-throughput (HT) rate format for bits 7:0
*
* 2-0: MCS rate base
* 0) 6 Mbps
* 1) 12 Mbps
* 2) 18 Mbps
* 3) 24 Mbps
* 4) 36 Mbps
* 5) 48 Mbps
* 6) 54 Mbps
* 7) 60 Mbps
* 4-3: 0) Single stream (SISO)
* 1) Dual stream (MIMO)
* 2) Triple stream (MIMO)
* 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
* (bits 7-6 are zero)
*
* Together the low 5 bits work out to the MCS index because we don't
* support MCSes above 15/23, and 0-7 have one stream, 8-15 have two
* streams and 16-23 have three streams. We could also support MCS 32
* which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
*/
#define RATE_HT_MCS_RATE_CODE_MSK 0x7
/* Bit 10: (1) Use Green Field preamble */
#define RATE_HT_MCS_GF_POS 10
#define RATE_HT_MCS_GF_MSK (1 << RATE_HT_MCS_GF_POS)
#define RATE_HT_MCS_INDEX_MSK 0x3f
/*
* Very High-throughput (VHT) rate format for bits 7:0
*
* 3-0: VHT MCS (0-9)
* 5-4: number of streams - 1:
* 0) Single stream (SISO)
* 1) Dual stream (MIMO)
* 2) Triple stream (MIMO)
*/
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
#define RATE_VHT_MCS_NSS_POS 4
#define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS)
/*
* Legacy OFDM rate format for bits 7:0
*
* 3-0: 0xD) 6 Mbps
* 0xF) 9 Mbps
* 0x5) 12 Mbps
* 0x7) 18 Mbps
* 0x9) 24 Mbps
* 0xB) 36 Mbps
* 0x1) 48 Mbps
* 0x3) 54 Mbps
* (bits 7-4 are 0)
*
* Legacy CCK rate format for bits 7:0:
* bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK):
*
* 6-0: 10) 1 Mbps
* 20) 2 Mbps
* 55) 5.5 Mbps
* 110) 11 Mbps
* (bit 7 is 0)
*/
#define RATE_LEGACY_RATE_MSK 0xff
/*
* Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz
* 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT
*/
#define RATE_MCS_CHAN_WIDTH_POS 11
#define RATE_MCS_CHAN_WIDTH_MSK (3 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS)
#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS)
/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
#define RATE_MCS_SGI_POS 13
#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS)
/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */
#define RATE_MCS_ANT_POS 14
#define RATE_MCS_ANT_A_MSK (1 << RATE_MCS_ANT_POS)
#define RATE_MCS_ANT_B_MSK (2 << RATE_MCS_ANT_POS)
#define RATE_MCS_ANT_C_MSK (4 << RATE_MCS_ANT_POS)
#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | \
RATE_MCS_ANT_B_MSK)
#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \
RATE_MCS_ANT_C_MSK)
#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK
#define RATE_MCS_ANT_NUM 3
/* Bit 17-18: (0) SS, (1) SS*2 */
#define RATE_MCS_STBC_POS 17
#define RATE_MCS_STBC_MSK (1 << RATE_MCS_STBC_POS)
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */
#define RATE_MCS_BF_POS 19
#define RATE_MCS_BF_MSK (1 << RATE_MCS_BF_POS)
/* Bit 20: (0) ZLF is off, (1) ZLF is on */
#define RATE_MCS_ZLF_POS 20
#define RATE_MCS_ZLF_MSK (1 << RATE_MCS_ZLF_POS)
/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */
#define RATE_MCS_DUP_POS 24
#define RATE_MCS_DUP_MSK (3 << RATE_MCS_DUP_POS)
/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */
#define RATE_MCS_LDPC_POS 27
#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS)
/* Link Quality definitions */
/* # entries in rate scale table to support Tx retries */
#define LQ_MAX_RETRY_NUM 16
/* Link quality command flags, only this one is available */
#define LQ_FLAG_SET_STA_TLC_RTS_MSK BIT(0)
/**
* struct iwl_lq_cmd - link quality command
* @sta_id: station to update
* @control: not used
* @flags: combination of LQ_FLAG_*
* @mimo_delim: the first SISO index in rs_table, which separates MIMO
* and SISO rates
* @single_stream_ant_msk: best antenna for SISO (can be dual in CDD).
* Should be ANT_[ABC]
* @dual_stream_ant_msk: best antennas for MIMO, combination of ANT_[ABC]
* @initial_rate_index: first index from rs_table per AC category
* @agg_time_limit: aggregation max time threshold in usec/100, meaning
* value of 100 is one usec. Range is 100 to 8000
* @agg_disable_start_th: try-count threshold for starting aggregation.
* If a frame has higher try-count, it should not be selected for
* starting an aggregation sequence.
* @agg_frame_cnt_limit: max frame count in an aggregation.
* 0: no limit
* 1: no aggregation (one frame per aggregation)
* 2 - 0x3f: maximal number of frames (up to 3f == 63)
* @rs_table: array of rates for each TX try, each is rate_n_flags,
* meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP
* @bf_params: beam forming params, currently not used
*/
struct iwl_lq_cmd {
u8 sta_id;
u8 reserved1;
u16 control;
/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
u8 flags;
u8 mimo_delim;
u8 single_stream_ant_msk;
u8 dual_stream_ant_msk;
u8 initial_rate_index[AC_NUM];
/* LINK_QUAL_AGG_PARAMS_API_S_VER_1 */
__le16 agg_time_limit;
u8 agg_disable_start_th;
u8 agg_frame_cnt_limit;
__le32 reserved2;
__le32 rs_table[LQ_MAX_RETRY_NUM];
__le32 bf_params;
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
#endif /* __fw_api_rs_h__ */
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_scan_h__
#define __fw_api_scan_h__
#include "fw-api.h"
/* Scan Commands, Responses, Notifications */
/* Masks for iwl_scan_channel.type flags */
#define SCAN_CHANNEL_TYPE_PASSIVE 0
#define SCAN_CHANNEL_TYPE_ACTIVE BIT(0)
#define SCAN_CHANNEL_NARROW_BAND BIT(22)
/* Max number of IEs for direct SSID scans in a command */
#define PROBE_OPTION_MAX 20
/**
* struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
* @channel: band is selected by iwl_scan_cmd "flags" field
* @tx_gain: gain for analog radio
* @dsp_atten: gain for DSP
* @active_dwell: dwell time for active scan in TU, typically 5-50
* @passive_dwell: dwell time for passive scan in TU, typically 20-500
* @type: type is broken down to these bits:
* bit 0: 0 = passive, 1 = active
* bits 1-20: SSID direct bit map. If any of these bits is set then
* the corresponding SSID IE is transmitted in probe request
* (bit i adds IE in position i to the probe request)
* bit 22: channel width, 0 = regular, 1 = TGj narrow channel
*
* @iteration_count:
* @iteration_interval:
* This struct is used once for each channel in the scan list.
* Each channel can independently select:
* 1) SSID for directed active scans
* 2) Txpower setting (for rate specified within Tx command)
* 3) How long to stay on-channel (behavior may be modified by quiet_time,
* quiet_plcp_th, good_CRC_th)
*
* To avoid uCode errors, make sure the following are true (see comments
* under struct iwl_scan_cmd about max_out_time and quiet_time):
* 1) If using passive_dwell (i.e. passive_dwell != 0):
* active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
* 2) quiet_time <= active_dwell
* 3) If restricting off-channel time (i.e. max_out_time !=0):
* passive_dwell < max_out_time
* active_dwell < max_out_time
*/
struct iwl_scan_channel {
__le32 type;
__le16 channel;
__le16 iteration_count;
__le32 iteration_interval;
__le16 active_dwell;
__le16 passive_dwell;
} __packed; /* SCAN_CHANNEL_CONTROL_API_S_VER_1 */
/**
* struct iwl_ssid_ie - directed scan network information element
*
* Up to 20 of these may appear in REPLY_SCAN_CMD,
* selected by "type" bit field in struct iwl_scan_channel;
* each channel may select different ssids from among the 20 entries.
* SSID IEs get transmitted in reverse order of entry.
*/
struct iwl_ssid_ie {
u8 id;
u8 len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
} __packed; /* SCAN_DIRECT_SSID_IE_API_S_VER_1 */
/**
* iwl_scan_flags - masks for scan command flags
*@SCAN_FLAGS_PERIODIC_SCAN:
*@SCAN_FLAGS_P2P_PUBLIC_ACTION_FRAME_TX:
*@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
*@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
*@SCAN_FLAGS_FRAGMENTED_SCAN:
*/
enum iwl_scan_flags {
SCAN_FLAGS_PERIODIC_SCAN = BIT(0),
SCAN_FLAGS_P2P_PUBLIC_ACTION_FRAME_TX = BIT(1),
SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2),
SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3),
SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4),
};
/**
* enum iwl_scan_type - Scan types for scan command
* @SCAN_TYPE_FORCED:
* @SCAN_TYPE_BACKGROUND:
* @SCAN_TYPE_OS:
* @SCAN_TYPE_ROAMING:
* @SCAN_TYPE_ACTION:
* @SCAN_TYPE_DISCOVERY:
* @SCAN_TYPE_DISCOVERY_FORCED:
*/
enum iwl_scan_type {
SCAN_TYPE_FORCED = 0,
SCAN_TYPE_BACKGROUND = 1,
SCAN_TYPE_OS = 2,
SCAN_TYPE_ROAMING = 3,
SCAN_TYPE_ACTION = 4,
SCAN_TYPE_DISCOVERY = 5,
SCAN_TYPE_DISCOVERY_FORCED = 6,
}; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
/* Maximal number of channels to scan */
#define MAX_NUM_SCAN_CHANNELS 0x24
/**
* struct iwl_scan_cmd - scan request command
* ( SCAN_REQUEST_CMD = 0x80 )
* @len: command length in bytes
* @scan_flags: scan flags from SCAN_FLAGS_*
* @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS)
* @quiet_time: in msecs, dwell this time for active scan on quiet channels
* @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
* this number of packets were received (typically 1)
* @passive2active: is auto switching from passive to active allowed (0 or 1)
* @rxchain_sel_flags: RXON_RX_CHAIN_*
* @max_out_time: in usecs, max out of serving channel time
* @suspend_time: how long to pause scan when returning to service channel:
* bits 0-19: beacon interal in usecs (suspend before executing)
* bits 20-23: reserved
* bits 24-31: number of beacons (suspend between channels)
* @rxon_flags: RXON_FLG_*
* @filter_flags: RXON_FILTER_*
* @tx_cmd: for active scans (zero for passive), w/o payload,
* no RS so specify TX rate
* @direct_scan: direct scan SSIDs
* @type: one of SCAN_TYPE_*
* @repeats: how many time to repeat the scan
*/
struct iwl_scan_cmd {
__le16 len;
u8 scan_flags;
u8 channel_count;
__le16 quiet_time;
__le16 quiet_plcp_th;
__le16 passive2active;
__le16 rxchain_sel_flags;
__le32 max_out_time;
__le32 suspend_time;
/* RX_ON_FLAGS_API_S_VER_1 */
__le32 rxon_flags;
__le32 filter_flags;
struct iwl_tx_cmd tx_cmd;
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
__le32 type;
__le32 repeats;
/*
* Probe request frame, followed by channel list.
*
* Size of probe request frame is specified by byte count in tx_cmd.
* Channel list follows immediately after probe request frame.
* Number of channels in list is specified by channel_count.
* Each channel in list is of type:
*
* struct iwl_scan_channel channels[0];
*
* NOTE: Only one band of channels can be scanned per pass. You
* must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
* for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
* before requesting another scan.
*/
u8 data[0];
} __packed; /* SCAN_REQUEST_FIXED_PART_API_S_VER_5 */
/* Response to scan request contains only status with one of these values */
#define SCAN_RESPONSE_OK 0x1
#define SCAN_RESPONSE_ERROR 0x2
/*
* SCAN_ABORT_CMD = 0x81
* When scan abort is requested, the command has no fields except the common
* header. The response contains only a status with one of these values.
*/
#define SCAN_ABORT_POSSIBLE 0x1
#define SCAN_ABORT_IGNORED 0x2 /* no pending scans */
/* TODO: complete documentation */
#define SCAN_OWNER_STATUS 0x1
#define MEASURE_OWNER_STATUS 0x2
/**
* struct iwl_scan_start_notif - notifies start of scan in the device
* ( SCAN_START_NOTIFICATION = 0x82 )
* @tsf_low: TSF timer (lower half) in usecs
* @tsf_high: TSF timer (higher half) in usecs
* @beacon_timer: structured as follows:
* bits 0:19 - beacon interval in usecs
* bits 20:23 - reserved (0)
* bits 24:31 - number of beacons
* @channel: which channel is scanned
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
* @status: one of *_OWNER_STATUS
*/
struct iwl_scan_start_notif {
__le32 tsf_low;
__le32 tsf_high;
__le32 beacon_timer;
u8 channel;
u8 band;
u8 reserved[2];
__le32 status;
} __packed; /* SCAN_START_NTF_API_S_VER_1 */
/* scan results probe_status first bit indicates success */
#define SCAN_PROBE_STATUS_OK 0
#define SCAN_PROBE_STATUS_TX_FAILED BIT(0)
/* error statuses combined with TX_FAILED */
#define SCAN_PROBE_STATUS_FAIL_TTL BIT(1)
#define SCAN_PROBE_STATUS_FAIL_BT BIT(2)
/* How many statistics are gathered for each channel */
#define SCAN_RESULTS_STATISTICS 1
/**
* enum iwl_scan_complete_status - status codes for scan complete notifications
* @SCAN_COMP_STATUS_OK: scan completed successfully
* @SCAN_COMP_STATUS_ABORT: scan was aborted by user
* @SCAN_COMP_STATUS_ERR_SLEEP: sending null sleep packet failed
* @SCAN_COMP_STATUS_ERR_CHAN_TIMEOUT: timeout before channel is ready
* @SCAN_COMP_STATUS_ERR_PROBE: sending probe request failed
* @SCAN_COMP_STATUS_ERR_WAKEUP: sending null wakeup packet failed
* @SCAN_COMP_STATUS_ERR_ANTENNAS: invalid antennas chosen at scan command
* @SCAN_COMP_STATUS_ERR_INTERNAL: internal error caused scan abort
* @SCAN_COMP_STATUS_ERR_COEX: medium was lost ot WiMax
* @SCAN_COMP_STATUS_P2P_ACTION_OK: P2P public action frame TX was successful
* (not an error!)
* @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repeatition the driver
* asked for
* @SCAN_COMP_STATUS_ERR_ALLOC_TE: scan could not allocate time events
*/
enum iwl_scan_complete_status {
SCAN_COMP_STATUS_OK = 0x1,
SCAN_COMP_STATUS_ABORT = 0x2,
SCAN_COMP_STATUS_ERR_SLEEP = 0x3,
SCAN_COMP_STATUS_ERR_CHAN_TIMEOUT = 0x4,
SCAN_COMP_STATUS_ERR_PROBE = 0x5,
SCAN_COMP_STATUS_ERR_WAKEUP = 0x6,
SCAN_COMP_STATUS_ERR_ANTENNAS = 0x7,
SCAN_COMP_STATUS_ERR_INTERNAL = 0x8,
SCAN_COMP_STATUS_ERR_COEX = 0x9,
SCAN_COMP_STATUS_P2P_ACTION_OK = 0xA,
SCAN_COMP_STATUS_ITERATION_END = 0x0B,
SCAN_COMP_STATUS_ERR_ALLOC_TE = 0x0C,
};
/**
* struct iwl_scan_results_notif - scan results for one channel
* ( SCAN_RESULTS_NOTIFICATION = 0x83 )
* @channel: which channel the results are from
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
* @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
* @num_probe_not_sent: # of request that weren't sent due to not enough time
* @duration: duration spent in channel, in usecs
* @statistics: statistics gathered for this channel
*/
struct iwl_scan_results_notif {
u8 channel;
u8 band;
u8 probe_status;
u8 num_probe_not_sent;
__le32 duration;
__le32 statistics[SCAN_RESULTS_STATISTICS];
} __packed; /* SCAN_RESULT_NTF_API_S_VER_2 */
/**
* struct iwl_scan_complete_notif - notifies end of scanning (all channels)
* ( SCAN_COMPLETE_NOTIFICATION = 0x84 )
* @scanned_channels: number of channels scanned (and number of valid results)
* @status: one of SCAN_COMP_STATUS_*
* @bt_status: BT on/off status
* @last_channel: last channel that was scanned
* @tsf_low: TSF timer (lower half) in usecs
* @tsf_high: TSF timer (higher half) in usecs
* @results: all scan results, only "scanned_channels" of them are valid
*/
struct iwl_scan_complete_notif {
u8 scanned_channels;
u8 status;
u8 bt_status;
u8 last_channel;
__le32 tsf_low;
__le32 tsf_high;
struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS];
} __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
/* scan offload */
#define IWL_MAX_SCAN_CHANNELS 40
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_MAX_PROFILES 11
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
/* Default watchdog (in MS) for scheduled scan iteration */
#define IWL_SCHED_SCAN_WATCHDOG cpu_to_le16(15000)
#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)
#define CAN_ABORT_STATUS 1
#define IWL_FULL_SCAN_MULTIPLIER 5
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
/**
* struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
* @scan_flags: see enum iwl_scan_flags
* @channel_count: channels in channel list
* @quiet_time: dwell time, in milisiconds, on quiet channel
* @quiet_plcp_th: quiet channel num of packets threshold
* @good_CRC_th: passive to active promotion threshold
* @rx_chain: RXON rx chain.
* @max_out_time: max uSec to be out of assoceated channel
* @suspend_time: pause scan this long when returning to service channel
* @flags: RXON flags
* @filter_flags: RXONfilter
* @tx_cmd: tx command for active scan; for 2GHz and for 5GHz.
* @direct_scan: list of SSIDs for directed active scan
* @scan_type: see enum iwl_scan_type.
* @rep_count: repetition count for each scheduled scan iteration.
*/
struct iwl_scan_offload_cmd {
__le16 len;
u8 scan_flags;
u8 channel_count;
__le16 quiet_time;
__le16 quiet_plcp_th;
__le16 good_CRC_th;
__le16 rx_chain;
__le32 max_out_time;
__le32 suspend_time;
/* RX_ON_FLAGS_API_S_VER_1 */
__le32 flags;
__le32 filter_flags;
struct iwl_tx_cmd tx_cmd[2];
/* SCAN_DIRECT_SSID_IE_API_S_VER_1 */
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
__le32 scan_type;
__le32 rep_count;
} __packed;
enum iwl_scan_offload_channel_flags {
IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE = BIT(0),
IWL_SCAN_OFFLOAD_CHANNEL_NARROW = BIT(22),
IWL_SCAN_OFFLOAD_CHANNEL_FULL = BIT(24),
IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL = BIT(25),
};
/**
* iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S
* @type: bitmap - see enum iwl_scan_offload_channel_flags.
* 0: passive (0) or active (1) scan.
* 1-20: directed scan to i'th ssid.
* 22: channel width configuation - 1 for narrow.
* 24: full scan.
* 25: partial scan.
* @channel_number: channel number 1-13 etc.
* @iter_count: repetition count for the channel.
* @iter_interval: interval between two innteration on one channel.
* @dwell_time: entry 0 - active scan, entry 1 - passive scan.
*/
struct iwl_scan_channel_cfg {
__le32 type[IWL_MAX_SCAN_CHANNELS];
__le16 channel_number[IWL_MAX_SCAN_CHANNELS];
__le16 iter_count[IWL_MAX_SCAN_CHANNELS];
__le32 iter_interval[IWL_MAX_SCAN_CHANNELS];
u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2];
} __packed;
/**
* iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S
* @scan_cmd: scan command fixed part
* @channel_cfg: scan channel configuration
* @data: probe request frames (one per band)
*/
struct iwl_scan_offload_cfg {
struct iwl_scan_offload_cmd scan_cmd;
struct iwl_scan_channel_cfg channel_cfg;
u8 data[0];
} __packed;
/**
* iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
* @ssid: MAC address to filter out
* @reported_rssi: AP rssi reported to the host
*/
struct iwl_scan_offload_blacklist {
u8 ssid[ETH_ALEN];
u8 reported_rssi;
u8 reserved;
} __packed;
enum iwl_scan_offload_network_type {
IWL_NETWORK_TYPE_BSS = 1,
IWL_NETWORK_TYPE_IBSS = 2,
IWL_NETWORK_TYPE_ANY = 3,
};
enum iwl_scan_offload_band_selection {
IWL_SCAN_OFFLOAD_SELECT_2_4 = 0x4,
IWL_SCAN_OFFLOAD_SELECT_5_2 = 0x8,
IWL_SCAN_OFFLOAD_SELECT_ANY = 0xc,
};
/**
* iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
* @ssid_index: index to ssid list in fixed part
* @unicast_cipher: encryption olgorithm to match - bitmap
* @aut_alg: authentication olgorithm to match - bitmap
* @network_type: enum iwl_scan_offload_network_type
* @band_selection: enum iwl_scan_offload_band_selection
*/
struct iwl_scan_offload_profile {
u8 ssid_index;
u8 unicast_cipher;
u8 auth_alg;
u8 network_type;
u8 band_selection;
u8 reserved[3];
} __packed;
/**
* iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
* @blaclist: AP list to filter off from scan results
* @profiles: profiles to search for match
* @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list
*/
struct iwl_scan_offload_profile_cfg {
struct iwl_scan_offload_blacklist blacklist[IWL_SCAN_MAX_BLACKLIST_LEN];
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
u8 blacklist_len;
u8 num_profiles;
u8 reserved[2];
} __packed;
/**
* iwl_scan_offload_schedule - schedule of scan offload
* @delay: delay between iterations, in seconds.
* @iterations: num of scan iterations
* @full_scan_mul: number of partial scans before each full scan
*/
struct iwl_scan_offload_schedule {
u16 delay;
u8 iterations;
u8 full_scan_mul;
} __packed;
/*
* iwl_scan_offload_flags
*
* IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID: filter mode - upload every beacon or match
* ssid list.
* IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
* IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan
* on A band.
*/
enum iwl_scan_offload_flags {
IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID = BIT(0),
IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2),
IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN = BIT(3),
};
/**
* iwl_scan_offload_req - scan offload request command
* @flags: bitmap - enum iwl_scan_offload_flags.
* @watchdog: maximum scan duration in TU.
* @delay: delay in seconds before first iteration.
* @schedule_line: scan offload schedule, for fast and regular scan.
*/
struct iwl_scan_offload_req {
__le16 flags;
__le16 watchdog;
__le16 delay;
__le16 reserved;
struct iwl_scan_offload_schedule schedule_line[2];
} __packed;
enum iwl_scan_offload_compleate_status {
IWL_SCAN_OFFLOAD_COMPLETED = 1,
IWL_SCAN_OFFLOAD_ABORTED = 2,
};
/**
* iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1
* @last_schedule_line: last schedule line executed (fast or regular)
* @last_schedule_iteration: last scan iteration executed before scan abort
* @status: enum iwl_scan_offload_compleate_status
*/
struct iwl_scan_offload_complete {
u8 last_schedule_line;
u8 last_schedule_iteration;
u8 status;
u8 reserved;
} __packed;
#endif
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 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 __fw_api_sta_h__
#define __fw_api_sta_h__
/**
* enum iwl_sta_flags - flags for the ADD_STA host command
* @STA_FLG_REDUCED_TX_PWR_CTRL:
* @STA_FLG_REDUCED_TX_PWR_DATA:
* @STA_FLG_FLG_ANT_MSK: Antenna selection
* @STA_FLG_PS: set if STA is in Power Save
* @STA_FLG_INVALID: set if STA is invalid
* @STA_FLG_DLP_EN: Direct Link Protocol is enabled
* @STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs
* @STA_FLG_DRAIN_FLOW: drain flow
* @STA_FLG_PAN: STA is for PAN interface
* @STA_FLG_CLASS_AUTH:
* @STA_FLG_CLASS_ASSOC:
* @STA_FLG_CLASS_MIMO_PROT:
* @STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU
* @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
* @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
* initialised by driver and can be updated by fw upon reception of
* action frames that can change the channel width. When cleared the fw
* will send all the frames in 20MHz even when FAT channel is requested.
* @STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the
* driver and can be updated by fw upon reception of action frames.
* @STA_FLG_MFP_EN: Management Frame Protection
*/
enum iwl_sta_flags {
STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3),
STA_FLG_REDUCED_TX_PWR_DATA = BIT(6),
STA_FLG_FLG_ANT_A = (1 << 4),
STA_FLG_FLG_ANT_B = (2 << 4),
STA_FLG_FLG_ANT_MSK = (STA_FLG_FLG_ANT_A |
STA_FLG_FLG_ANT_B),
STA_FLG_PS = BIT(8),
STA_FLG_INVALID = BIT(9),
STA_FLG_DLP_EN = BIT(10),
STA_FLG_SET_ALL_KEYS = BIT(11),
STA_FLG_DRAIN_FLOW = BIT(12),
STA_FLG_PAN = BIT(13),
STA_FLG_CLASS_AUTH = BIT(14),
STA_FLG_CLASS_ASSOC = BIT(15),
STA_FLG_RTS_MIMO_PROT = BIT(17),
STA_FLG_MAX_AGG_SIZE_SHIFT = 19,
STA_FLG_MAX_AGG_SIZE_8K = (0 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_16K = (1 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_32K = (2 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_64K = (3 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_128K = (4 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_256K = (5 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_512K = (6 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_1024K = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_MAX_AGG_SIZE_MSK = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT),
STA_FLG_AGG_MPDU_DENS_SHIFT = 23,
STA_FLG_AGG_MPDU_DENS_2US = (4 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_4US = (5 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_8US = (6 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_16US = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_AGG_MPDU_DENS_MSK = (7 << STA_FLG_AGG_MPDU_DENS_SHIFT),
STA_FLG_FAT_EN_20MHZ = (0 << 26),
STA_FLG_FAT_EN_40MHZ = (1 << 26),
STA_FLG_FAT_EN_80MHZ = (2 << 26),
STA_FLG_FAT_EN_160MHZ = (3 << 26),
STA_FLG_FAT_EN_MSK = (3 << 26),
STA_FLG_MIMO_EN_SISO = (0 << 28),
STA_FLG_MIMO_EN_MIMO2 = (1 << 28),
STA_FLG_MIMO_EN_MIMO3 = (2 << 28),
STA_FLG_MIMO_EN_MSK = (3 << 28),
};
/**
* enum iwl_sta_key_flag - key flags for the ADD_STA host command
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithm
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
* station info array (1 - n 1X mode)
* @STA_KEY_FLG_KEYID_MSK: the index of the key
* @STA_KEY_NOT_VALID: key is invalid
* @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key
* @STA_KEY_MULTICAST: set for multical key
* @STA_KEY_MFP: key is used for Management Frame Protection
*/
enum iwl_sta_key_flag {
STA_KEY_FLG_NO_ENC = (0 << 0),
STA_KEY_FLG_WEP = (1 << 0),
STA_KEY_FLG_CCM = (2 << 0),
STA_KEY_FLG_TKIP = (3 << 0),
STA_KEY_FLG_CMAC = (6 << 0),
STA_KEY_FLG_ENC_UNKNOWN = (7 << 0),
STA_KEY_FLG_EN_MSK = (7 << 0),
STA_KEY_FLG_WEP_KEY_MAP = BIT(3),
STA_KEY_FLG_KEYID_POS = 8,
STA_KEY_FLG_KEYID_MSK = (3 << STA_KEY_FLG_KEYID_POS),
STA_KEY_NOT_VALID = BIT(11),
STA_KEY_FLG_WEP_13BYTES = BIT(12),
STA_KEY_MULTICAST = BIT(14),
STA_KEY_MFP = BIT(15),
};
/**
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
* @STA_MODIFY_KEY: this command modifies %key
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
* @STA_MODIFY_TX_RATE: unused
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
* @STA_MODIFY_PROT_TH:
* @STA_MODIFY_QUEUES: modify the queues used by this station
*/
enum iwl_sta_modify_flag {
STA_MODIFY_KEY = BIT(0),
STA_MODIFY_TID_DISABLE_TX = BIT(1),
STA_MODIFY_TX_RATE = BIT(2),
STA_MODIFY_ADD_BA_TID = BIT(3),
STA_MODIFY_REMOVE_BA_TID = BIT(4),
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
STA_MODIFY_PROT_TH = BIT(6),
STA_MODIFY_QUEUES = BIT(7),
};
#define STA_MODE_MODIFY 1
/**
* enum iwl_sta_sleep_flag - type of sleep of the station
* @STA_SLEEP_STATE_AWAKE:
* @STA_SLEEP_STATE_PS_POLL:
* @STA_SLEEP_STATE_UAPSD:
*/
enum iwl_sta_sleep_flag {
STA_SLEEP_STATE_AWAKE = 0,
STA_SLEEP_STATE_PS_POLL = BIT(0),
STA_SLEEP_STATE_UAPSD = BIT(1),
};
/* STA ID and color bits definitions */
#define STA_ID_SEED (0x0f)
#define STA_ID_POS (0)
#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS)
#define STA_COLOR_SEED (0x7)
#define STA_COLOR_POS (4)
#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS)
#define STA_ID_N_COLOR_GET_COLOR(id_n_color) \
(((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS)
#define STA_ID_N_COLOR_GET_ID(id_n_color) \
(((id_n_color) & STA_ID_MSK) >> STA_ID_POS)
#define STA_KEY_MAX_NUM (16)
#define STA_KEY_IDX_INVALID (0xff)
#define STA_KEY_MAX_DATA_KEY_NUM (4)
#define IWL_MAX_GLOBAL_KEYS (4)
#define STA_KEY_LEN_WEP40 (5)
#define STA_KEY_LEN_WEP104 (13)
/**
* struct iwl_mvm_keyinfo - key information
* @key_flags: type %iwl_sta_key_flag
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
* @key_offset: key offset in the fw's key table
* @key: 16-byte unicast decryption key
* @tx_secur_seq_cnt: initial RSC / PN needed for replay check
* @hw_tkip_mic_rx_key: byte: MIC Rx Key - used for TKIP only
* @hw_tkip_mic_tx_key: byte: MIC Tx Key - used for TKIP only
*/
struct iwl_mvm_keyinfo {
__le16 key_flags;
u8 tkip_rx_tsc_byte2;
u8 reserved1;
__le16 tkip_rx_ttak[5];
u8 key_offset;
u8 reserved2;
u8 key[16];
__le64 tx_secur_seq_cnt;
__le64 hw_tkip_mic_rx_key;
__le64 hw_tkip_mic_tx_key;
} __packed;
/**
* struct iwl_mvm_add_sta_cmd - Add / modify a station in the fw's station table
* ( REPLY_ADD_STA = 0x18 )
* @add_modify: 1: modify existing, 0: add new station
* @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent
* @multicast_tx_key_id: multicast tx key id. Relevant only when multicast key
* sent
* @mac_id_n_color: the Mac context this station belongs to
* @addr[ETH_ALEN]: station's MAC address
* @sta_id: index of station in uCode's station table
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
* alone. 1 - modify, 0 - don't change.
* @key: look at %iwl_mvm_keyinfo
* @station_flags: look at %iwl_sta_flags
* @station_flags_msk: what of %station_flags have changed
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
* @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx)
* Set %STA_MODIFY_REMOVE_BA_TID to use this field
* @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with
* add_immediate_ba_tid.
* @sleep_tx_count: number of packets to transmit to station even though it is
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
* @sleep_state_flags: Look at %iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
* attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD).
*
* ADD_STA sets up the table entry for one station, either creating a new
* entry, or modifying a pre-existing one.
*/
struct iwl_mvm_add_sta_cmd {
u8 add_modify;
u8 unicast_tx_key_id;
u8 multicast_tx_key_id;
u8 reserved1;
__le32 mac_id_n_color;
u8 addr[ETH_ALEN];
__le16 reserved2;
u8 sta_id;
u8 modify_mask;
__le16 reserved3;
struct iwl_mvm_keyinfo key;
__le32 station_flags;
__le32 station_flags_msk;
__le16 tid_disable_tx;
__le16 reserved4;
u8 add_immediate_ba_tid;
u8 remove_immediate_ba_tid;
__le16 add_immediate_ba_ssn;
__le16 sleep_tx_count;
__le16 sleep_state_flags;
__le16 assoc_id;
__le16 beamform_flags;
__le32 tfd_queue_msk;
} __packed; /* ADD_STA_CMD_API_S_VER_5 */
/**
* enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command
* @ADD_STA_SUCCESS: operation was executed successfully
* @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table
* @ADD_STA_IMMEDIATE_BA_FAILURE: can't add Rx block ack session
* @ADD_STA_MODIFY_NON_EXISTING_STA: driver requested to modify a station that
* doesn't exist.
*/
enum iwl_mvm_add_sta_rsp_status {
ADD_STA_SUCCESS = 0x1,
ADD_STA_STATIONS_OVERLOAD = 0x2,
ADD_STA_IMMEDIATE_BA_FAILURE = 0x4,
ADD_STA_MODIFY_NON_EXISTING_STA = 0x8,
};
/**
* struct iwl_mvm_rm_sta_cmd - Add / modify a station in the fw's station table
* ( REMOVE_STA = 0x19 )
* @sta_id: the station id of the station to be removed
*/
struct iwl_mvm_rm_sta_cmd {
u8 sta_id;
u8 reserved[3];
} __packed; /* REMOVE_STA_CMD_API_S_VER_2 */
/**
* struct iwl_mvm_mgmt_mcast_key_cmd
* ( MGMT_MCAST_KEY = 0x1f )
* @ctrl_flags: %iwl_sta_key_flag
* @IGTK:
* @K1: IGTK master key
* @K2: IGTK sub key
* @sta_id: station ID that support IGTK
* @key_id:
* @receive_seq_cnt: initial RSC/PN needed for replay check
*/
struct iwl_mvm_mgmt_mcast_key_cmd {
__le32 ctrl_flags;
u8 IGTK[16];
u8 K1[16];
u8 K2[16];
__le32 key_id;
__le32 sta_id;
__le64 receive_seq_cnt;
} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */
struct iwl_mvm_wep_key {
u8 key_index;
u8 key_offset;
__le16 reserved1;
u8 key_size;
u8 reserved2[3];
u8 key[16];
} __packed;
struct iwl_mvm_wep_key_cmd {
__le32 mac_id_n_color;
u8 num_keys;
u8 decryption_type;
u8 flags;
u8 reserved;
struct iwl_mvm_wep_key wep_key[0];
} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */
#endif /* __fw_api_sta_h__ */
此差异已折叠。
此差异已折叠。
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <net/mac80211.h>
#include "iwl-trans.h"
#include "iwl-op-mode.h"
#include "iwl-fw.h"
#include "iwl-debug.h"
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-eeprom-parse.h"
#include "mvm.h"
#include "iwl-phy-db.h"
#define MVM_UCODE_ALIVE_TIMEOUT HZ
#define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
#define UCODE_VALID_OK cpu_to_le32(0x1)
/* Default calibration values for WkP - set to INIT image w/o running */
static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
0x00, 0x18, 0x00 };
static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f };
static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
0x00 };
static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
struct iwl_calib_default_data {
u16 size;
void *data;
};
#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
[5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
[6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
[7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
[8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
[10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
};
struct iwl_mvm_alive_data {
bool valid;
u32 scd_base_addr;
};
static inline const struct fw_img *
iwl_get_ucode_image(struct iwl_mvm *mvm, enum iwl_ucode_type ucode_type)
{
if (ucode_type >= IWL_UCODE_TYPE_MAX)
return NULL;
return &mvm->fw->img[ucode_type];
}
static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
{
struct iwl_tx_ant_cfg_cmd tx_ant_cmd = {
.valid = cpu_to_le32(valid_tx_ant),
};
IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
sizeof(tx_ant_cmd), &tx_ant_cmd);
}
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
struct iwl_mvm_alive_data *alive_data = data;
struct mvm_alive_resp *palive;
palive = (void *)pkt->data;
mvm->error_event_table = le32_to_cpu(palive->error_event_table_ptr);
mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr);
alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
le16_to_cpu(palive->status), palive->ver_type,
palive->ver_subtype);
return true;
}
static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_phy_db *phy_db = data;
if (pkt->hdr.cmd != CALIB_RES_NOTIF_PHY_DB) {
WARN_ON(pkt->hdr.cmd != INIT_COMPLETE_NOTIF);
return true;
}
WARN_ON(iwl_phy_db_set_section(phy_db, pkt, GFP_ATOMIC));
return false;
}
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
enum iwl_ucode_type ucode_type)
{
struct iwl_notification_wait alive_wait;
struct iwl_mvm_alive_data alive_data;
const struct fw_img *fw;
int ret, i;
enum iwl_ucode_type old_type = mvm->cur_ucode;
static const u8 alive_cmd[] = { MVM_ALIVE };
mvm->cur_ucode = ucode_type;
fw = iwl_get_ucode_image(mvm, ucode_type);
mvm->ucode_loaded = false;
if (!fw)
return -EINVAL;
iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
alive_cmd, ARRAY_SIZE(alive_cmd),
iwl_alive_fn, &alive_data);
ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
if (ret) {
mvm->cur_ucode = old_type;
iwl_remove_notification(&mvm->notif_wait, &alive_wait);
return ret;
}
/*
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
*/
ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
MVM_UCODE_ALIVE_TIMEOUT);
if (ret) {
mvm->cur_ucode = old_type;
return ret;
}
if (!alive_data.valid) {
IWL_ERR(mvm, "Loaded ucode is not valid!\n");
mvm->cur_ucode = old_type;
return -EIO;
}
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
/*
* Note: all the queues are enabled as part of the interface
* initialization, but in firmware restart scenarios they
* could be stopped, so wake them up. In firmware restart,
* mac80211 will have the queues stopped as well until the
* reconfiguration completes. During normal startup, they
* will be empty.
*/
for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE)
mvm->queue_to_mac80211[i] = i;
else
mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
atomic_set(&mvm->queue_stop_count[i], 0);
}
mvm->transport_queue_stop = 0;
mvm->ucode_loaded = true;
return 0;
}
#define IWL_HW_REV_ID_RAINBOW 0x2
#define IWL_PROJ_TYPE_LHP 0x5
static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
{
struct iwl_nvm_data *data = mvm->nvm_data;
/* Temp calls to static definitions, will be changed to CSR calls */
u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
u8 project_type = IWL_PROJ_TYPE_LHP;
return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
(hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
(data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
}
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
{
struct iwl_phy_cfg_cmd phy_cfg_cmd;
enum iwl_ucode_type ucode_type = mvm->cur_ucode;
/* Set parameters */
phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
phy_cfg_cmd.calib_control.event_trigger =
mvm->fw->default_calib[ucode_type].event_trigger;
phy_cfg_cmd.calib_control.flow_trigger =
mvm->fw->default_calib[ucode_type].flow_trigger;
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC,
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
}
/* Starting with the new PHY DB implementation - New calibs are enabled */
/* Value - 0x405e7 */
#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\
IWL_CALIB_CFG_TEMPERATURE_IDX |\
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
IWL_CALIB_CFG_DC_IDX |\
IWL_CALIB_CFG_BB_FILTER_IDX |\
IWL_CALIB_CFG_LO_LEAKAGE_IDX |\
IWL_CALIB_CFG_TX_IQ_IDX |\
IWL_CALIB_CFG_RX_IQ_IDX |\
IWL_CALIB_CFG_AGC_IDX)
#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0
/* Value 0x41567 */
#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\
IWL_CALIB_CFG_TEMPERATURE_IDX |\
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
IWL_CALIB_CFG_BB_FILTER_IDX |\
IWL_CALIB_CFG_DC_IDX |\
IWL_CALIB_CFG_TX_IQ_IDX |\
IWL_CALIB_CFG_RX_IQ_IDX |\
IWL_CALIB_CFG_SENSITIVITY_IDX |\
IWL_CALIB_CFG_AGC_IDX)
#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\
IWL_CALIB_CFG_TEMPERATURE_IDX |\
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
IWL_CALIB_CFG_TX_PWR_IDX |\
IWL_CALIB_CFG_DC_IDX |\
IWL_CALIB_CFG_TX_IQ_IDX |\
IWL_CALIB_CFG_SENSITIVITY_IDX)
/*
* Sets the calibrations trigger values that will be sent to the FW for runtime
* and init calibrations.
* The ones given in the FW TLV are not correct.
*/
static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
{
struct iwl_tlv_calib_ctrl default_calib;
/*
* WkP FW TLV calib bits are wrong, overwrite them.
* This defines the dynamic calibrations which are implemented in the
* uCode both for init(flow) calculation and event driven calibs.
*/
/* Init Image */
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
if (default_calib.event_trigger !=
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
IWL_ERR(mvm,
"Updating the event calib for INIT image: 0x%x -> 0x%x\n",
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
default_calib.event_trigger);
if (default_calib.flow_trigger !=
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
IWL_ERR(mvm,
"Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
default_calib.flow_trigger);
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
IWL_ERR(mvm,
"Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
default_calib.event_trigger,
default_calib.flow_trigger);
/* Run time image */
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
if (default_calib.event_trigger !=
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
IWL_ERR(mvm,
"Updating the event calib for RT image: 0x%x -> 0x%x\n",
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
default_calib.event_trigger);
if (default_calib.flow_trigger !=
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
IWL_ERR(mvm,
"Updating the flow calib for RT image: 0x%x -> 0x%x\n",
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
default_calib.flow_trigger);
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
IWL_ERR(mvm,
"Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
default_calib.event_trigger,
default_calib.flow_trigger);
}
static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
{
u8 cmd_raw[16]; /* holds the variable size commands */
struct iwl_set_calib_default_cmd *cmd =
(struct iwl_set_calib_default_cmd *)cmd_raw;
int ret, i;
/* Setting default values for calibrations we don't run */
for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
u16 cmd_len;
if (wkp_calib_default_data[i].size == 0)
continue;
memset(cmd_raw, 0, sizeof(cmd_raw));
cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
cmd->calib_index = cpu_to_le16(i);
cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
"Need to enlarge cmd_raw to %d\n", cmd_len))
break;
memcpy(cmd->data, wkp_calib_default_data[i].data,
wkp_calib_default_data[i].size);
ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
sizeof(*cmd) +
wkp_calib_default_data[i].size,
cmd);
if (ret)
return ret;
}
return 0;
}
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
{
struct iwl_notification_wait calib_wait;
static const u8 init_complete[] = {
INIT_COMPLETE_NOTIF,
CALIB_RES_NOTIF_PHY_DB
};
int ret;
lockdep_assert_held(&mvm->mutex);
if (mvm->init_ucode_run)
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
&calib_wait,
init_complete,
ARRAY_SIZE(init_complete),
iwl_wait_phy_db_entry,
mvm->phy_db);
/* Will also start the device */
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_INIT);
if (ret) {
IWL_ERR(mvm, "Failed to start INIT ucode: %d\n", ret);
goto error;
}
if (read_nvm) {
/* Read nvm */
ret = iwl_nvm_init(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
goto error;
}
}
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
WARN_ON(ret);
/* Override the calibrations from TLV and the const of fw */
iwl_set_default_calib_trigger(mvm);
/* WkP doesn't have all calibrations, need to set default values */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
ret = iwl_set_default_calibrations(mvm);
if (ret)
goto error;
}
/*
* Send phy configurations command to init uCode
* to start the 16.0 uCode init image internal calibrations.
*/
ret = iwl_send_phy_cfg_cmd(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to run INIT calibrations: %d\n",
ret);
goto error;
}
/*
* Some things may run in the background now, but we
* just wait for the calibration complete notification.
*/
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
if (!ret)
mvm->init_ucode_run = true;
goto out;
error:
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out:
if (!iwlmvm_mod_params.init_dbg) {
iwl_trans_stop_device(mvm->trans);
} else if (!mvm->nvm_data) {
/* we want to debug INIT and we have no NVM - fake */
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
sizeof(struct ieee80211_channel) +
sizeof(struct ieee80211_rate),
GFP_KERNEL);
if (!mvm->nvm_data)
return -ENOMEM;
mvm->nvm_data->valid_rx_ant = 1;
mvm->nvm_data->valid_tx_ant = 1;
mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
mvm->nvm_data->bands[0].n_channels = 1;
mvm->nvm_data->bands[0].n_bitrates = 1;
mvm->nvm_data->bands[0].bitrates =
(void *)mvm->nvm_data->channels + 1;
mvm->nvm_data->bands[0].bitrates->hw_value = 10;
}
return ret;
}
#define UCODE_CALIB_TIMEOUT (2*HZ)
int iwl_mvm_up(struct iwl_mvm *mvm)
{
int ret, i;
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
if (ret)
return ret;
/* If we were in RFKILL during module loading, load init ucode now */
if (!mvm->init_ucode_run) {
ret = iwl_run_init_mvm_ucode(mvm, false);
if (ret && !iwlmvm_mod_params.init_dbg) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
goto error;
}
}
if (iwlmvm_mod_params.init_dbg)
return 0;
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
if (ret) {
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
goto error;
}
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
if (ret)
goto error;
/* Send phy db control command and then phy db calibration*/
ret = iwl_send_phy_db_data(mvm->phy_db);
if (ret)
goto error;
ret = iwl_send_phy_cfg_cmd(mvm);
if (ret)
goto error;
/* init the fw <-> mac80211 STA mapping */
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
/* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm);
if (ret)
goto error;
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
iwl_trans_stop_device(mvm->trans);
return ret;
}
int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
{
int ret, i;
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
if (ret)
return ret;
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_WOWLAN);
if (ret) {
IWL_ERR(mvm, "Failed to start WoWLAN firmware: %d\n", ret);
goto error;
}
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
if (ret)
goto error;
/* Send phy db control command and then phy db calibration*/
ret = iwl_send_phy_db_data(mvm->phy_db);
if (ret)
goto error;
ret = iwl_send_phy_cfg_cmd(mvm);
if (ret)
goto error;
/* init the fw <-> mac80211 STA mapping */
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
/* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm);
if (ret)
goto error;
return 0;
error:
iwl_trans_stop_device(mvm->trans);
return ret;
}
int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
u32 flags = le32_to_cpu(card_state_notif->flags);
IWL_DEBUG_RF_KILL(mvm, "Card state received: HW:%s SW:%s CT:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
(flags & SW_CARD_DISABLED) ? "Kill" : "On",
(flags & CT_KILL_CARD_DISABLED) ?
"Reached" : "Not reached");
if (flags & CARD_DISABLED_MSK)
iwl_write32(mvm->trans, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
return 0;
}
int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_radio_version_notif *radio_version = (void *)pkt->data;
/* TODO: what to do with that? */
IWL_DEBUG_INFO(mvm,
"Radio version: flavor: 0x%08x, step 0x%08x, dash 0x%08x\n",
le32_to_cpu(radio_version->radio_flavor),
le32_to_cpu(radio_version->radio_step),
le32_to_cpu(radio_version->radio_dash));
return 0;
}
/******************************************************************************
*
* 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) 2012 - 2013 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) 2012 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <linux/leds.h>
#include "iwl-io.h"
#include "iwl-csr.h"
#include "mvm.h"
/* Set led register on */
static void iwl_mvm_led_enable(struct iwl_mvm *mvm)
{
iwl_write32(mvm->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON);
}
/* Set led register off */
static void iwl_mvm_led_disable(struct iwl_mvm *mvm)
{
iwl_write32(mvm->trans, CSR_LED_REG, CSR_LED_REG_TURN_OFF);
}
static void iwl_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct iwl_mvm *mvm = container_of(led_cdev, struct iwl_mvm, led);
if (brightness > 0)
iwl_mvm_led_enable(mvm);
else
iwl_mvm_led_disable(mvm);
}
int iwl_mvm_leds_init(struct iwl_mvm *mvm)
{
int mode = iwlwifi_mod_params.led_mode;
int ret;
switch (mode) {
case IWL_LED_DEFAULT:
case IWL_LED_RF_STATE:
mode = IWL_LED_RF_STATE;
break;
case IWL_LED_DISABLE:
IWL_INFO(mvm, "Led disabled\n");
return 0;
default:
return -EINVAL;
};
mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
wiphy_name(mvm->hw->wiphy));
mvm->led.brightness_set = iwl_led_brightness_set;
mvm->led.max_brightness = 1;
if (mode == IWL_LED_RF_STATE)
mvm->led.default_trigger =
ieee80211_get_radio_led_name(mvm->hw);
ret = led_classdev_register(mvm->trans->dev, &mvm->led);
if (ret) {
kfree(mvm->led.name);
IWL_INFO(mvm, "Failed to enable led\n");
return ret;
}
return 0;
}
void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
{
if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE)
return;
led_classdev_unregister(&mvm->led);
kfree(mvm->led.name);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册