Commit 444474dd authored by John W. Linville's avatar John W. Linville
parents a72e25f7 246dd992
......@@ -83,6 +83,8 @@
#define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL3160_NVM_VERSION 0x709
#define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265_NVM_VERSION 0x0a1d
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
......@@ -90,6 +92,9 @@
#define IWL3160_FW_PRE "iwlwifi-3160-"
#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
#define IWL7265_FW_PRE "iwlwifi-7265-"
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
static const struct iwl_base_params iwl7000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
......@@ -182,5 +187,14 @@ const struct iwl_cfg iwl3160_n_cfg = {
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
};
const struct iwl_cfg iwl7265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
......@@ -292,6 +292,7 @@ extern const struct iwl_cfg iwl7260_n_cfg;
extern const struct iwl_cfg iwl3160_2ac_cfg;
extern const struct iwl_cfg iwl3160_2n_cfg;
extern const struct iwl_cfg iwl3160_n_cfg;
extern const struct iwl_cfg iwl7265_2ac_cfg;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
......@@ -394,6 +394,38 @@
#define CSR_DRAM_INT_TBL_ENABLE (1 << 31)
#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)
/* SECURE boot registers */
#define CSR_SECURE_BOOT_CONFIG_ADDR (0x100)
enum secure_boot_config_reg {
CSR_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP = 0x00000001,
CSR_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002,
};
#define CSR_SECURE_BOOT_CPU1_STATUS_ADDR (0x100)
#define CSR_SECURE_BOOT_CPU2_STATUS_ADDR (0x100)
enum secure_boot_status_reg {
CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS = 0x00000003,
CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED = 0x00000002,
CSR_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS = 0x00000004,
CSR_SECURE_BOOT_CPU_STATUS_VERF_FAIL = 0x00000008,
CSR_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL = 0x00000010,
};
#define CSR_UCODE_LOAD_STATUS_ADDR (0x100)
enum secure_load_status_reg {
CSR_CPU_STATUS_LOADING_STARTED = 0x00000001,
CSR_CPU_STATUS_LOADING_COMPLETED = 0x00000002,
CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED = 0x000000F8,
CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK = 0x0000FF00,
};
#define CSR_SECURE_INSPECTOR_CODE_ADDR (0x100)
#define CSR_SECURE_INSPECTOR_DATA_ADDR (0x100)
#define CSR_SECURE_TIME_OUT (100)
#define FH_TCSR_0_REG0 (0x1D00)
/*
* HBUS (Host-side Bus)
*
......
......@@ -483,6 +483,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const u8 *tlv_data;
char buildstr[25];
u32 build;
int num_of_cpus;
if (len < sizeof(*ucode)) {
IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
......@@ -692,6 +693,42 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
goto invalid_tlv_len;
drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_SECURE_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_REGULAR].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len);
drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_INIT].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len);
drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true;
break;
case IWL_UCODE_TLV_NUM_OF_CPU:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
num_of_cpus =
le32_to_cpup((__le32 *)tlv_data);
if (num_of_cpus == 2) {
drv->fw.img[IWL_UCODE_REGULAR].is_dual_cpus =
true;
drv->fw.img[IWL_UCODE_INIT].is_dual_cpus =
true;
drv->fw.img[IWL_UCODE_WOWLAN].is_dual_cpus =
true;
} else if ((num_of_cpus > 2) || (num_of_cpus < 1)) {
IWL_ERR(drv, "Driver support upto 2 CPUs\n");
return -EINVAL;
}
break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
......
......@@ -121,6 +121,10 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SEC_WOWLAN = 21,
IWL_UCODE_TLV_DEF_CALIB = 22,
IWL_UCODE_TLV_PHY_SKU = 23,
IWL_UCODE_TLV_SECURE_SEC_RT = 24,
IWL_UCODE_TLV_SECURE_SEC_INIT = 25,
IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
IWL_UCODE_TLV_NUM_OF_CPU = 27,
};
struct iwl_ucode_tlv {
......
......@@ -75,11 +75,23 @@
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
* @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
* @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
* offload profile config command.
* @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
* @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
* (rather than two) IPv6 addresses
* @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
* @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
* from the probe request template.
* @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping
* connection when going back to D0
* @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
* @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
* @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.
* @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
* @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
* containing CAM (Continuous Active Mode) indication.
*/
enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
......@@ -87,11 +99,20 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5),
IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6),
IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7),
IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8),
IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9),
IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11),
IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12),
IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API = BIT(14),
IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15),
IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16),
IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17),
IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19),
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20),
};
/* The default calibrate table size if not specified by firmware file */
......@@ -133,7 +154,8 @@ enum iwl_ucode_sec {
* For 16.0 uCode and above, there is no differentiation between sections,
* just an offset to the HW address.
*/
#define IWL_UCODE_SECTION_MAX 4
#define IWL_UCODE_SECTION_MAX 6
#define IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU (IWL_UCODE_SECTION_MAX/2)
struct iwl_ucode_capabilities {
u32 max_probe_length;
......@@ -150,6 +172,8 @@ struct fw_desc {
struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX];
bool is_secure;
bool is_dual_cpus;
};
/* uCode version contains 4 values: Major/Minor/API/Serial */
......
......@@ -97,6 +97,8 @@
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
#define APMG_RTC_INT_STT_RFKILL (0x10000000)
/* Device system time */
#define DEVICE_SYSTEM_TIME_REG 0xA0206C
......
This diff is collapsed.
......@@ -70,7 +70,9 @@
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8
#define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30
#define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50
#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50
#define IWL_MVM_PS_SNOOZE_INTERVAL 25
......
This diff is collapsed.
......@@ -246,58 +246,56 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
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,
static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
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");
char buf[64];
int bufsz = sizeof(buf);
int pos = 0;
/*
* TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it
*/
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
mvm->disable_power_off);
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
mvm->disable_power_off_d3);
return count;
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
static ssize_t iwl_dbgfs_disable_power_off_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;
char buf[64] = {};
int ret;
int val;
if (!mvm->ucode_loaded)
return -EIO;
if (copy_from_user(buf, user_buf, sizeof(buf)))
count = min_t(size_t, count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
if (sscanf(buf, "%d", &allow) != 1)
if (!strncmp("disable_power_off_d0=", buf, 21)) {
if (sscanf(buf + 21, "%d", &val) != 1)
return -EINVAL;
mvm->disable_power_off = val;
} else if (!strncmp("disable_power_off_d3=", buf, 21)) {
if (sscanf(buf + 21, "%d", &val) != 1)
return -EINVAL;
mvm->disable_power_off_d3 = val;
} else {
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;
mutex_lock(&mvm->mutex);
ret = iwl_mvm_power_update_device_mode(mvm);
mutex_unlock(&mvm->mutex);
return count;
return ret ?: count;
}
static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
......@@ -371,7 +369,8 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
int val;
int ret;
if (copy_from_user(buf, user_buf, sizeof(buf)))
count = min_t(size_t, count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
if (!strncmp("keep_alive=", buf, 11)) {
......@@ -394,7 +393,9 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
if (sscanf(buf + 16, "%d", &val) != 1)
return -EINVAL;
param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
} else if (!strncmp("disable_power_off=", buf, 18)) {
} else if (!strncmp("disable_power_off=", buf, 18) &&
!(mvm->fw->ucode_capa.flags &
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) {
if (sscanf(buf + 18, "%d", &val) != 1)
return -EINVAL;
param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
......@@ -590,6 +591,12 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
notif->bt_agg_traffic_load);
pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
notif->bt_ci_compliance);
pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
le32_to_cpu(notif->primary_ch_lut));
pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
le32_to_cpu(notif->secondary_ch_lut));
pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
le32_to_cpu(notif->bt_activity_grading));
mutex_unlock(&mvm->mutex);
......@@ -600,6 +607,38 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
}
#undef BT_MBOX_PRINT
static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
char buf[256];
int bufsz = sizeof(buf);
int pos = 0;
mutex_lock(&mvm->mutex);
pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n");
pos += scnprintf(buf+pos, bufsz-pos,
"\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
le64_to_cpu(cmd->bt_primary_ci),
!!cmd->co_run_bw_primary);
pos += scnprintf(buf+pos, bufsz-pos,
"\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
le64_to_cpu(cmd->bt_secondary_ci),
!!cmd->co_run_bw_secondary);
pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
mutex_unlock(&mvm->mutex);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
#define PRINT_STATS_LE32(_str, _val) \
pos += scnprintf(buf + pos, bufsz - pos, \
fmt_table, _str, \
......@@ -615,9 +654,11 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
int pos = 0;
char *buf;
int ret;
int bufsz = sizeof(struct mvm_statistics_rx_phy) * 20 +
sizeof(struct mvm_statistics_rx_non_phy) * 10 +
sizeof(struct mvm_statistics_rx_ht_phy) * 10 + 200;
/* 43 is the size of each data line, 33 is the size of each header */
size_t bufsz =
((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) +
(4 * 33) + 1;
struct mvm_statistics_rx_phy *ofdm;
struct mvm_statistics_rx_phy *cck;
struct mvm_statistics_rx_non_phy *general;
......@@ -712,6 +753,7 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b);
PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c);
PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills);
PRINT_STATS_LE32("mac_id", general->mac_id);
PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu);
pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
......@@ -757,6 +799,59 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
return count;
}
static ssize_t
iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
/* print which antennas were set for the scan command by the user */
pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
if (mvm->scan_rx_ant & ANT_A)
pos += scnprintf(buf + pos, bufsz - pos, "A");
if (mvm->scan_rx_ant & ANT_B)
pos += scnprintf(buf + pos, bufsz - pos, "B");
if (mvm->scan_rx_ant & ANT_C)
pos += scnprintf(buf + pos, bufsz - pos, "C");
pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t
iwl_dbgfs_scan_ant_rxchain_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 buf_size;
u8 scan_rx_ant;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
/* get the argument from the user and check if it is valid */
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
return -EINVAL;
if (scan_rx_ant > ANT_ABC)
return -EINVAL;
if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw))
return -EINVAL;
/* change the rx antennas for scan command */
mvm->scan_rx_ant = scan_rx_ant;
return count;
}
static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
enum iwl_dbgfs_bf_mask param, int value)
{
......@@ -968,7 +1063,8 @@ static ssize_t iwl_dbgfs_d3_sram_write(struct file *file,
char buf[8] = {};
int store;
if (copy_from_user(buf, user_buf, sizeof(buf)))
count = min_t(size_t, count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
if (sscanf(buf, "%d", &store) != 1)
......@@ -1063,10 +1159,12 @@ MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
MVM_DEBUGFS_READ_FILE_OPS(stations);
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off);
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain);
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram);
#endif
......@@ -1087,10 +1185,14 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
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(bt_notif, 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);
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
S_IWUSR | S_IRUSR);
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
......
......@@ -82,6 +82,8 @@
* @BT_USE_DEFAULTS:
* @BT_SYNC_2_BT_DISABLE:
* @BT_COEX_CORUNNING_TBL_EN:
*
* The COEX_MODE must be set for each command. Even if it is not changed.
*/
enum iwl_bt_coex_flags {
BT_CH_PRIMARY_EN = BIT(0),
......@@ -95,14 +97,16 @@ enum iwl_bt_coex_flags {
BT_COEX_NW = 0x3 << BT_COEX_MODE_POS,
BT_USE_DEFAULTS = BIT(6),
BT_SYNC_2_BT_DISABLE = BIT(7),
/*
* For future use - when the flags will be enlarged
* BT_COEX_CORUNNING_TBL_EN = BIT(8),
*/
BT_COEX_CORUNNING_TBL_EN = BIT(8),
BT_COEX_MPLUT_TBL_EN = BIT(9),
/* Bit 10 is reserved */
BT_COEX_WF_PRIO_BOOST_CHECK_EN = BIT(11),
};
/*
* indicates what has changed in the BT_COEX command.
* BT_VALID_ENABLE must be set for each command. Commands without this bit will
* discarded by the firmware
*/
enum iwl_bt_coex_valid_bit_msk {
BT_VALID_ENABLE = BIT(0),
......@@ -121,11 +125,8 @@ enum iwl_bt_coex_valid_bit_msk {
BT_VALID_CORUN_LUT_40 = BIT(13),
BT_VALID_ANT_ISOLATION = BIT(14),
BT_VALID_ANT_ISOLATION_THRS = BIT(15),
/*
* For future use - when the valid flags will be enlarged
* BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16),
* BT_VALID_TXRX_MAX_FREQ_0 = BIT(17),
*/
BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16),
BT_VALID_TXRX_MAX_FREQ_0 = BIT(17),
};
/**
......@@ -142,48 +143,88 @@ enum iwl_bt_reduced_tx_power {
BT_REDUCED_TX_POWER_DATA = BIT(1),
};
enum iwl_bt_coex_lut_type {
BT_COEX_TIGHT_LUT = 0,
BT_COEX_LOOSE_LUT,
BT_COEX_TX_DIS_LUT,
BT_COEX_MAX_LUT,
};
#define BT_COEX_LUT_SIZE (12)
#define BT_COEX_CORUN_LUT_SIZE (32)
#define BT_COEX_MULTI_PRIO_LUT_SIZE (2)
#define BT_COEX_BOOST_SIZE (4)
#define BT_REDUCED_TX_POWER_BIT BIT(7)
/**
* struct iwl_bt_coex_cmd - bt coex configuration command
* @flags:&enum iwl_bt_coex_flags
* @lead_time:
* @max_kill:
* @bt3_time_t7_value:
* @kill_ack_msk:
* @kill_cts_msk:
* @bt3_prio_sample_time:
* @bt3_timer_t2_value:
* @bt4_reaction_time:
* @decision_lut[12]:
* @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
* @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk
* @bt_prio_boost: values for PTA boost register
* @bt4_antenna_isolation:
* @bt4_antenna_isolation_thr:
* @bt4_tx_tx_delta_freq_thr:
* @bt4_tx_rx_max_freq0:
* @bt_prio_boost:
* @wifi_tx_prio_boost: SW boost of wifi tx priority
* @wifi_rx_prio_boost: SW boost of wifi rx priority
* @kill_ack_msk:
* @kill_cts_msk:
* @decision_lut:
* @bt4_multiprio_lut:
* @bt4_corun_lut20:
* @bt4_corun_lut40:
* @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk
*
* The structure is used for the BT_COEX command.
*/
struct iwl_bt_coex_cmd {
u8 flags;
u8 lead_time;
__le32 flags;
u8 max_kill;
u8 bt3_time_t7_value;
u8 bt_reduced_tx_power;
u8 reserved[2];
u8 bt4_antenna_isolation;
u8 bt4_antenna_isolation_thr;
u8 bt4_tx_tx_delta_freq_thr;
u8 bt4_tx_rx_max_freq0;
__le32 bt_prio_boost[BT_COEX_BOOST_SIZE];
__le32 wifi_tx_prio_boost;
__le32 wifi_rx_prio_boost;
__le32 kill_ack_msk;
__le32 kill_cts_msk;
u8 bt3_prio_sample_time;
u8 bt3_timer_t2_value;
__le16 bt4_reaction_time;
__le32 decision_lut[BT_COEX_LUT_SIZE];
u8 bt_reduced_tx_power;
u8 reserved;
__le16 valid_bit_msk;
__le32 bt_prio_boost;
u8 reserved2;
u8 wifi_tx_prio_boost;
__le16 wifi_rx_prio_boost;
__le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE];
__le32 bt4_multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE];
__le32 bt4_corun_lut20[BT_COEX_CORUN_LUT_SIZE];
__le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE];
__le32 valid_bit_msk;
} __packed; /* BT_COEX_CMD_API_S_VER_3 */
/**
* struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
* @bt_primary_ci:
* @bt_secondary_ci:
* @co_run_bw_primary:
* @co_run_bw_secondary:
* @primary_ch_phy_id:
* @secondary_ch_phy_id:
*
* Used for BT_COEX_CI command
*/
struct iwl_bt_coex_ci_cmd {
__le64 bt_primary_ci;
__le64 bt_secondary_ci;
u8 co_run_bw_primary;
u8 co_run_bw_secondary;
u8 primary_ch_phy_id;
u8 secondary_ch_phy_id;
} __packed; /* BT_CI_MSG_API_S_VER_1 */
#define BT_MBOX(n_dw, _msg, _pos, _nbits) \
BT_MBOX##n_dw##_##_msg##_POS = (_pos), \
BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS
......@@ -244,23 +285,39 @@ enum iwl_bt_mxbox_dw3 {
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
>> BT_MBOX##_num##_##_field##_POS)
enum iwl_bt_activity_grading {
BT_OFF = 0,
BT_ON_NO_CONNECTION = 1,
BT_LOW_TRAFFIC = 2,
BT_HIGH_TRAFFIC = 3,
};
/**
* struct iwl_bt_coex_profile_notif - notification about BT coex
* @mbox_msg: message from BT to WiFi
* @:bt_status: 0 - off, 1 - on
* @:bt_open_conn: number of BT connections open
* @:bt_traffic_load: load of BT traffic
* @:bt_agg_traffic_load: aggregated load of BT traffic
* @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
* @msg_idx: the index of the message
* @bt_status: 0 - off, 1 - on
* @bt_open_conn: number of BT connections open
* @bt_traffic_load: load of BT traffic
* @bt_agg_traffic_load: aggregated load of BT traffic
* @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
* @primary_ch_lut: LUT used for primary channel
* @secondary_ch_lut: LUT used for secondary channel
* @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
*/
struct iwl_bt_coex_profile_notif {
__le32 mbox_msg[4];
__le32 msg_idx;
u8 bt_status;
u8 bt_open_conn;
u8 bt_traffic_load;
u8 bt_agg_traffic_load;
u8 bt_ci_compliance;
u8 reserved[3];
__le32 primary_ch_lut;
__le32 secondary_ch_lut;
__le32 bt_activity_grading;
} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */
enum iwl_bt_coex_prio_table_event {
......@@ -300,20 +357,4 @@ struct iwl_bt_coex_prio_tbl_cmd {
u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
} __packed;
enum iwl_bt_coex_env_action {
BT_COEX_ENV_CLOSE = 0,
BT_COEX_ENV_OPEN = 1,
}; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */
/**
* struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope
* @action: enum %iwl_bt_coex_env_action
* @type: enum %iwl_bt_coex_prio_table_event
*/
struct iwl_bt_coex_prot_env_cmd {
u8 action; /* 0 = closed, 1 = open */
u8 type; /* 0 .. 15 */
u8 reserved[2];
} __packed;
#endif /* __fw_api_bt_coex_h__ */
......@@ -100,7 +100,12 @@ enum iwl_proto_offloads {
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L 12
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S 4
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 12
#define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L 4
#define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S 2
/**
* struct iwl_proto_offload_cmd_common - ARP/NS offload common part
......@@ -155,6 +160,43 @@ struct iwl_proto_offload_cmd_v2 {
u8 reserved2[3];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
struct iwl_ns_config {
struct in6_addr source_ipv6_addr;
struct in6_addr dest_ipv6_addr;
u8 target_mac_addr[ETH_ALEN];
__le16 reserved;
} __packed; /* NS_OFFLOAD_CONFIG */
struct iwl_targ_addr {
struct in6_addr addr;
__le32 config_num;
} __packed; /* TARGET_IPV6_ADDRESS */
/**
* struct iwl_proto_offload_cmd_v3_small - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @target_ipv6_addr: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_small {
struct iwl_proto_offload_cmd_common common;
__le32 num_valid_ipv6_addrs;
struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S];
struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */
/**
* struct iwl_proto_offload_cmd_v3_large - ARP/NS offload configuration
* @common: common/IPv4 configuration
* @target_ipv6_addr: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_large {
struct iwl_proto_offload_cmd_common common;
__le32 num_valid_ipv6_addrs;
struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L];
struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */
/*
* WOWLAN_PATTERNS
......@@ -293,7 +335,7 @@ enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_status {
struct iwl_wowlan_status_v4 {
__le64 replay_ctr;
__le16 pattern_number;
__le16 non_qos_seq_ctr;
......@@ -308,6 +350,29 @@ struct iwl_wowlan_status {
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
} __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
struct iwl_wowlan_gtk_status {
u8 key_index;
u8 reserved[3];
u8 decrypt_key[16];
u8 tkip_mic_key[8];
struct iwl_wowlan_rsc_tsc_params_cmd rsc;
} __packed;
struct iwl_wowlan_status_v6 {
struct iwl_wowlan_gtk_status gtk;
__le64 replay_ctr;
__le16 pattern_number;
__le16 non_qos_seq_ctr;
__le16 qos_seq_ctr[8];
__le32 wakeup_reasons;
__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_6 */
#define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64
#define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128
#define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048
......
......@@ -170,12 +170,14 @@ struct iwl_mac_data_ap {
* @beacon_tsf: beacon transmit time in TSF
* @bi: beacon interval in TU
* @bi_reciprocal: 2^32 / bi
* @beacon_template: beacon template ID
*/
struct iwl_mac_data_ibss {
__le32 beacon_time;
__le64 beacon_tsf;
__le32 bi;
__le32 bi_reciprocal;
__le32 beacon_template;
} __packed; /* IBSS_MAC_DATA_API_S_VER_1 */
/**
......@@ -372,4 +374,13 @@ static inline u32 iwl_mvm_reciprocal(u32 v)
return 0xFFFFFFFF / v;
}
#define IWL_NONQOS_SEQ_GET 0x1
#define IWL_NONQOS_SEQ_SET 0x2
struct iwl_nonqos_seq_query_cmd {
__le32 get_set_flag;
__le32 mac_id_n_color;
__le16 value;
__le16 reserved;
} __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */
#endif /* __fw_api_mac_h__ */
......@@ -131,6 +131,33 @@ struct iwl_powertable_cmd {
__le32 lprx_rssi_threshold;
} __packed;
/**
* enum iwl_device_power_flags - masks for device power command flags
* @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow. This flag should be
* always set to '1' unless one need to disable actual power down for debug
* purposes.
* @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning
* that power management is disabled. '0' Power management is enabled, one
* of power schemes is applied.
*/
enum iwl_device_power_flags {
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
DEVICE_POWER_FLAGS_CAM_MSK = BIT(13),
};
/**
* struct iwl_device_power_cmd - device wide power command.
* DEVICE_POWER_CMD = 0x77 (command, has simple generic response)
*
* @flags: Power table command flags from DEVICE_POWER_FLAGS_*
*/
struct iwl_device_power_cmd {
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
__le16 flags;
__le16 reserved;
} __packed;
/**
* struct iwl_mac_power_cmd - New power command containing uAPSD support
* MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
......@@ -290,7 +317,7 @@ struct iwl_beacon_filter_cmd {
#define IWL_BF_ESCAPE_TIMER_MIN 0
#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
#define IWL_BA_ESCAPE_TIMER_D3 6
#define IWL_BA_ESCAPE_TIMER_D3 9
#define IWL_BA_ESCAPE_TIMER_MAX 1024
#define IWL_BA_ESCAPE_TIMER_MIN 0
......
......@@ -68,6 +68,7 @@
/*
* These serve as indexes into
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
* TODO: avoid overlap between legacy and HT rates
*/
enum {
IWL_RATE_1M_INDEX = 0,
......@@ -78,18 +79,31 @@ enum {
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
IWL_RATE_6M_INDEX,
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX,
IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX,
IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX,
IWL_RATE_9M_INDEX,
IWL_RATE_12M_INDEX,
IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX,
IWL_RATE_18M_INDEX,
IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX,
IWL_RATE_24M_INDEX,
IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX,
IWL_RATE_36M_INDEX,
IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX,
IWL_RATE_48M_INDEX,
IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX,
IWL_RATE_54M_INDEX,
IWL_RATE_MCS_6_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_MCS_7_INDEX = IWL_RATE_60M_INDEX,
IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX,
IWL_RATE_MCS_8_INDEX,
IWL_RATE_MCS_9_INDEX,
IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX,
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
IWL_RATE_COUNT,
IWL_RATE_COUNT = IWL_LAST_VHT_RATE + 1,
};
#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
......@@ -108,6 +122,7 @@ enum {
IWL_RATE_2M_PLCP = 20,
IWL_RATE_5M_PLCP = 55,
IWL_RATE_11M_PLCP = 110,
IWL_RATE_INVM_PLCP = -1,
};
/*
......@@ -164,6 +179,8 @@ enum {
* which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
*/
#define RATE_HT_MCS_RATE_CODE_MSK 0x7
#define RATE_HT_MCS_NSS_POS 3
#define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS)
/* Bit 10: (1) Use Green Field preamble */
#define RATE_HT_MCS_GF_POS 10
......
......@@ -356,6 +356,7 @@ struct iwl_scan_complete_notif {
/* scan offload */
#define IWL_MAX_SCAN_CHANNELS 40
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
#define IWL_SCAN_MAX_PROFILES 11
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
......@@ -368,6 +369,12 @@ struct iwl_scan_complete_notif {
#define IWL_FULL_SCAN_MULTIPLIER 5
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
enum scan_framework_client {
SCAN_CLIENT_SCHED_SCAN = BIT(0),
SCAN_CLIENT_NETDETECT = BIT(1),
SCAN_CLIENT_ASSET_TRACKING = BIT(2),
};
/**
* struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
* @scan_flags: see enum iwl_scan_flags
......@@ -449,11 +456,12 @@ struct iwl_scan_offload_cfg {
* iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
* @ssid: MAC address to filter out
* @reported_rssi: AP rssi reported to the host
* @client_bitmap: clients ignore this entry - enum scan_framework_client
*/
struct iwl_scan_offload_blacklist {
u8 ssid[ETH_ALEN];
u8 reported_rssi;
u8 reserved;
u8 client_bitmap;
} __packed;
enum iwl_scan_offload_network_type {
......@@ -475,6 +483,7 @@ enum iwl_scan_offload_band_selection {
* @aut_alg: authentication olgorithm to match - bitmap
* @network_type: enum iwl_scan_offload_network_type
* @band_selection: enum iwl_scan_offload_band_selection
* @client_bitmap: clients waiting for match - enum scan_framework_client
*/
struct iwl_scan_offload_profile {
u8 ssid_index;
......@@ -482,7 +491,8 @@ struct iwl_scan_offload_profile {
u8 auth_alg;
u8 network_type;
u8 band_selection;
u8 reserved[3];
u8 client_bitmap;
u8 reserved[2];
} __packed;
/**
......@@ -491,13 +501,18 @@ struct iwl_scan_offload_profile {
* @profiles: profiles to search for match
* @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list
* @match_notify: clients waiting for match found notification
* @pass_match: clients waiting for the results
* @active_clients: active clients bitmap - enum scan_framework_client
*/
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];
u8 match_notify;
u8 pass_match;
u8 active_clients;
u8 reserved[3];
} __packed;
/**
......@@ -560,4 +575,15 @@ struct iwl_scan_offload_complete {
u8 reserved;
} __packed;
/**
* iwl_sched_scan_results - SCAN_OFFLOAD_MATCH_FOUND_NTF_API_S_VER_1
* @ssid_bitmap: SSIDs indexes found in this iteration
* @client_bitmap: clients that are active and wait for this notification
*/
struct iwl_sched_scan_results {
__le16 ssid_bitmap;
u8 client_bitmap;
u8 reserved;
};
#endif
......@@ -247,7 +247,7 @@ struct iwl_mvm_keyinfo {
} __packed;
/**
* struct iwl_mvm_add_sta_cmd - Add / modify a station in the fw's station table
* struct iwl_mvm_add_sta_cmd_v5 - Add/modify a station in the fw's sta 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
......@@ -286,7 +286,7 @@ struct iwl_mvm_keyinfo {
* 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 {
struct iwl_mvm_add_sta_cmd_v5 {
u8 add_modify;
u8 unicast_tx_key_id;
u8 multicast_tx_key_id;
......@@ -312,6 +312,57 @@ struct iwl_mvm_add_sta_cmd {
__le32 tfd_queue_msk;
} __packed; /* ADD_STA_CMD_API_S_VER_5 */
/**
* struct iwl_mvm_add_sta_cmd_v6 - Add / modify a station
* VER_6 of this command is quite similar to VER_5 except
* exclusion of all fields related to the security key installation.
*/
struct iwl_mvm_add_sta_cmd_v6 {
u8 add_modify;
u8 reserved1;
__le16 tid_disable_tx;
__le32 mac_id_n_color;
u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
__le16 reserved2;
u8 sta_id;
u8 modify_mask;
__le16 reserved3;
__le32 station_flags;
__le32 station_flags_msk;
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_6 */
/**
* struct iwl_mvm_add_sta_key_cmd - add/modify sta key
* ( REPLY_ADD_STA_KEY = 0x17 )
* @sta_id: index of station in uCode's station table
* @key_offset: key offset in key storage
* @key_flags: type %iwl_sta_key_flag
* @key: key material data
* @key2: key material data
* @rx_secur_seq_cnt: RX security sequence counter for the key
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
*/
struct iwl_mvm_add_sta_key_cmd {
u8 sta_id;
u8 key_offset;
__le16 key_flags;
u8 key[16];
u8 key2[16];
u8 rx_secur_seq_cnt[16];
u8 tkip_rx_tsc_byte2;
u8 reserved;
__le16 tkip_rx_ttak[5];
} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */
/**
* enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command
* @ADD_STA_SUCCESS: operation was executed successfully
......
......@@ -72,17 +72,17 @@
#include "fw-api-d3.h"
#include "fw-api-bt-coex.h"
/* queue and FIFO numbers by usage */
/* maximal number of Tx queues in any platform */
#define IWL_MVM_MAX_QUEUES 20
/* Tx queue numbers */
enum {
IWL_MVM_OFFCHANNEL_QUEUE = 8,
IWL_MVM_CMD_QUEUE = 9,
IWL_MVM_AUX_QUEUE = 15,
IWL_MVM_FIRST_AGG_QUEUE = 16,
IWL_MVM_NUM_QUEUES = 20,
IWL_MVM_LAST_AGG_QUEUE = IWL_MVM_NUM_QUEUES - 1,
IWL_MVM_CMD_FIFO = 7
};
#define IWL_MVM_CMD_FIFO 7
#define IWL_MVM_STATION_COUNT 16
/* commands */
......@@ -97,6 +97,7 @@ enum {
DBG_CFG = 0x9,
/* station table */
ADD_STA_KEY = 0x17,
ADD_STA = 0x18,
REMOVE_STA = 0x19,
......@@ -114,6 +115,7 @@ enum {
TIME_EVENT_NOTIFICATION = 0x2a,
BINDING_CONTEXT_CMD = 0x2b,
TIME_QUOTA_CMD = 0x2c,
NON_QOS_TX_COUNTER_CMD = 0x2d,
LQ_CMD = 0x4e,
......@@ -130,6 +132,7 @@ enum {
SCAN_OFFLOAD_COMPLETE = 0x6D,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
MATCH_FOUND_NOTIFICATION = 0xd9,
/* Phy */
PHY_CONFIGURATION_CMD = 0x6a,
......@@ -178,6 +181,7 @@ enum {
BT_COEX_PRIO_TABLE = 0xcc,
BT_COEX_PROT_ENV = 0xcd,
BT_PROFILE_NOTIFICATION = 0xce,
BT_COEX_CI = 0x5d,
REPLY_BEACON_FILTERING_CMD = 0xd2,
......
......@@ -199,7 +199,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
*/
for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE)
if (i < 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;
......@@ -243,7 +243,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held(&mvm->mutex);
if (mvm->init_ucode_run)
if (mvm->init_ucode_complete)
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
......@@ -264,6 +264,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
if (ret)
goto error;
/* Read the NVM only at driver load time, no need to do this twice */
if (read_nvm) {
/* Read nvm */
ret = iwl_nvm_init(mvm);
......@@ -273,6 +274,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
}
/* In case we read the NVM from external file, load it to the NIC */
if (iwlwifi_mod_params.nvm_file)
iwl_mvm_load_nvm_to_nic(mvm);
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
WARN_ON(ret);
......@@ -310,7 +315,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
if (!ret)
mvm->init_ucode_run = true;
mvm->init_ucode_complete = true;
goto out;
error:
......@@ -353,8 +358,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
return ret;
/* If we were in RFKILL during module loading, load init ucode now */
if (!mvm->init_ucode_run) {
/*
* If we haven't completed the run of the init ucode during
* module loading, load init ucode now
* (for example, if we were in RFKILL)
*/
if (!mvm->init_ucode_complete) {
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);
......@@ -424,6 +433,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
ret = iwl_mvm_power_update_device_mode(mvm);
if (ret)
goto error;
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
......
......@@ -80,7 +80,7 @@ struct iwl_mvm_mac_iface_iterator_data {
struct ieee80211_vif *vif;
unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_FIRST_AGG_QUEUE)];
unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_MAX_QUEUES)];
enum iwl_tsf_id preferred_tsf;
bool found_vif;
};
......@@ -218,7 +218,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
.preferred_tsf = NUM_TSF_IDS,
.used_hw_queues = {
BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
BIT(IWL_MVM_AUX_QUEUE) |
BIT(mvm->aux_queue) |
BIT(IWL_MVM_CMD_QUEUE)
},
.found_vif = false,
......@@ -242,9 +242,17 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
* that we should share it with another interface.
*/
/* Currently, MAC ID 0 should be used only for the managed vif */
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
/* Currently, MAC ID 0 should be used only for the managed/IBSS vif */
switch (vif->type) {
case NL80211_IFTYPE_ADHOC:
break;
case NL80211_IFTYPE_STATION:
if (!vif->p2p)
break;
/* fall through */
default:
__clear_bit(0, data.available_mac_ids);
}
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
......@@ -302,9 +310,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
/* Find available queues, and allocate them to the ACs */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
u8 queue = find_first_zero_bit(data.used_hw_queues,
IWL_MVM_FIRST_AGG_QUEUE);
mvm->first_agg_queue);
if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
if (queue >= mvm->first_agg_queue) {
IWL_ERR(mvm, "Failed to allocate queue\n");
ret = -EIO;
goto exit_fail;
......@@ -317,9 +325,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
/* Allocate the CAB queue for softAP and GO interfaces */
if (vif->type == NL80211_IFTYPE_AP) {
u8 queue = find_first_zero_bit(data.used_hw_queues,
IWL_MVM_FIRST_AGG_QUEUE);
mvm->first_agg_queue);
if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
if (queue >= mvm->first_agg_queue) {
IWL_ERR(mvm, "Failed to allocate cab queue\n");
ret = -EIO;
goto exit_fail;
......@@ -559,8 +567,12 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
/* Don't use cts to self as the fw doesn't support it currently. */
if (vif->bss_conf.use_cts_prot)
if (vif->bss_conf.use_cts_prot) {
cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
cmd->protection_flags |=
cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN);
}
/*
* I think that we should enable these 2 flags regardless the HT PROT
......@@ -712,6 +724,31 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 action)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mac_ctx_cmd cmd = {};
WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
MAC_FILTER_IN_PROBE_REQUEST);
/* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
cmd.ibss.bi_reciprocal =
cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
/* TODO: Assumes that the beacon id == mac context id */
cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id);
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
struct iwl_mvm_go_iterator_data {
bool go_active;
};
......@@ -721,7 +758,8 @@ static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
struct iwl_mvm_go_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (vif->type == NL80211_IFTYPE_AP && vif->p2p && mvmvif->ap_active)
if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
mvmvif->ap_ibss_active)
data->go_active = true;
}
......@@ -833,6 +871,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
/* Set up TX beacon command fields */
if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd,
beacon->data,
beacon_skb_len);
......@@ -848,14 +887,15 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
return iwl_mvm_send_cmd(mvm, &cmd);
}
/* The beacon template for the AP/GO context has changed and needs update */
/* The beacon template for the AP/GO/IBSS has changed and needs update */
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct sk_buff *beacon;
int ret;
WARN_ON(vif->type != NL80211_IFTYPE_AP);
WARN_ON(vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC);
beacon = ieee80211_beacon_get(mvm->hw, vif);
if (!beacon)
......@@ -1018,6 +1058,8 @@ static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
case NL80211_IFTYPE_P2P_DEVICE:
return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
case NL80211_IFTYPE_ADHOC:
return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action);
default:
break;
}
......@@ -1038,6 +1080,9 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;
/* will only do anything at resume from D3 time */
iwl_mvm_set_last_nonqos_seq(mvm, vif);
mvmvif->uploaded = true;
return 0;
}
......
This diff is collapsed.
......@@ -162,6 +162,7 @@ enum iwl_power_scheme {
struct iwl_mvm_power_ops {
int (*power_update_mode)(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int (*power_update_device_mode)(struct iwl_mvm *mvm);
int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
......@@ -241,12 +242,18 @@ enum iwl_mvm_smps_type_request {
* @last_beacon_signal: last beacon rssi signal in dbm
* @ave_beacon_signal: average beacon signal
* @last_cqm_event: rssi of the last cqm event
* @bt_coex_min_thold: minimum threshold for BT coex
* @bt_coex_max_thold: maximum threshold for BT coex
* @last_bt_coex_event: rssi of the last BT coex event
*/
struct iwl_mvm_vif_bf_data {
bool bf_enabled;
bool ba_enabled;
s8 ave_beacon_signal;
s8 last_cqm_event;
s8 bt_coex_min_thold;
s8 bt_coex_max_thold;
s8 last_bt_coex_event;
};
/**
......@@ -255,7 +262,7 @@ struct iwl_mvm_vif_bf_data {
* @color: to solve races upon MAC addition and removal
* @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
* @uploaded: indicates the MAC context has been added to the device
* @ap_active: indicates that ap context is configured, and that the interface
* @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
* should get quota etc.
* @monitor_active: indicates that monitor context is configured, and that the
* interface should get quota etc.
......@@ -272,7 +279,7 @@ struct iwl_mvm_vif {
u8 ap_sta_id;
bool uploaded;
bool ap_active;
bool ap_ibss_active;
bool monitor_active;
struct iwl_mvm_vif_bf_data bf_data;
......@@ -306,6 +313,9 @@ struct iwl_mvm_vif {
int tx_key_idx;
bool seqno_valid;
u16 seqno;
#if IS_ENABLED(CONFIG_IPV6)
/* IPv6 addresses for WoWLAN */
struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
......@@ -333,6 +343,7 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
enum iwl_scan_status {
IWL_MVM_SCAN_NONE,
IWL_MVM_SCAN_OS,
IWL_MVM_SCAN_SCHED,
};
/**
......@@ -434,7 +445,7 @@ struct iwl_mvm {
enum iwl_ucode_type cur_ucode;
bool ucode_loaded;
bool init_ucode_run;
bool init_ucode_complete;
u32 error_event_table;
u32 log_event_table;
......@@ -470,6 +481,9 @@ struct iwl_mvm {
enum iwl_scan_status scan_status;
struct iwl_scan_cmd *scan_cmd;
/* rx chain antennas set through debugfs for the scan command */
u8 scan_rx_ant;
/* Internal station */
struct iwl_mvm_int_sta aux_sta;
......@@ -479,7 +493,8 @@ struct iwl_mvm {
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *debugfs_dir;
u32 dbgfs_sram_offset, dbgfs_sram_len;
bool prevent_power_down_d3;
bool disable_power_off;
bool disable_power_off_d3;
#endif
struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX];
......@@ -523,12 +538,23 @@ struct iwl_mvm {
/* BT-Coex */
u8 bt_kill_msk;
struct iwl_bt_coex_profile_notif last_bt_notif;
struct iwl_bt_coex_ci_cmd last_bt_ci_cmd;
/* Thermal Throttling and CTkill */
struct iwl_mvm_tt_mgmt thermal_throttle;
s32 temperature; /* Celsius */
const struct iwl_mvm_power_ops *pm_ops;
#ifdef CONFIG_NL80211_TESTMODE
u32 noa_duration;
struct ieee80211_vif *noa_vif;
#endif
/* Tx queues */
u8 aux_queue;
u8 first_agg_queue;
u8 last_agg_queue;
};
/* Extract MVM priv from op_mode and _hw */
......@@ -570,6 +596,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm);
/* Utils */
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
enum ieee80211_band band);
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
enum ieee80211_band band,
struct ieee80211_tx_rate *r);
u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
......@@ -608,6 +637,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
/* NVM */
int iwl_nvm_init(struct iwl_mvm *mvm);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
int iwl_mvm_up(struct iwl_mvm *mvm);
int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm);
......@@ -682,6 +712,23 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
void iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
/* Scheduled scan */
int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies);
int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
......@@ -720,6 +767,13 @@ static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
return mvm->pm_ops->power_disable(mvm, vif);
}
static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm)
{
if (mvm->pm_ops->power_update_device_mode)
return mvm->pm_ops->power_update_device_mode(mvm);
return 0;
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
......@@ -745,6 +799,15 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int idx);
extern const struct file_operations iwl_dbgfs_d3_test_ops;
#ifdef CONFIG_PM_SLEEP
void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
#else
static inline void
iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
}
#endif
/* BT Coex */
int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
......@@ -754,7 +817,20 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd);
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event rssi_event);
void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm);
u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
enum iwl_bt_kill_msk {
BT_KILL_MSK_DEFAULT,
BT_KILL_MSK_SCO_HID_A2DP,
BT_KILL_MSK_REDUCED_TXPOW,
BT_KILL_MSK_MAX,
};
extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX];
extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX];
/* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS
......
......@@ -77,7 +77,7 @@ static const int nvm_to_read[] = {
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
#define IWL_MAX_NVM_SECTION_SIZE 6000
#define IWL_MAX_NVM_SECTION_SIZE 7000
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
......@@ -259,6 +259,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
#define MAX_NVM_FILE_LEN 16384
/*
* Reads external NVM from a file into mvm->nvm_sections
*
* HOW TO CREATE THE NVM FILE FORMAT:
* ------------------------------
* 1. create hex file, format:
......@@ -277,20 +279,23 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
*
* 4. save as "iNVM_xxx.bin" under /lib/firmware
*/
static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm)
static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
{
int ret, section_id, section_size;
int ret, section_size;
u16 section_id;
const struct firmware *fw_entry;
const struct {
__le16 word1;
__le16 word2;
u8 data[];
} *file_sec;
const u8 *eof;
const u8 *eof, *temp;
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
/*
* Obtain NVM image via request_firmware. Since we already used
* request_firmware_nowait() for the firmware binary load and only
......@@ -362,12 +367,18 @@ static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm)
break;
}
ret = iwl_nvm_write_section(mvm, section_id, file_sec->data,
section_size);
if (ret < 0) {
IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret);
temp = kmemdup(file_sec->data, section_size, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
break;
}
if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) {
IWL_ERR(mvm, "Invalid NVM section ID\n");
ret = -EINVAL;
break;
}
mvm->nvm_sections[section_id].data = temp;
mvm->nvm_sections[section_id].length = section_size;
/* advance to the next section */
file_sec = (void *)(file_sec->data + section_size);
......@@ -377,6 +388,28 @@ static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm)
return ret;
}
/* Loads the NVM data stored in mvm->nvm_sections into the NIC */
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
{
int i, ret;
u16 section_id;
struct iwl_nvm_section *sections = mvm->nvm_sections;
IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n");
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
section_id = nvm_to_read[i];
ret = iwl_nvm_write_section(mvm, section_id,
sections[section_id].data,
sections[section_id].length);
if (ret < 0) {
IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret);
break;
}
}
return ret;
}
int iwl_nvm_init(struct iwl_mvm *mvm)
{
int ret, i, section;
......@@ -385,11 +418,10 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* load external NVM if configured */
if (iwlwifi_mod_params.nvm_file) {
/* move to External NVM flow */
ret = iwl_mvm_load_external_nvm(mvm);
ret = iwl_mvm_read_external_nvm(mvm);
if (ret)
return ret;
}
} else {
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
......@@ -415,6 +447,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
kfree(nvm_buffer);
if (ret < 0)
return ret;
}
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
if (!mvm->nvm_data)
......
......@@ -224,6 +224,10 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
iwl_mvm_rx_scan_offload_complete_notif, false),
RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
false),
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
......@@ -249,6 +253,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(TIME_EVENT_NOTIFICATION),
CMD(BINDING_CONTEXT_CMD),
CMD(TIME_QUOTA_CMD),
CMD(NON_QOS_TX_COUNTER_CMD),
CMD(RADIO_VERSION_NOTIFICATION),
CMD(SCAN_REQUEST_CMD),
CMD(SCAN_ABORT_CMD),
......@@ -260,10 +265,12 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(CALIB_RES_NOTIF_PHY_DB),
CMD(SET_CALIB_DEFAULT_CMD),
CMD(CALIBRATION_COMPLETE_NOTIFICATION),
CMD(ADD_STA_KEY),
CMD(ADD_STA),
CMD(REMOVE_STA),
CMD(LQ_CMD),
CMD(SCAN_OFFLOAD_CONFIG_CMD),
CMD(MATCH_FOUND_NOTIFICATION),
CMD(SCAN_OFFLOAD_REQUEST_CMD),
CMD(SCAN_OFFLOAD_ABORT_CMD),
CMD(SCAN_OFFLOAD_COMPLETE),
......@@ -303,6 +310,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(REPLY_BEACON_FILTERING_CMD),
CMD(REPLY_THERMAL_MNG_BACKOFF),
CMD(MAC_PM_POWER_TABLE),
CMD(BT_COEX_CI),
};
#undef CMD
......@@ -344,6 +352,14 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
mvm->aux_queue = 15;
mvm->first_agg_queue = 16;
mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1;
if (mvm->cfg->base_params->num_of_queues == 16) {
mvm->aux_queue = 11;
mvm->first_agg_queue = 12;
}
mutex_init(&mvm->mutex);
spin_lock_init(&mvm->async_handlers_lock);
INIT_LIST_HEAD(&mvm->time_event_list);
......@@ -401,12 +417,19 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
IWL_INFO(mvm, "Detected %s, REV=0x%X\n",
mvm->cfg->name, mvm->trans->hw_rev);
iwl_mvm_tt_initialize(mvm);
/*
* If the NVM exists in an external file,
* there is no need to unnecessarily power up the NIC at driver load
*/
if (iwlwifi_mod_params.nvm_file) {
iwl_nvm_init(mvm);
} else {
err = iwl_trans_start_hw(mvm->trans);
if (err)
goto out_free;
iwl_mvm_tt_initialize(mvm);
mutex_lock(&mvm->mutex);
err = iwl_run_init_mvm_ucode(mvm, true);
mutex_unlock(&mvm->mutex);
......@@ -419,6 +442,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
/* Stop the hw after the ALIVE and NVM has been read */
if (!iwlmvm_mod_params.init_dbg)
iwl_trans_stop_hw(mvm->trans, false);
}
scan_size = sizeof(struct iwl_scan_cmd) +
mvm->fw->ucode_capa.max_probe_length +
......@@ -449,6 +473,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
out_free:
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
if (!iwlwifi_mod_params.nvm_file)
iwl_trans_stop_hw(trans, true);
ieee80211_free_hw(mvm->hw);
return NULL;
......@@ -715,6 +740,9 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
case IWL_MVM_SCAN_OS:
ieee80211_scan_completed(mvm->hw, true);
break;
case IWL_MVM_SCAN_SCHED:
ieee80211_sched_scan_stopped(mvm->hw);
break;
}
if (mvm->restart_fw > 0)
......
......@@ -297,11 +297,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
}
if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
cmd->rx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
cmd->tx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
BIT(IEEE80211_AC_VI) |
BIT(IEEE80211_AC_BE) |
......@@ -316,10 +311,31 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
}
cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags &
cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
cmd->rx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
cmd->tx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
} else {
cmd->rx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
cmd->tx_data_timeout_uapsd =
cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
}
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
cmd->heavy_tx_thld_packets =
IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
cmd->heavy_rx_thld_packets =
IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
} else {
cmd->heavy_tx_thld_packets =
IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
cmd->heavy_rx_thld_packets =
IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
}
cmd->heavy_tx_thld_percentage =
IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
cmd->heavy_rx_thld_percentage =
......@@ -427,6 +443,32 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
sizeof(cmd), &cmd);
}
static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
{
struct iwl_device_power_cmd cmd = {
.flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
};
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
return 0;
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 :
mvm->disable_power_off)
cmd.flags &=
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
#endif
IWL_DEBUG_POWER(mvm,
"Sending device power command with flags = 0x%X\n",
cmd.flags);
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd),
&cmd);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, char *buf,
......@@ -437,6 +479,7 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
(cmd.flags &
cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
......@@ -606,6 +649,7 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
const struct iwl_mvm_power_ops pm_mac_ops = {
.power_update_mode = iwl_mvm_power_mac_update_mode,
.power_update_device_mode = iwl_mvm_power_update_device,
.power_disable = iwl_mvm_power_mac_disable,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
......
......@@ -110,7 +110,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_AP:
if (mvmvif->ap_active)
case NL80211_IFTYPE_ADHOC:
if (mvmvif->ap_ibss_active)
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_MONITOR:
......@@ -119,16 +120,45 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
break;
case NL80211_IFTYPE_P2P_DEVICE:
break;
case NL80211_IFTYPE_ADHOC:
if (vif->bss_conf.ibss_joined)
data->n_interfaces[id]++;
break;
default:
WARN_ON_ONCE(1);
break;
}
}
static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
struct iwl_time_quota_cmd *cmd)
{
#ifdef CONFIG_NL80211_TESTMODE
struct iwl_mvm_vif *mvmvif;
int i, phy_id = -1, beacon_int = 0;
if (!mvm->noa_duration || !mvm->noa_vif)
return;
mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif);
if (!mvmvif->ap_ibss_active)
return;
phy_id = mvmvif->phy_ctxt->id;
beacon_int = mvm->noa_vif->bss_conf.beacon_int;
for (i = 0; i < MAX_BINDINGS; i++) {
u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color);
u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS;
u32 quota = le32_to_cpu(cmd->quotas[i].quota);
if (id != phy_id)
continue;
quota *= (beacon_int - mvm->noa_duration);
quota /= beacon_int;
cmd->quotas[i].quota = cpu_to_le32(quota);
}
#endif
}
int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
{
struct iwl_time_quota_cmd cmd = {};
......@@ -196,6 +226,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
/* Give the remainder of the session to the first binding */
le32_add_cpu(&cmd.quotas[0].quota, quota_rem);
iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,
sizeof(cmd), &cmd);
if (ret)
......
This diff is collapsed.
......@@ -36,8 +36,10 @@
struct iwl_rs_rate_info {
u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
u8 plcp_vht_siso;
u8 plcp_vht_mimo2;
u8 prev_rs; /* previous rate used in rs algo */
u8 next_rs; /* next rate used in rs algo */
};
......@@ -83,35 +85,52 @@ enum {
#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
/* uCode API values for OFDM high-throughput (HT) bit rates */
/* uCode API values for HT/VHT bit rates */
enum {
IWL_RATE_SISO_6M_PLCP = 0,
IWL_RATE_SISO_12M_PLCP = 1,
IWL_RATE_SISO_18M_PLCP = 2,
IWL_RATE_SISO_24M_PLCP = 3,
IWL_RATE_SISO_36M_PLCP = 4,
IWL_RATE_SISO_48M_PLCP = 5,
IWL_RATE_SISO_54M_PLCP = 6,
IWL_RATE_SISO_60M_PLCP = 7,
IWL_RATE_MIMO2_6M_PLCP = 0x8,
IWL_RATE_MIMO2_12M_PLCP = 0x9,
IWL_RATE_MIMO2_18M_PLCP = 0xa,
IWL_RATE_MIMO2_24M_PLCP = 0xb,
IWL_RATE_MIMO2_36M_PLCP = 0xc,
IWL_RATE_MIMO2_48M_PLCP = 0xd,
IWL_RATE_MIMO2_54M_PLCP = 0xe,
IWL_RATE_MIMO2_60M_PLCP = 0xf,
IWL_RATE_MIMO3_6M_PLCP = 0x10,
IWL_RATE_MIMO3_12M_PLCP = 0x11,
IWL_RATE_MIMO3_18M_PLCP = 0x12,
IWL_RATE_MIMO3_24M_PLCP = 0x13,
IWL_RATE_MIMO3_36M_PLCP = 0x14,
IWL_RATE_MIMO3_48M_PLCP = 0x15,
IWL_RATE_MIMO3_54M_PLCP = 0x16,
IWL_RATE_MIMO3_60M_PLCP = 0x17,
IWL_RATE_SISO_INVM_PLCP,
IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
IWL_RATE_HT_SISO_MCS_0_PLCP = 0,
IWL_RATE_HT_SISO_MCS_1_PLCP = 1,
IWL_RATE_HT_SISO_MCS_2_PLCP = 2,
IWL_RATE_HT_SISO_MCS_3_PLCP = 3,
IWL_RATE_HT_SISO_MCS_4_PLCP = 4,
IWL_RATE_HT_SISO_MCS_5_PLCP = 5,
IWL_RATE_HT_SISO_MCS_6_PLCP = 6,
IWL_RATE_HT_SISO_MCS_7_PLCP = 7,
IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8,
IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9,
IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA,
IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB,
IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC,
IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD,
IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE,
IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF,
IWL_RATE_VHT_SISO_MCS_0_PLCP = 0,
IWL_RATE_VHT_SISO_MCS_1_PLCP = 1,
IWL_RATE_VHT_SISO_MCS_2_PLCP = 2,
IWL_RATE_VHT_SISO_MCS_3_PLCP = 3,
IWL_RATE_VHT_SISO_MCS_4_PLCP = 4,
IWL_RATE_VHT_SISO_MCS_5_PLCP = 5,
IWL_RATE_VHT_SISO_MCS_6_PLCP = 6,
IWL_RATE_VHT_SISO_MCS_7_PLCP = 7,
IWL_RATE_VHT_SISO_MCS_8_PLCP = 8,
IWL_RATE_VHT_SISO_MCS_9_PLCP = 9,
IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10,
IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11,
IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12,
IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13,
IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14,
IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15,
IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16,
IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17,
IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18,
IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19,
IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
};
#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
......@@ -139,25 +158,33 @@ enum {
#define IWL_RATE_DECREASE_TH 1920 /* 15% */
/* possible actions when in legacy mode */
#define IWL_LEGACY_SWITCH_ANTENNA1 0
#define IWL_LEGACY_SWITCH_ANTENNA2 1
#define IWL_LEGACY_SWITCH_SISO 2
#define IWL_LEGACY_SWITCH_MIMO2 3
enum {
IWL_LEGACY_SWITCH_ANTENNA,
IWL_LEGACY_SWITCH_SISO,
IWL_LEGACY_SWITCH_MIMO2,
IWL_LEGACY_FIRST_ACTION = IWL_LEGACY_SWITCH_ANTENNA,
IWL_LEGACY_LAST_ACTION = IWL_LEGACY_SWITCH_MIMO2,
};
/* possible actions when in siso mode */
#define IWL_SISO_SWITCH_ANTENNA1 0
#define IWL_SISO_SWITCH_ANTENNA2 1
#define IWL_SISO_SWITCH_MIMO2 2
#define IWL_SISO_SWITCH_GI 3
enum {
IWL_SISO_SWITCH_ANTENNA,
IWL_SISO_SWITCH_MIMO2,
IWL_SISO_SWITCH_GI,
IWL_SISO_FIRST_ACTION = IWL_SISO_SWITCH_ANTENNA,
IWL_SISO_LAST_ACTION = IWL_SISO_SWITCH_GI,
};
/* possible actions when in mimo mode */
#define IWL_MIMO2_SWITCH_ANTENNA1 0
#define IWL_MIMO2_SWITCH_ANTENNA2 1
#define IWL_MIMO2_SWITCH_SISO_A 2
#define IWL_MIMO2_SWITCH_SISO_B 3
#define IWL_MIMO2_SWITCH_GI 4
enum {
IWL_MIMO2_SWITCH_SISO_A,
IWL_MIMO2_SWITCH_SISO_B,
IWL_MIMO2_SWITCH_GI,
IWL_MIMO2_FIRST_ACTION = IWL_MIMO2_SWITCH_SISO_A,
IWL_MIMO2_LAST_ACTION = IWL_MIMO2_SWITCH_GI,
};
#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
#define IWL_MAX_SEARCH IWL_MIMO2_LAST_ACTION
#define IWL_ACTION_LIMIT 3 /* # possible actions */
......@@ -188,20 +215,31 @@ enum {
enum iwl_table_type {
LQ_NONE,
LQ_G, /* legacy types */
LQ_A,
LQ_SISO, /* high-throughput types */
LQ_MIMO2,
LQ_LEGACY_G, /* legacy types */
LQ_LEGACY_A,
LQ_HT_SISO, /* HT types */
LQ_HT_MIMO2,
LQ_VHT_SISO, /* VHT types */
LQ_VHT_MIMO2,
LQ_MAX,
};
#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
#define is_siso(tbl) ((tbl) == LQ_SISO)
#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
#define is_mimo(tbl) is_mimo2(tbl)
#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
#define is_a_band(tbl) ((tbl) == LQ_A)
#define is_g_and(tbl) ((tbl) == LQ_G)
#define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A))
#define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO)
#define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2)
#define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO)
#define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2)
#define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl))
#define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl))
#define is_mimo(tbl) (is_mimo2(tbl))
#define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl))
#define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl))
#define is_a_band(tbl) ((tbl) == LQ_LEGACY_A)
#define is_g_band(tbl) ((tbl) == LQ_LEGACY_G)
#define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20)
#define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40)
#define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80)
#define IWL_MAX_MCS_DISPLAY_SIZE 12
......@@ -232,7 +270,7 @@ struct iwl_scale_tbl_info {
enum iwl_table_type lq_type;
u8 ant_type;
u8 is_SGI; /* 1 = short guard interval */
u8 is_ht40; /* 1 = 40 MHz channel width */
u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
u8 max_search; /* maximun number of tables we can search */
s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
......@@ -262,7 +300,7 @@ struct iwl_lq_sta {
u64 flush_timer; /* time staying in mode before new search */
u8 action_counter; /* # mode-switch actions tried */
u8 is_green;
bool is_vht;
enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
......
......@@ -422,6 +422,27 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
mvmvif->bf_data.ave_beacon_signal = sig;
/* BT Coex */
if (mvmvif->bf_data.bt_coex_min_thold !=
mvmvif->bf_data.bt_coex_max_thold) {
last_event = mvmvif->bf_data.last_bt_coex_event;
if (sig > mvmvif->bf_data.bt_coex_max_thold &&
(last_event <= mvmvif->bf_data.bt_coex_min_thold ||
last_event == 0)) {
mvmvif->bf_data.last_bt_coex_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n",
sig);
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH);
} else if (sig < mvmvif->bf_data.bt_coex_min_thold &&
(last_event >= mvmvif->bf_data.bt_coex_max_thold ||
last_event == 0)) {
mvmvif->bf_data.last_bt_coex_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n",
sig);
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW);
}
}
if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
return;
......
This diff is collapsed.
This diff is collapsed.
......@@ -293,10 +293,6 @@ struct iwl_mvm_sta {
struct iwl_lq_sta lq_sta;
struct ieee80211_vif *vif;
#ifdef CONFIG_PM_SLEEP
u16 last_seq_ctl;
#endif
/* Temporary, until the new TLC will control the Tx protection */
s8 tx_protection;
bool tt_tx_protection;
......
/******************************************************************************
*
* 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) 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 COPYING.
*
* 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) 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 __IWL_MVM_TESTMODE_H__
#define __IWL_MVM_TESTMODE_H__
/**
* enum iwl_mvm_testmode_attrs - testmode attributes inside NL80211_ATTR_TESTDATA
* @IWL_MVM_TM_ATTR_UNSPEC: (invalid attribute)
* @IWL_MVM_TM_ATTR_CMD: sub command, see &enum iwl_mvm_testmode_commands (u32)
* @IWL_MVM_TM_ATTR_NOA_DURATION: requested NoA duration (u32)
* @IWL_MVM_TM_ATTR_BEACON_FILTER_STATE: beacon filter state (0 or 1, u32)
*/
enum iwl_mvm_testmode_attrs {
IWL_MVM_TM_ATTR_UNSPEC,
IWL_MVM_TM_ATTR_CMD,
IWL_MVM_TM_ATTR_NOA_DURATION,
IWL_MVM_TM_ATTR_BEACON_FILTER_STATE,
/* keep last */
NUM_IWL_MVM_TM_ATTRS,
IWL_MVM_TM_ATTR_MAX = NUM_IWL_MVM_TM_ATTRS - 1,
};
/**
* enum iwl_mvm_testmode_commands - MVM testmode commands
* @IWL_MVM_TM_CMD_SET_NOA: set NoA on GO vif for testing
* @IWL_MVM_TM_CMD_SET_BEACON_FILTER: turn beacon filtering off/on
*/
enum iwl_mvm_testmode_commands {
IWL_MVM_TM_CMD_SET_NOA,
IWL_MVM_TM_CMD_SET_BEACON_FILTER,
};
#endif /* __IWL_MVM_TESTMODE_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment